diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2022-04-27 19:34:48 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2022-04-27 19:34:48 -0700 |
commit | cee49acbf13324bce50b4b8ef9c76fcca17790a0 (patch) | |
tree | d3da738182b8079f7db7299c91369b0ba4c158ea | |
parent | bb28f2cd6687e100e52233c6cc58a1909a11c9b3 (diff) | |
download | pw-cee49acbf13324bce50b4b8ef9c76fcca17790a0.tar.gz pw-cee49acbf13324bce50b4b8ef9c76fcca17790a0.tar.bz2 pw-cee49acbf13324bce50b4b8ef9c76fcca17790a0.zip |
New feature: trigger mode.
Prototype: does substring searching only: no regex.
-rw-r--r-- | pw.1 | 28 | ||||
-rw-r--r-- | pw.c | 118 |
2 files changed, 119 insertions, 27 deletions
@@ -177,6 +177,34 @@ and also terminate colon mode without executing a command. Colon commands are documented in the COLON COMMANDS section below. +.IP \fB/\fP\fIpattern\fP +Activate head trigger mode if a non-empty +.I pattern +is specified, or else cancel trigger mode if an empty pattern is +specified. Under head trigger mode, +the display refreshes only when the most recent line in the FIFO +matches the specified +.IR pattern . +That line at the head of the FIFO is the one which will appear at +the bottom of the display, since newer lines appear at the bottom +and scroll out toward the top. +In head trigger mode, the status string +.BI "TRIG (/" pattern ")" +appears, showing the pattern preceded by a slash. + +.IP \fB?\fP\fIpattern\fP +Activate tail trigger mode if a non-empty +.I pattern +is specified, or else cancel trigger mode if an empty pattern is +specified. Under tail trigger mode, +the display refreshes only when the least recent line in the FIFO +matches the specified +.IR pattern . +That line at the tail of the FIFO is the one which will appear at +the top of the display. In tail trigger mode, the status string +.BI "TRIG (?" pattern ")" +appears, showing the pattern preceded by a question mark. + .SH COLON COMMANDS First, some general remarks. Display refresh doesn't pause during the editing @@ -13,9 +13,12 @@ #include <sys/time.h> enum status_flags { - stat_dirty = 1, - stat_eof = 2, - stat_susp = 4 + stat_dirty = 1, // display needs refresh + stat_eof = 2, // end of data reached + stat_susp = 4, // display refresh suspended + stat_htmode = 8, // head trigger mode + stat_ttmode = 16, // tail trigger mode + stat_trgrd = 32 // triggered flag }; typedef struct dstr { @@ -28,6 +31,7 @@ typedef struct dstr { char **snapshot; int snaplines; +char *trigpat; static void panic(const char *fmt, ...) { @@ -88,6 +92,14 @@ static char *dsgrow(char *str, size_t len) return ds->str; } +static char *dsdup(char *str) +{ + size_t len = strlen(str); + char *copy = dsgrow(0, len); + memcpy(copy, str, len); + return copy; +} + static char *addch(char *line, int ch) { size_t len = line ? dslen(line) : 0; @@ -178,9 +190,13 @@ static void drawstatus(unsigned stat, char *cmd) { if (cmd) { printf("%s", cmd); - } else if ((stat & (stat_eof | stat_susp))) { + } else if ((stat & (stat_eof | stat_susp | stat_htmode | stat_ttmode))) { if ((stat & stat_eof)) printf("EOF "); + else if ((stat & stat_htmode)) + printf("TRIG (/%s) ", trigpat); + else if ((stat & stat_ttmode)) + printf("TRIG (?%s) ", trigpat); if ((stat & stat_susp)) printf("SUSPENDED "); } else { @@ -192,7 +208,10 @@ static void drawstatus(unsigned stat, char *cmd) static void redraw(char **circbuf, int nlines, int hpos, int columns, unsigned stat, char *cmd) { - if ((stat & stat_susp) == 0) { + if ((stat & stat_susp) == 0 && + (stat & (stat_htmode | stat_trgrd)) != stat_htmode && + (stat & (stat_ttmode | stat_trgrd)) != stat_ttmode) + { if (snapshot) { for (int i = 0; i < snaplines; i++) dsdrop(snapshot[i]); @@ -204,7 +223,9 @@ static void redraw(char **circbuf, int nlines, int hpos, snapshot[i] = dsref(circbuf[i]); } } else { - clrline(); + printf("\r\033[%dA\033[J", snaplines); + for (int i = 0; i < snaplines; i++) + drawline(snapshot[i], hpos, columns); } drawstatus(stat, cmd); } @@ -283,10 +304,13 @@ int main(int argc, char **argv) struct termios tty_saved, tty_new; struct winsize ws = { 0 }; int columns = 80; - enum kbd_state { kbd_cmd, kbd_esc, kbd_bkt, kbd_exit, kbd_colon, kbd_result }; + enum kbd_state { + kbd_cmd, kbd_esc, kbd_bkt, kbd_exit, + kbd_colon, kbd_result, kbd_htrig, kbd_ttrig + }; int auto_quit = 1; int exit_status = EXIT_FAILURE; - char cmdbuf[100], *colcmd = 0; + char cmdbuf[100], *curcmd = 0; if (fd < 0) panic("unable to obtain input file descriptor"); @@ -361,11 +385,16 @@ int main(int argc, char **argv) for (unsigned stat = stat_dirty, hpos = 0, kbd_state = kbd_cmd, lasttime = ~0U; kbd_state != kbd_exit ;) { + int force = 0; struct pollfd pe[2] = { { .fd = ttyfd, .events = POLLIN | POLLHUP | POLLERR }, { .fd = fd, .events = POLLIN | POLLHUP | POLLERR }, }; + if (stat & stat_trgrd) + force = 1; + + if (!force) { struct timeval tv; unsigned now; @@ -374,38 +403,49 @@ int main(int argc, char **argv) now = (((unsigned) tv.tv_sec)%1000000)*1000 + tv.tv_usec/1000; if (lasttime == ~0U || now - lasttime > (unsigned) long_interval) { if ((stat & stat_dirty) && nlines == maxlines) - redraw(circbuf, nlines, hpos, columns, stat, colcmd); + force = 1; lasttime = now; stat &= ~stat_dirty; } } + if (force) { + redraw(circbuf, nlines, hpos, columns, stat, curcmd); + stat &= ~(stat_dirty | stat_trgrd); + } + if (poll(pe, ((stat & stat_eof)) ? 1 : 2, poll_interval) <= 0) { if ((stat & stat_dirty) && nlines == maxlines) { - redraw(circbuf, nlines, hpos, columns, stat, colcmd); + redraw(circbuf, nlines, hpos, columns, stat, curcmd); stat &= ~stat_dirty; } if (kbd_state == kbd_esc || kbd_state == kbd_result) { kbd_state = kbd_cmd; - colcmd = 0; + curcmd = 0; clrline(); - drawstatus(stat, colcmd); + drawstatus(stat, curcmd); } } else { if ((stat & stat_eof) == 0 && pe[1].revents) { if ((line = getln(stdin))) { + if ((stat & stat_htmode)) + if (strstr(line, trigpat)) + stat |= stat_trgrd; if (nlines == maxlines) { dsdrop(circbuf[0]); memmove(circbuf, circbuf + 1, (nlines - 1) * sizeof *circbuf); circbuf[nlines - 1] = line; stat |= stat_dirty; + if ((stat & stat_ttmode)) + if (strstr(circbuf[0], trigpat)) + stat |= stat_trgrd; } else { circbuf[nlines++] = line; if ((stat & stat_susp) == 0) { snapshot[snaplines++] = dsref(line); clrline(); drawline(line, hpos, columns); - drawstatus(stat, colcmd); + drawstatus(stat, curcmd); } } } else { @@ -413,7 +453,7 @@ int main(int argc, char **argv) kbd_state = kbd_exit; else stat |= stat_eof; - redraw(circbuf, nlines, hpos, columns, stat, colcmd); + redraw(circbuf, nlines, hpos, columns, stat, curcmd); stat |= stat_eof; stat &= ~stat_dirty; if (!ferror(stdin)) @@ -431,7 +471,7 @@ int main(int argc, char **argv) switch (ch) { case 'q': case 3: kbd_state = kbd_exit; - if ((stat & (stat_eof | stat_susp))) { + if ((stat & (stat_eof | stat_susp | stat_htmode | stat_ttmode))) { clrline(); fflush(stdout); } @@ -467,7 +507,19 @@ int main(int argc, char **argv) kbd_state = kbd_colon; cmdbuf[0] = ch; cmdbuf[1] = 0; - colcmd = cmdbuf; + curcmd = cmdbuf; + break; + case '/': + kbd_state = kbd_htrig; + cmdbuf[0] = ch; + cmdbuf[1] = 0; + curcmd = cmdbuf; + break; + case '?': + kbd_state = kbd_ttrig; + cmdbuf[0] = ch; + cmdbuf[1] = 0; + curcmd = cmdbuf; break; } break; @@ -491,24 +543,35 @@ int main(int argc, char **argv) } break; case kbd_colon: + case kbd_htrig: + case kbd_ttrig: switch (ch) { case 27: case 13: case 3: kbd_state = kbd_cmd; stat |= stat_dirty; - if (ch == 13 && cmdbuf[1]) { - execute(cmdbuf); - stat &= ~stat_dirty; - kbd_state = kbd_result; - break; + if (ch == 13) { + if (kbd_state == kbd_colon && cmdbuf[1]) { + execute(cmdbuf); + stat &= ~stat_dirty; + kbd_state = kbd_result; + break; + } else if (cmdbuf[1]) { + dsdrop(trigpat); + trigpat = dsdup(cmdbuf + 1); + stat &= ~(stat_htmode | stat_ttmode); + stat |= (kbd_state == kbd_htrig) ? stat_htmode : stat_ttmode; + } else { + stat &= ~(stat_htmode | stat_ttmode); + } } - colcmd = 0; + curcmd = 0; break; case 8: case 127: { size_t len = strlen(cmdbuf); if (len == 1) { kbd_state = kbd_cmd; - colcmd = 0; + curcmd = 0; stat |= stat_dirty; } else { cmdbuf[--len] = 0; @@ -543,18 +606,19 @@ int main(int argc, char **argv) case kbd_result: kbd_state = kbd_cmd; stat |= stat_dirty; - colcmd = 0; + curcmd = 0; break; case kbd_exit: break; } if ((stat & stat_dirty)) { - redraw(circbuf, nlines, hpos, columns, stat, colcmd); + redraw(circbuf, nlines, hpos, columns, stat, curcmd); stat &= ~stat_dirty; - } else if (kbd_state == kbd_colon || kbd_state == kbd_result) { + } else switch (kbd_state) { + case kbd_colon: case kbd_htrig: case kbd_ttrig: case kbd_result: clrline(); - drawstatus(stat, colcmd); + drawstatus(stat, curcmd); } } } |