xaizek / hstr (License: Apachev2) (since 2018-12-07)
Bash and Zsh shell history suggest box - easily view, navigate, search and manage your command history.
Commit 9b1de77d8c0091da70c38c4f75fbaf78152614c4

Fixed #38 by a generic function to print pattern AND fixed #39 by using dynamic blacklist lng.
Author: Martin Dvorak
Author date (UTC): 2014-01-25 07:52
Committer name: Martin Dvorak
Committer date (UTC): 2014-01-25 07:52
Parent(s): c6a796cd94b2c96f5259e613c582b1a80eadd0c2
Signing key:
Tree: d6c649808b364b9687f652f11d119aba436261d2
File Lines added Lines deleted
man/hh.1 4 1
src/hstr.c 56 42
src/hstr_utils.c 13 0
src/include/hstr_utils.h 1 0
File man/hh.1 changed (mode: 100644) (index c749644..c1ce877)
... ... Type to filter shell history.
23 23 \fBCtrl\-t\fR \fBCtrl\-t\fR
24 24 Toggle case sensitive search. Toggle case sensitive search.
25 25 .TP .TP
26 \fBCtrl\-h\fR
26 \fBCtrl\-/\fR
27 27 Toggle history as provided by shell vs. ranked history ordered by the number of occurences, length and timestamp. Toggle history as provided by shell vs. ranked history ordered by the number of occurences, length and timestamp.
28 .TP
29 \fBCtrl\-l\fR
30 Make search pattern lowercase or uppercase.
28 31 .TP .TP
29 32 \fBCtrl\-r\fR, \fBUP\fR arrow, \fBDOWN\fR arrow \fBCtrl\-r\fR, \fBUP\fR arrow, \fBDOWN\fR arrow
30 33 Navigate in the history list. Navigate in the history list.
File src/hstr.c changed (mode: 100644) (index 7175f82..05691c4)
38 38 #define K_CTRL_E 5 #define K_CTRL_E 5
39 39 #define K_CTRL_G 7 #define K_CTRL_G 7
40 40 #define K_CTRL_H 8 #define K_CTRL_H 8
41 #define K_CTRL_L 12
41 42 #define K_CTRL_R 18 #define K_CTRL_R 18
42 43 #define K_CTRL_T 20 #define K_CTRL_T 20
43 44 #define K_CTRL_U 21 #define K_CTRL_U 21
45 #define K_CTRL_W 23
44 46 #define K_CTRL_X 24 #define K_CTRL_X 24
45 47 #define K_CTRL_Z 26 #define K_CTRL_Z 26
46 48
49 #define K_CTRL_SLASH 31
50
47 51 #define K_ESC 27 #define K_ESC 27
48 52 #define K_TAB 9 #define K_TAB 9
49 53 #define K_BACKSPACE 127 #define K_BACKSPACE 127
 
... ... void print_cmd_deleted_label(char *cmd, int occurences)
116 120 // make this status row // make this status row
117 121 void print_history_label(HistoryItems *history) void print_history_label(HistoryItems *history)
118 122 { {
119 sprintf(screenLine, "- HISTORY - case:%s (C-t) - order:%s (C-h) - %d/%d ",
123 sprintf(screenLine, "- HISTORY - case:%s (C-t) - order:%s (C-/) - %d/%d ",
120 124 (caseSensitive?"sensitive":"insensitive"), (caseSensitive?"sensitive":"insensitive"),
121 125 (defaultOrder?"history":"ranking"), (defaultOrder?"history":"ranking"),
122 126 history->count, history->count,
 
... ... void print_history_label(HistoryItems *history)
137 141 refresh(); refresh();
138 142 } }
139 143
144 void print_pattern(char *pattern, int y, int x) {
145 color_attr_on(A_BOLD);
146 mvprintw(y, x, "%s", pattern);
147 color_attr_off(A_BOLD);
148 clrtoeol();
149 }
150
140 151 unsigned get_max_history_items() unsigned get_max_history_items()
141 152 { {
142 153 return (getmaxy(stdscr)-Y_OFFSET_ITEMS); return (getmaxy(stdscr)-Y_OFFSET_ITEMS);
 
... ... void signal_callback_handler_ctrl_c(int signum)
314 325 } }
315 326 } }
316 327
317 void selection_loop(HistoryItems *history)
328 void loop_to_select(HistoryItems *history)
318 329 { {
319 330 signal(SIGINT, signal_callback_handler_ctrl_c); signal(SIGINT, signal_callback_handler_ctrl_c);
320 331
 
... ... void selection_loop(HistoryItems *history)
331 342
332 343 color_attr_off(COLOR_PAIR(1)); color_attr_off(COLOR_PAIR(1));
333 344
334 bool done=FALSE, skip=TRUE, executeResult=FALSE;
345 bool done=FALSE, skip=TRUE, executeResult=FALSE, lowercase=TRUE;
335 346 int basex=print_prompt(stdscr); int basex=print_prompt(stdscr);
336 347 int x=basex, y=1, c, cursorX=0, cursorY=0, maxHistoryItems, deleteOccurences; int x=basex, y=1, c, cursorX=0, cursorY=0, maxHistoryItems, deleteOccurences;
337 348 int width=getmaxx(stdscr); int width=getmaxx(stdscr);
338 349 int selectionCursorPosition=SELECTION_CURSOR_IN_PROMPT; int selectionCursorPosition=SELECTION_CURSOR_IN_PROMPT;
339 350 int previousSelectionCursorPosition=SELECTION_CURSOR_IN_PROMPT; int previousSelectionCursorPosition=SELECTION_CURSOR_IN_PROMPT;
340 351 char *result="", *msg, *delete; char *result="", *msg, *delete;
341 char prefix[SELECTION_PREFIX_MAX_LNG];
342 prefix[0]=0;
343 strcpy(prefix, cmdline);
352 char pattern[SELECTION_PREFIX_MAX_LNG];
353 pattern[0]=0;
354 strcpy(pattern, cmdline);
344 355 while (!done) { while (!done) {
345 356 maxHistoryItems=get_max_history_items(stdscr); maxHistoryItems=get_max_history_items(stdscr);
346 357
347 358 if(!skip) { if(!skip) {
348 359 c = wgetch(stdscr); c = wgetch(stdscr);
349 360 } else { } else {
350 if(strlen(prefix)>0) {
361 if(strlen(pattern)>0) {
351 362 color_attr_on(A_BOLD); color_attr_on(A_BOLD);
352 mvprintw(y, basex, "%s", prefix);
363 mvprintw(y, basex, "%s", pattern);
353 364 color_attr_off(A_BOLD); color_attr_off(A_BOLD);
354 365 cursorX=getcurx(stdscr); cursorX=getcurx(stdscr);
355 366 cursorY=getcury(stdscr); cursorY=getcury(stdscr);
356 result=print_selection(maxHistoryItems, prefix, history);
367 result=print_selection(maxHistoryItems, pattern, history);
357 368 move(cursorY, cursorX); move(cursorY, cursorX);
358 369 } }
359 370 skip=FALSE; skip=FALSE;
 
... ... void selection_loop(HistoryItems *history)
368 379 strcpy(msg,delete); strcpy(msg,delete);
369 380 selection_remove(delete, history); selection_remove(delete, history);
370 381 deleteOccurences=history_mgmt_remove(delete); deleteOccurences=history_mgmt_remove(delete);
371 result=print_selection(maxHistoryItems, prefix, history);
382 result=print_selection(maxHistoryItems, pattern, history);
372 383 print_cmd_deleted_label(msg, deleteOccurences); print_cmd_deleted_label(msg, deleteOccurences);
373 move(y, basex+strlen(prefix));
384 move(y, basex+strlen(pattern));
374 385 } }
375 386 print_history_label(history); print_history_label(history);
376 387 break; break;
377 388 case K_CTRL_T: case K_CTRL_T:
378 389 caseSensitive=!caseSensitive; caseSensitive=!caseSensitive;
379 result=print_selection(maxHistoryItems, prefix, history);
380 // TODO render selected line (or reset and move to prompt)
390 result=print_selection(maxHistoryItems, pattern, history);
381 391 print_history_label(history); print_history_label(history);
392 selectionCursorPosition=0;
382 393 break; break;
383 case K_CTRL_H:
394 case K_CTRL_SLASH:
384 395 defaultOrder=!defaultOrder; defaultOrder=!defaultOrder;
385 result=print_selection(maxHistoryItems, prefix, history);
386 // TODO render selected line (or reset and move to prompt)
396 result=print_selection(maxHistoryItems, pattern, history);
387 397 print_history_label(history); print_history_label(history);
398 selectionCursorPosition=0;
388 399 break; break;
389 400 case K_CTRL_X: case K_CTRL_X:
390 401 result=NULL; result=NULL;
 
... ... void selection_loop(HistoryItems *history)
392 403 break; break;
393 404 case KEY_RESIZE: case KEY_RESIZE:
394 405 print_history_label(history); print_history_label(history);
395 move(y, basex+strlen(prefix));
406 move(y, basex+strlen(pattern));
396 407 break; break;
397 408 case K_CTRL_U: case K_CTRL_U:
398 prefix[0]=0;
399 mvprintw(y, basex, "");
400 clrtoeol();
409 case K_CTRL_W: // TODO supposed to delete just one word backward
410 pattern[0]=0;
411 print_pattern(pattern, y, basex);
412 break;
413 case K_CTRL_L:
414 toggle_case(pattern, lowercase);
415 lowercase=!lowercase;
416 print_pattern(pattern, y, basex);
417 selectionCursorPosition=0;
418 break;
419 case K_CTRL_H:
401 420 case K_BACKSPACE: case K_BACKSPACE:
402 421 case KEY_BACKSPACE: case KEY_BACKSPACE:
403 if(strlen(prefix)>0) {
404 prefix[strlen(prefix)-1]=0;
422 if(strlen(pattern)>0) {
423 pattern[strlen(pattern)-1]=0;
405 424 x--; x--;
406 color_attr_on(A_BOLD);
407 mvprintw(y, basex, "%s", prefix);
408 color_attr_off(A_BOLD);
409 clrtoeol();
425 print_pattern(pattern, y, basex);
410 426 } }
411 427
412 if(strlen(prefix)>0) {
413 make_selection(prefix, history, maxHistoryItems);
428 if(strlen(pattern)>0) {
429 make_selection(pattern, history, maxHistoryItems);
414 430 } else { } else {
415 431 make_selection(NULL, history, maxHistoryItems); make_selection(NULL, history, maxHistoryItems);
416 432 } }
417 result=print_selection(maxHistoryItems, prefix, history);
433 result=print_selection(maxHistoryItems, pattern, history);
418 434
419 move(y, basex+strlen(prefix));
435 move(y, basex+strlen(pattern));
420 436 break; break;
421 437 case KEY_UP: case KEY_UP:
422 438 previousSelectionCursorPosition=selectionCursorPosition; previousSelectionCursorPosition=selectionCursorPosition;
 
... ... void selection_loop(HistoryItems *history)
425 441 } else { } else {
426 442 selectionCursorPosition=selectionSize-1; selectionCursorPosition=selectionSize-1;
427 443 } }
428 highlight_selection(selectionCursorPosition, previousSelectionCursorPosition, prefix);
429 move(y, basex+strlen(prefix));
444 highlight_selection(selectionCursorPosition, previousSelectionCursorPosition, pattern);
445 move(y, basex+strlen(pattern));
430 446 break; break;
431 447 case K_CTRL_R: case K_CTRL_R:
432 448 case KEY_DOWN: case KEY_DOWN:
 
... ... void selection_loop(HistoryItems *history)
440 456 selectionCursorPosition=0; selectionCursorPosition=0;
441 457 } }
442 458 } }
443 highlight_selection(selectionCursorPosition, previousSelectionCursorPosition, prefix);
444 move(y, basex+strlen(prefix));
459 highlight_selection(selectionCursorPosition, previousSelectionCursorPosition, pattern);
460 move(y, basex+strlen(pattern));
445 461 break; break;
446 462 case K_ENTER: case K_ENTER:
447 463 case KEY_ENTER: case KEY_ENTER:
 
