aboutsummaryrefslogtreecommitdiffstats
path: root/pw.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2022-04-28 07:37:44 -0700
committerKaz Kylheku <kaz@kylheku.com>2022-04-28 07:37:44 -0700
commitf476ca3777265350305d1f89b04949d6dd0ec8e4 (patch)
treed7d9f735037e63af19d02d35c5169dd145580b2f /pw.c
parentbc781bd17ee2cc996a57be3b3661236c5905d026 (diff)
downloadpw-f476ca3777265350305d1f89b04949d6dd0ec8e4.tar.gz
pw-f476ca3777265350305d1f89b04949d6dd0ec8e4.tar.bz2
pw-f476ca3777265350305d1f89b04949d6dd0ec8e4.zip
History recall for colon commands and trigger patterns.
Diffstat (limited to 'pw.c')
-rw-r--r--pw.c91
1 files changed, 83 insertions, 8 deletions
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))
{