From f476ca3777265350305d1f89b04949d6dd0ec8e4 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Thu, 28 Apr 2022 07:37:44 -0700 Subject: History recall for colon commands and trigger patterns. --- pw.1 | 11 +++++++++ pw.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 94 insertions(+), 8 deletions(-) diff --git a/pw.1 b/pw.1 index 428a5c1..5c0240e 100644 --- a/pw.1 +++ b/pw.1 @@ -211,6 +211,11 @@ appears, showing the pattern preceded by a question mark. The .I pattern is an extended regular expression (ERE). +Trigger patterns saved in a history which may be navigated for +recall using the up and down arrow keys or +.B Ctrl-P +and +.BR Ctrl-N . .SH COLON COMMANDS @@ -222,6 +227,12 @@ the poll interval period. The longer the poll interval .RB ( -i " option), the longer the result message persists. +Colon commands are saved in a history which may be navigated for +recall using the up and down arrow keys or +.B Ctrl-P +and +.BR Ctrl-N . + .IP "\fB:w\fP \fIfilename\fP" Write the current contents of the display into the specified file. diff --git a/pw.c b/pw.c index 7782057..f3c4c34 100644 --- a/pw.c +++ b/pw.c @@ -56,6 +56,12 @@ regex_t trigex; grep grepstack[maxgrep]; int ngrep; +char **cmdhist; +unsigned ncmdhist; + +char **pathist; +unsigned npathist; + static void panic(const char *fmt, ...) { va_list vl; @@ -410,7 +416,7 @@ int main(int argc, char **argv) }; int auto_quit = 1; int exit_status = EXIT_FAILURE; - char cmdbuf[cmdsize], *curcmd = 0; + char cmdbuf[cmdsize], *curcmd = 0, *savedcmd = 0; if (fd < 0) panic("unable to obtain input file descriptor"); @@ -486,8 +492,8 @@ int main(int argc, char **argv) panic("unable to set stdin nonblocking"); for (unsigned stat = stat_dirty, hpos = 0, - kbd_state = kbd_cmd, lasttime = ~0U, - work = 1000; + kbd_state = kbd_cmd, kbd_prev = kbd_cmd, lasttime = ~0U, + work = 1000, histpos = 0; kbd_state != kbd_exit ;) { int force = 0, nfds = 2, pollms = poll_interval; @@ -647,16 +653,19 @@ int main(int argc, char **argv) stat |= stat_dirty; break; case ESC: + kbd_prev = kbd_state; kbd_state = kbd_esc; break; case ':': kbd_state = kbd_colon; + histpos = 0; cmdbuf[0] = ch; cmdbuf[1] = 0; curcmd = cmdbuf; break; case '/': case '?': kbd_state = kbd_trig; + histpos = 0; cmdbuf[0] = ch; cmdbuf[1] = 0; curcmd = cmdbuf; @@ -664,13 +673,16 @@ int main(int argc, char **argv) } break; case kbd_esc: - kbd_state = kbd_cmd; - if (ch == '[') + if (ch == '[') { kbd_state = kbd_bkt; + break; + } + kbd_state = kbd_cmd; + curcmd = 0; break; case kbd_bkt: - kbd_state = kbd_cmd; - switch (ch) { + kbd_state = kbd_prev; + if (kbd_prev == kbd_cmd) switch (ch) { case 'D': ch = 'h'; goto fakecmd; @@ -681,6 +693,14 @@ int main(int argc, char **argv) ch = '0'; goto fakecmd; } + switch (ch) { + case 'A': + ch = ctrl('p'); + goto fakecmd; + case 'B': + ch = ctrl('n'); + goto fakecmd; + } break; case kbd_trig: if (trigpat) { @@ -692,8 +712,28 @@ int main(int argc, char **argv) // fallthrough case kbd_colon: switch (ch) { - case ESC: case CR: case ctrl('c'): + case ESC: + kbd_prev = kbd_state; + kbd_state = kbd_esc; + break; + case CR: case ctrl('c'): if (ch == CR) { + if (cmdbuf[1]) { + unsigned *pnhist = (kbd_state == kbd_colon + ? &ncmdhist : &npathist); + unsigned nhist = *pnhist; + char ***hist = (kbd_state == kbd_colon ? + &cmdhist : &pathist); + + if (nhist == 0 || strcmp(cmdbuf, (*hist)[0]) != 0) { + if ((*hist = realloc(*hist, sizeof **hist * (nhist + 1))) == 0) + panic("out of memory"); + memmove(*hist + 1, *hist, sizeof **hist * nhist); + *pnhist = nhist + 1; + (*hist)[0] = dsdup(cmdbuf); + } + } + if (kbd_state == kbd_colon && cmdbuf[1]) { execute(cmdbuf, &stat); if (cmdbuf[0] != 0) { @@ -744,6 +784,41 @@ int main(int argc, char **argv) cmdbuf[len] = 0; } break; + case ctrl('p'): + case ctrl('n'): + { + unsigned nhist = (kbd_state == kbd_colon ? ncmdhist : npathist); + char ***hist = (kbd_state == kbd_colon ? &cmdhist : &pathist); + + if (ch == ctrl('p')) { + if (histpos == 0) { + dsdrop(savedcmd); + savedcmd = dsdup(cmdbuf); + } else { + dsdrop((*hist)[histpos-1]); + (*hist)[histpos-1] = dsdup(cmdbuf); + } + if (histpos < nhist) { + char *cmd = (*hist)[histpos++]; + strcpy(cmdbuf, cmd); + } + } else { + if (histpos >= 1) { + dsdrop((*hist)[histpos-1]); + (*hist)[histpos-1] = dsdup(cmdbuf); + } + if (histpos > 1) { + char *cmd = (*hist)[--histpos - 1]; + strcpy(cmdbuf, cmd); + } else if (histpos == 1) { + --histpos; + strcpy(cmdbuf, savedcmd); + dsdrop(savedcmd); + savedcmd = 0; + } + } + } + break; default: if (isprint(ch)) { -- cgit v1.2.3