... ... void selection_loop(HistoryItems *history)
467 483 if(c>K_CTRL_Z) { if(c>K_CTRL_Z) {
468 484 selectionCursorPosition=SELECTION_CURSOR_IN_PROMPT; selectionCursorPosition=SELECTION_CURSOR_IN_PROMPT;
469 485
470 if(strlen(prefix)<(width-basex-1)) {
471 strcat(prefix, (char*)(&c));
472 color_attr_on(A_BOLD);
473 mvprintw(y, basex, "%s", prefix);
486 if(strlen(pattern)<(width-basex-1)) {
487 strcat(pattern, (char*)(&c));
488 print_pattern(pattern, y, basex);
474 489 cursorX=getcurx(stdscr); cursorX=getcurx(stdscr);
475 490 cursorY=getcury(stdscr); cursorY=getcury(stdscr);
476 color_attr_off(A_BOLD);
477 clrtoeol();
478 491 } }
479 492
480 result = print_selection(maxHistoryItems, prefix, history);
493 result = print_selection(maxHistoryItems, pattern, history);
481 494 move(cursorY, cursorX); move(cursorY, cursorX);
482 495 refresh(); refresh();
483 496 } }
 
... ... void install_show()
500 513 } }
501 514
502 515 void assemble_cmdline(int argc, char *argv[]) { void assemble_cmdline(int argc, char *argv[]) {
516 // TODO support BASH substitutions: !!, !!ps, !$, !*
503 517 int i; int i;
504 518 cmdline[0]=0; cmdline[0]=0;
505 519 for(i=1; i<argc; i++) { for(i=1; i<argc; i++) {
 
... ... void hstr()
522 536 HistoryItems *history=get_prioritized_history(); HistoryItems *history=get_prioritized_history();
523 537 if(history) { if(history) {
524 538 history_mgmt_open(); history_mgmt_open();
525 selection_loop(history);
539 loop_to_select(history);
526 540 hstr_on_exit(); hstr_on_exit();
527 541 } else { } else {
528 542 printf("Empty shell history - nothing to suggest...\n"); printf("Empty shell history - nothing to suggest...\n");
File src/hstr_utils.c changed (mode: 100644) (index bd8623c..c78e6d7)
8 8 */ */
9 9
10 10 #include "include/hstr_utils.h" #include "include/hstr_utils.h"
11 #include <ctype.h>
11 12
12 13 #define DEFAULT_COMMAND "pwd" #define DEFAULT_COMMAND "pwd"
13 14 #define HOSTNAME_BUFFER 100 #define HOSTNAME_BUFFER 100
 
... ... char *get_hostname()
65 66 return b; return b;
66 67 } }
67 68
69 void toggle_case(char *str, bool lowercase) {
70 if(str && strlen(str>0)) {
71 int i;
72 for(i = 0; str[i]; i++){
73 if(lowercase) {
74 str[i] = tolower(str[i]);
75 } else {
76 str[i] = toupper(str[i]);
77 }
78 }
79 }
80 }
File src/include/hstr_utils.h changed (mode: 100644) (index 2539087..fa435c1)
... ... void tiocsti();
24 24 void fill_terminal_input(char* cmd, bool padding); void fill_terminal_input(char* cmd, bool padding);
25 25 void reverse_char_pointer_array(char **array, unsigned length); void reverse_char_pointer_array(char **array, unsigned length);
26 26 char *get_hostname(); char *get_hostname();
27 void toggle_case(char *str, bool lowercase);
27 28
28 29 #endif #endif
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/hstr

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/hstr

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master