mirror of
https://github.com/dvorka/hstr.git
synced 2025-02-24 23:08:36 +08:00
This commit is contained in:
parent
c6a796cd94
commit
9b1de77d8c
4 changed files with 74 additions and 43 deletions
5
man/hh.1
5
man/hh.1
|
@ -23,9 +23,12 @@ Type to filter shell history.
|
||||||
\fBCtrl\-t\fR
|
\fBCtrl\-t\fR
|
||||||
Toggle case sensitive search.
|
Toggle case sensitive search.
|
||||||
.TP
|
.TP
|
||||||
\fBCtrl\-h\fR
|
\fBCtrl\-/\fR
|
||||||
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.
|
||||||
.TP
|
.TP
|
||||||
|
\fBCtrl\-l\fR
|
||||||
|
Make search pattern lowercase or uppercase.
|
||||||
|
.TP
|
||||||
\fBCtrl\-r\fR, \fBUP\fR arrow, \fBDOWN\fR arrow
|
\fBCtrl\-r\fR, \fBUP\fR arrow, \fBDOWN\fR arrow
|
||||||
Navigate in the history list.
|
Navigate in the history list.
|
||||||
.TP
|
.TP
|
||||||
|
|
98
src/hstr.c
98
src/hstr.c
|
@ -38,12 +38,16 @@
|
||||||
#define K_CTRL_E 5
|
#define K_CTRL_E 5
|
||||||
#define K_CTRL_G 7
|
#define K_CTRL_G 7
|
||||||
#define K_CTRL_H 8
|
#define K_CTRL_H 8
|
||||||
|
#define K_CTRL_L 12
|
||||||
#define K_CTRL_R 18
|
#define K_CTRL_R 18
|
||||||
#define K_CTRL_T 20
|
#define K_CTRL_T 20
|
||||||
#define K_CTRL_U 21
|
#define K_CTRL_U 21
|
||||||
|
#define K_CTRL_W 23
|
||||||
#define K_CTRL_X 24
|
#define K_CTRL_X 24
|
||||||
#define K_CTRL_Z 26
|
#define K_CTRL_Z 26
|
||||||
|
|
||||||
|
#define K_CTRL_SLASH 31
|
||||||
|
|
||||||
#define K_ESC 27
|
#define K_ESC 27
|
||||||
#define K_TAB 9
|
#define K_TAB 9
|
||||||
#define K_BACKSPACE 127
|
#define K_BACKSPACE 127
|
||||||
|
@ -116,7 +120,7 @@ void print_cmd_deleted_label(char *cmd, int occurences)
|
||||||
// make this status row
|
// make this status row
|
||||||
void print_history_label(HistoryItems *history)
|
void print_history_label(HistoryItems *history)
|
||||||
{
|
{
|
||||||
sprintf(screenLine, "- HISTORY - case:%s (C-t) - order:%s (C-h) - %d/%d ",
|
sprintf(screenLine, "- HISTORY - case:%s (C-t) - order:%s (C-/) - %d/%d ",
|
||||||
(caseSensitive?"sensitive":"insensitive"),
|
(caseSensitive?"sensitive":"insensitive"),
|
||||||
(defaultOrder?"history":"ranking"),
|
(defaultOrder?"history":"ranking"),
|
||||||
history->count,
|
history->count,
|
||||||
|
@ -137,6 +141,13 @@ void print_history_label(HistoryItems *history)
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void print_pattern(char *pattern, int y, int x) {
|
||||||
|
color_attr_on(A_BOLD);
|
||||||
|
mvprintw(y, x, "%s", pattern);
|
||||||
|
color_attr_off(A_BOLD);
|
||||||
|
clrtoeol();
|
||||||
|
}
|
||||||
|
|
||||||
unsigned get_max_history_items()
|
unsigned get_max_history_items()
|
||||||
{
|
{
|
||||||
return (getmaxy(stdscr)-Y_OFFSET_ITEMS);
|
return (getmaxy(stdscr)-Y_OFFSET_ITEMS);
|
||||||
|
@ -314,7 +325,7 @@ void signal_callback_handler_ctrl_c(int signum)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void selection_loop(HistoryItems *history)
|
void loop_to_select(HistoryItems *history)
|
||||||
{
|
{
|
||||||
signal(SIGINT, signal_callback_handler_ctrl_c);
|
signal(SIGINT, signal_callback_handler_ctrl_c);
|
||||||
|
|
||||||
|
@ -331,29 +342,29 @@ void selection_loop(HistoryItems *history)
|
||||||
|
|
||||||
color_attr_off(COLOR_PAIR(1));
|
color_attr_off(COLOR_PAIR(1));
|
||||||
|
|
||||||
bool done=FALSE, skip=TRUE, executeResult=FALSE;
|
bool done=FALSE, skip=TRUE, executeResult=FALSE, lowercase=TRUE;
|
||||||
int basex=print_prompt(stdscr);
|
int basex=print_prompt(stdscr);
|
||||||
int x=basex, y=1, c, cursorX=0, cursorY=0, maxHistoryItems, deleteOccurences;
|
int x=basex, y=1, c, cursorX=0, cursorY=0, maxHistoryItems, deleteOccurences;
|
||||||
int width=getmaxx(stdscr);
|
int width=getmaxx(stdscr);
|
||||||
int selectionCursorPosition=SELECTION_CURSOR_IN_PROMPT;
|
int selectionCursorPosition=SELECTION_CURSOR_IN_PROMPT;
|
||||||
int previousSelectionCursorPosition=SELECTION_CURSOR_IN_PROMPT;
|
int previousSelectionCursorPosition=SELECTION_CURSOR_IN_PROMPT;
|
||||||
char *result="", *msg, *delete;
|
char *result="", *msg, *delete;
|
||||||
char prefix[SELECTION_PREFIX_MAX_LNG];
|
char pattern[SELECTION_PREFIX_MAX_LNG];
|
||||||
prefix[0]=0;
|
pattern[0]=0;
|
||||||
strcpy(prefix, cmdline);
|
strcpy(pattern, cmdline);
|
||||||
while (!done) {
|
while (!done) {
|
||||||
maxHistoryItems=get_max_history_items(stdscr);
|
maxHistoryItems=get_max_history_items(stdscr);
|
||||||
|
|
||||||
if(!skip) {
|
if(!skip) {
|
||||||
c = wgetch(stdscr);
|
c = wgetch(stdscr);
|
||||||
} else {
|
} else {
|
||||||
if(strlen(prefix)>0) {
|
if(strlen(pattern)>0) {
|
||||||
color_attr_on(A_BOLD);
|
color_attr_on(A_BOLD);
|
||||||
mvprintw(y, basex, "%s", prefix);
|
mvprintw(y, basex, "%s", pattern);
|
||||||
color_attr_off(A_BOLD);
|
color_attr_off(A_BOLD);
|
||||||
cursorX=getcurx(stdscr);
|
cursorX=getcurx(stdscr);
|
||||||
cursorY=getcury(stdscr);
|
cursorY=getcury(stdscr);
|
||||||
result=print_selection(maxHistoryItems, prefix, history);
|
result=print_selection(maxHistoryItems, pattern, history);
|
||||||
move(cursorY, cursorX);
|
move(cursorY, cursorX);
|
||||||
}
|
}
|
||||||
skip=FALSE;
|
skip=FALSE;
|
||||||
|
@ -368,23 +379,23 @@ void selection_loop(HistoryItems *history)
|
||||||
strcpy(msg,delete);
|
strcpy(msg,delete);
|
||||||
selection_remove(delete, history);
|
selection_remove(delete, history);
|
||||||
deleteOccurences=history_mgmt_remove(delete);
|
deleteOccurences=history_mgmt_remove(delete);
|
||||||
result=print_selection(maxHistoryItems, prefix, history);
|
result=print_selection(maxHistoryItems, pattern, history);
|
||||||
print_cmd_deleted_label(msg, deleteOccurences);
|
print_cmd_deleted_label(msg, deleteOccurences);
|
||||||
move(y, basex+strlen(prefix));
|
move(y, basex+strlen(pattern));
|
||||||
}
|
}
|
||||||
print_history_label(history);
|
print_history_label(history);
|
||||||
break;
|
break;
|
||||||
case K_CTRL_T:
|
case K_CTRL_T:
|
||||||
caseSensitive=!caseSensitive;
|
caseSensitive=!caseSensitive;
|
||||||
result=print_selection(maxHistoryItems, prefix, history);
|
result=print_selection(maxHistoryItems, pattern, history);
|
||||||
// TODO render selected line (or reset and move to prompt)
|
|
||||||
print_history_label(history);
|
print_history_label(history);
|
||||||
|
selectionCursorPosition=0;
|
||||||
break;
|
break;
|
||||||
case K_CTRL_H:
|
case K_CTRL_SLASH:
|
||||||
defaultOrder=!defaultOrder;
|
defaultOrder=!defaultOrder;
|
||||||
result=print_selection(maxHistoryItems, prefix, history);
|
result=print_selection(maxHistoryItems, pattern, history);
|
||||||
// TODO render selected line (or reset and move to prompt)
|
|
||||||
print_history_label(history);
|
print_history_label(history);
|
||||||
|
selectionCursorPosition=0;
|
||||||
break;
|
break;
|
||||||
case K_CTRL_X:
|
case K_CTRL_X:
|
||||||
result=NULL;
|
result=NULL;
|
||||||
|
@ -392,31 +403,36 @@ void selection_loop(HistoryItems *history)
|
||||||
break;
|
break;
|
||||||
case KEY_RESIZE:
|
case KEY_RESIZE:
|
||||||
print_history_label(history);
|
print_history_label(history);
|
||||||
move(y, basex+strlen(prefix));
|
move(y, basex+strlen(pattern));
|
||||||
break;
|
break;
|
||||||
case K_CTRL_U:
|
case K_CTRL_U:
|
||||||
prefix[0]=0;
|
case K_CTRL_W: // TODO supposed to delete just one word backward
|
||||||
mvprintw(y, basex, "");
|
pattern[0]=0;
|
||||||
clrtoeol();
|
print_pattern(pattern, y, basex);
|
||||||
|
break;
|
||||||
|
case K_CTRL_L:
|
||||||
|
toggle_case(pattern, lowercase);
|
||||||
|
lowercase=!lowercase;
|
||||||
|
print_pattern(pattern, y, basex);
|
||||||
|
selectionCursorPosition=0;
|
||||||
|
break;
|
||||||
|
case K_CTRL_H:
|
||||||
case K_BACKSPACE:
|
case K_BACKSPACE:
|
||||||
case KEY_BACKSPACE:
|
case KEY_BACKSPACE:
|
||||||
if(strlen(prefix)>0) {
|
if(strlen(pattern)>0) {
|
||||||
prefix[strlen(prefix)-1]=0;
|
pattern[strlen(pattern)-1]=0;
|
||||||
x--;
|
x--;
|
||||||
color_attr_on(A_BOLD);
|
print_pattern(pattern, y, basex);
|
||||||
mvprintw(y, basex, "%s", prefix);
|
|
||||||
color_attr_off(A_BOLD);
|
|
||||||
clrtoeol();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(strlen(prefix)>0) {
|
if(strlen(pattern)>0) {
|
||||||
make_selection(prefix, history, maxHistoryItems);
|
make_selection(pattern, history, maxHistoryItems);
|
||||||
} else {
|
} else {
|
||||||
make_selection(NULL, history, maxHistoryItems);
|
make_selection(NULL, history, maxHistoryItems);
|
||||||
}
|
}
|
||||||
result=print_selection(maxHistoryItems, prefix, history);
|
result=print_selection(maxHistoryItems, pattern, history);
|
||||||
|
|
||||||
move(y, basex+strlen(prefix));
|
move(y, basex+strlen(pattern));
|
||||||
break;
|
break;
|
||||||
case KEY_UP:
|
case KEY_UP:
|
||||||
previousSelectionCursorPosition=selectionCursorPosition;
|
previousSelectionCursorPosition=selectionCursorPosition;
|
||||||
|
@ -425,8 +441,8 @@ void selection_loop(HistoryItems *history)
|
||||||
} else {
|
} else {
|
||||||
selectionCursorPosition=selectionSize-1;
|
selectionCursorPosition=selectionSize-1;
|
||||||
}
|
}
|
||||||
highlight_selection(selectionCursorPosition, previousSelectionCursorPosition, prefix);
|
highlight_selection(selectionCursorPosition, previousSelectionCursorPosition, pattern);
|
||||||
move(y, basex+strlen(prefix));
|
move(y, basex+strlen(pattern));
|
||||||
break;
|
break;
|
||||||
case K_CTRL_R:
|
case K_CTRL_R:
|
||||||
case KEY_DOWN:
|
case KEY_DOWN:
|
||||||
|
@ -440,8 +456,8 @@ void selection_loop(HistoryItems *history)
|
||||||
selectionCursorPosition=0;
|
selectionCursorPosition=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
highlight_selection(selectionCursorPosition, previousSelectionCursorPosition, prefix);
|
highlight_selection(selectionCursorPosition, previousSelectionCursorPosition, pattern);
|
||||||
move(y, basex+strlen(prefix));
|
move(y, basex+strlen(pattern));
|
||||||
break;
|
break;
|
||||||
case K_ENTER:
|
case K_ENTER:
|
||||||
case KEY_ENTER:
|
case KEY_ENTER:
|
||||||
|
@ -467,17 +483,14 @@ void selection_loop(HistoryItems *history)
|
||||||
if(c>K_CTRL_Z) {
|
if(c>K_CTRL_Z) {
|
||||||
selectionCursorPosition=SELECTION_CURSOR_IN_PROMPT;
|
selectionCursorPosition=SELECTION_CURSOR_IN_PROMPT;
|
||||||
|
|
||||||
if(strlen(prefix)<(width-basex-1)) {
|
if(strlen(pattern)<(width-basex-1)) {
|
||||||
strcat(prefix, (char*)(&c));
|
strcat(pattern, (char*)(&c));
|
||||||
color_attr_on(A_BOLD);
|
print_pattern(pattern, y, basex);
|
||||||
mvprintw(y, basex, "%s", prefix);
|
|
||||||
cursorX=getcurx(stdscr);
|
cursorX=getcurx(stdscr);
|
||||||
cursorY=getcury(stdscr);
|
cursorY=getcury(stdscr);
|
||||||
color_attr_off(A_BOLD);
|
|
||||||
clrtoeol();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result = print_selection(maxHistoryItems, prefix, history);
|
result = print_selection(maxHistoryItems, pattern, history);
|
||||||
move(cursorY, cursorX);
|
move(cursorY, cursorX);
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
@ -500,6 +513,7 @@ void install_show()
|
||||||
}
|
}
|
||||||
|
|
||||||
void assemble_cmdline(int argc, char *argv[]) {
|
void assemble_cmdline(int argc, char *argv[]) {
|
||||||
|
// TODO support BASH substitutions: !!, !!ps, !$, !*
|
||||||
int i;
|
int i;
|
||||||
cmdline[0]=0;
|
cmdline[0]=0;
|
||||||
for(i=1; i<argc; i++) {
|
for(i=1; i<argc; i++) {
|
||||||
|
@ -522,7 +536,7 @@ void hstr()
|
||||||
HistoryItems *history=get_prioritized_history();
|
HistoryItems *history=get_prioritized_history();
|
||||||
if(history) {
|
if(history) {
|
||||||
history_mgmt_open();
|
history_mgmt_open();
|
||||||
selection_loop(history);
|
loop_to_select(history);
|
||||||
hstr_on_exit();
|
hstr_on_exit();
|
||||||
} else {
|
} else {
|
||||||
printf("Empty shell history - nothing to suggest...\n");
|
printf("Empty shell history - nothing to suggest...\n");
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "include/hstr_utils.h"
|
#include "include/hstr_utils.h"
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
#define DEFAULT_COMMAND "pwd"
|
#define DEFAULT_COMMAND "pwd"
|
||||||
#define HOSTNAME_BUFFER 100
|
#define HOSTNAME_BUFFER 100
|
||||||
|
@ -65,3 +66,15 @@ char *get_hostname()
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void toggle_case(char *str, bool lowercase) {
|
||||||
|
if(str && strlen(str>0)) {
|
||||||
|
int i;
|
||||||
|
for(i = 0; str[i]; i++){
|
||||||
|
if(lowercase) {
|
||||||
|
str[i] = tolower(str[i]);
|
||||||
|
} else {
|
||||||
|
str[i] = toupper(str[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -24,5 +24,6 @@ void tiocsti();
|
||||||
void fill_terminal_input(char* cmd, bool padding);
|
void fill_terminal_input(char* cmd, bool padding);
|
||||||
void reverse_char_pointer_array(char **array, unsigned length);
|
void reverse_char_pointer_array(char **array, unsigned length);
|
||||||
char *get_hostname();
|
char *get_hostname();
|
||||||
|
void toggle_case(char *str, bool lowercase);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue