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 762fd77c4d3f953bc2613d066620f230d82c4308

Simplification of the command propagation to the prompt.
Author: Martin Dvorak
Author date (UTC): 2014-01-20 22:48
Committer name: Martin Dvorak
Committer date (UTC): 2014-01-20 22:48
Parent(s): 3450d22e7f5ff2ca2501241abe2aabd1ee0d8c55
Signing key:
Tree: d42491dbedc6f147d2de401e6b3166c0d7b423a8
File Lines added Lines deleted
man/hh.1 1 2
src/hstr.c 35 35
src/hstr_history.c 1 1
src/hstr_utils.c 1 0
src/include/hstr_history.h 1 1
tests/src/test_args.c 2 0
File man/hh.1 changed (mode: 100644) (index dcc5e35..c749644)
... ... Add the following lines to ~/.bashrc:
49 49 .sp .sp
50 50 shopt -s histappend shopt -s histappend
51 51 export PROMPT_COMMAND="history \-a; history \-n; ${PROMPT_COMMAND}" export PROMPT_COMMAND="history \-a; history \-n; ${PROMPT_COMMAND}"
52 bind '"\eC\-r": "\eC\-ahh \eC-j"'
52 bind '"\eC\-r": "\eC\-a hh \eC-j"'
53 53 .sp .sp
54 54 .fi .fi
55 55 The first command ensures that new history items are appended to .bash_history The first command ensures that new history items are appended to .bash_history
 
... ... Report bugs to https://github.com/dvorka/hstr/issues
63 63 .SH "SEE ALSO" .SH "SEE ALSO"
64 64 .BR history (1), .BR history (1),
65 65 .BR bash (1) .BR bash (1)
66
File src/hstr.c changed (mode: 100644) (index c98b42f..f88d4d7)
... ... static const char *INSTALL_STRING=
69 69 "\n# Add this configuration to ~/.bashrc to let HH load and flush up to date history" "\n# Add this configuration to ~/.bashrc to let HH load and flush up to date history"
70 70 "\nshopt -s histappend" "\nshopt -s histappend"
71 71 "\nexport PROMPT_COMMAND=\"history -a; history -n; ${PROMPT_COMMAND}\"" "\nexport PROMPT_COMMAND=\"history -a; history -n; ${PROMPT_COMMAND}\""
72 "\nbind '\"\\C-r\": \"\\C-ahh \\C-j\"'"
72 "\nbind '\"\\C-r\": \"\\C-a hh \\C-j\"'"
73 73 "\n\n"; "\n\n";
74 74
75 75 static const char *BUILD_STRING= static const char *BUILD_STRING=
 
... ... unsigned get_max_history_items()
143 143 } }
144 144
145 145
146 void alloc_selection(unsigned size)
146 void realloc_selection(unsigned size)
147 147 { {
148 148 selectionSize=size; selectionSize=size;
149 149 if(selection!=NULL) { if(selection!=NULL) {
150 free(selection);
151 selection=NULL;
152 }
153 if(size>0) {
154 selection = malloc(size);
150 if(size>0) {
151 selection=realloc(selection, size);
152 } else {
153 free(selection);
154 selection=NULL;
155 }
156 } else {
157 if(size>0) {
158 selection = malloc(size);
159 }
155 160 } }
156 161 } }
157 162
158 163 unsigned make_selection(char *prefix, HistoryItems *history, int maxSelectionCount) unsigned make_selection(char *prefix, HistoryItems *history, int maxSelectionCount)
159 164 { {
160 alloc_selection(sizeof(char*) * maxSelectionCount); // TODO realloc
165 realloc_selection(sizeof(char*) * maxSelectionCount);
161 166 unsigned i, selectionCount=0; unsigned i, selectionCount=0;
162 167 char **source=(defaultOrder?history->raw:history->items); char **source=(defaultOrder?history->raw:history->items);
163 168
 
... ... void selection_remove(char *cmd, HistoryItems *history)
295 300 } }
296 301 } }
297 302
298 void hstr_on_exit(char *command) {
299 history_mgmt_close();
300 fill_terminal_input(command, true);
303 void hstr_on_exit() {
304 history_mgmt_flush();
301 305 free_prioritized_history(); free_prioritized_history();
302 306 } }
303 307
 
... ... void signal_callback_handler_ctrl_c(int signum)
305 309 { {
306 310 if(signum==SIGINT) { if(signum==SIGINT) {
307 311 endwin(); endwin();
308 hstr_on_exit(NULL);
312 hstr_on_exit();
309 313 exit(signum); exit(signum);
310 314 } }
311 315 } }
312 316
313 char *prepare_result(int selectionCursorPosition, bool executeResult)
314 {
315 cmdline[0]=0;
316 strcpy(cmdline,selection[selectionCursorPosition]);
317 if(executeResult) strcat(cmdline,"\n");
318 alloc_selection(0);
319 return cmdline;
320 }
321
322 char *selection_loop(HistoryItems *history)
317 void selection_loop(HistoryItems *history)
323 318 { {
324 319 signal(SIGINT, signal_callback_handler_ctrl_c); signal(SIGINT, signal_callback_handler_ctrl_c);
325 320
 
... ... char *selection_loop(HistoryItems *history)
358 353 color_attr_off(A_BOLD); color_attr_off(A_BOLD);
359 354 cursorX=getcurx(stdscr); cursorX=getcurx(stdscr);
360 355 cursorY=getcury(stdscr); cursorY=getcury(stdscr);
361 result = print_selection(maxHistoryItems, prefix, history);
356 result=print_selection(maxHistoryItems, prefix, history);
362 357 move(cursorY, cursorX); move(cursorY, cursorX);
363 358 } }
364 359 skip=FALSE; skip=FALSE;
 
... ... char *selection_loop(HistoryItems *history)
373 368 strcpy(msg,delete); strcpy(msg,delete);
374 369 selection_remove(delete, history); selection_remove(delete, history);
375 370 deleteOccurences=history_mgmt_remove(delete); deleteOccurences=history_mgmt_remove(delete);
376 result = print_selection(maxHistoryItems, prefix, history);
371 result=print_selection(maxHistoryItems, prefix, history);
377 372 print_cmd_deleted_label(msg, deleteOccurences); print_cmd_deleted_label(msg, deleteOccurences);
378 373 move(y, basex+strlen(prefix)); move(y, basex+strlen(prefix));
379 374 } }
 
... ... char *selection_loop(HistoryItems *history)
381 376 break; break;
382 377 case K_CTRL_T: case K_CTRL_T:
383 378 caseSensitive=!caseSensitive; caseSensitive=!caseSensitive;
384 result = print_selection(maxHistoryItems, prefix, history);
379 result=print_selection(maxHistoryItems, prefix, history);
385 380 print_history_label(history); print_history_label(history);
386 381 break; break;
387 382 case K_CTRL_H: case K_CTRL_H:
388 383 defaultOrder=!defaultOrder; defaultOrder=!defaultOrder;
389 result = print_selection(maxHistoryItems, prefix, history);
384 result=print_selection(maxHistoryItems, prefix, history);
390 385 print_history_label(history); print_history_label(history);
391 386 break; break;
392 387 case K_CTRL_X: case K_CTRL_X:
393 result = NULL;
394 done = TRUE;
388 result=NULL;
389 done=TRUE;
395 390 break; break;
396 391 case KEY_RESIZE: case KEY_RESIZE:
397 392 print_history_label(history); print_history_label(history);
 
... ... char *selection_loop(HistoryItems *history)
417 412 } else { } else {
418 413 make_selection(NULL, history, maxHistoryItems); make_selection(NULL, history, maxHistoryItems);
419 414 } }
420 result = print_selection(maxHistoryItems, prefix, history);
415 result=print_selection(maxHistoryItems, prefix, history);
421 416
422 417 move(y, basex+strlen(prefix)); move(y, basex+strlen(prefix));
423 418 break; break;
 
... ... char *selection_loop(HistoryItems *history)
453 448 case KEY_LEFT: case KEY_LEFT:
454 449 case KEY_RIGHT: case KEY_RIGHT:
455 450 if(selectionCursorPosition!=SELECTION_CURSOR_IN_PROMPT) { if(selectionCursorPosition!=SELECTION_CURSOR_IN_PROMPT) {
456 result=prepare_result(selectionCursorPosition, executeResult);
451 result=selection[selectionCursorPosition];
457 452 } }
458 done = TRUE;
453 done=TRUE;
459 454 break; break;
460 455 case K_CTRL_G: case K_CTRL_G:
461 456 case K_ESC: case K_ESC:
462 result="";
457 result=NULL;
463 458 history_clear_dirty(); history_clear_dirty();
464 459 done=TRUE; done=TRUE;
465 460 break; break;
 
... ... char *selection_loop(HistoryItems *history)
489 484 } }
490 485 endwin(); endwin();
491 486
492 return result;
487 if(result!=NULL) {
488 fill_terminal_input(result, TRUE);
489 if(executeResult) {
490 fill_terminal_input("\n", FALSE);
491 }
492 }
493 493 } }
494 494
495 495 void install_show() void install_show()
 
... ... void hstr()
520 520 HistoryItems *history=get_prioritized_history(); HistoryItems *history=get_prioritized_history();
521 521 if(history) { if(history) {
522 522 history_mgmt_open(); history_mgmt_open();
523 char *command = selection_loop(history);
524 hstr_on_exit(command);
523 selection_loop(history);
524 hstr_on_exit();
525 525 } else { } else {
526 526 printf("Empty shell history - nothing to suggest...\n"); printf("Empty shell history - nothing to suggest...\n");
527 527 } }
File src/hstr_history.c changed (mode: 100644) (index 7ba60f1..d592d61)
... ... int history_mgmt_remove(char *cmd)
183 183 return occurences; return occurences;
184 184 } }
185 185
186 void history_mgmt_close()
186 void history_mgmt_flush()
187 187 { {
188 188 if(dirty) { if(dirty) {
189 189 fill_terminal_input("history -r\n", false); fill_terminal_input("history -r\n", false);
File src/hstr_utils.c changed (mode: 100644) (index e59f078..bd8623c)
... ... void fill_terminal_input(char *cmd, bool padding)
33 33 c=(cmd+i); c=(cmd+i);
34 34 ioctl(0, TIOCSTI, c); ioctl(0, TIOCSTI, c);
35 35 } }
36 // echo, but don't flush to terminal
36 37 if(padding) printf("\n"); if(padding) printf("\n");
37 38 } }
38 39 } }
File src/include/hstr_history.h changed (mode: 100644) (index 229473b..7798bbd)
... ... void free_prioritized_history();
45 45 void history_mgmt_open(); void history_mgmt_open();
46 46 void history_clear_dirty(); void history_clear_dirty();
47 47 int history_mgmt_remove(char *cmd); int history_mgmt_remove(char *cmd);
48 void history_mgmt_close();
48 void history_mgmt_flush();
49 49
50 50 #endif #endif
File tests/src/test_args.c changed (mode: 100644) (index 9e7e00f..1b59c2f)
14 14
15 15 int main(int argc, char *argv[]) int main(int argc, char *argv[])
16 16 { {
17 printf("%d",strchr("a\nb",10));
18
17 19 if(argc>0) { if(argc>0) {
18 20 int i; int i;
19 21 char line[LINELNG]; char line[LINELNG];
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