diff options
Diffstat (limited to 'pw.c')
-rw-r--r-- | pw.c | 122 |
1 files changed, 83 insertions, 39 deletions
@@ -52,6 +52,7 @@ typedef struct grep { #define cmdsize 256 #define maxgrep 64 #define maxtrig 100 +#define snhistsize 20 typedef struct dstr { int refs; @@ -65,8 +66,8 @@ static int poll_interval = 1000; static int long_interval = 10000; static int regex_flags = 0; -static char **snapshot; -static int snaplines; +static char **snapshot[snhistsize]; +static int snaplines[snhistsize]; static grep grepstack[maxgrep]; static int ngrep; @@ -246,7 +247,7 @@ static void clreol(int nl) putchar('\n'); } -static void drawline(const char *line, int hpos, int columns) +static void drawline(const char *line, unsigned hpos, int columns) { size_t len = dslen(line); @@ -271,7 +272,7 @@ static void drawline(const char *line, int hpos, int columns) } } -static void drawstatus(int columns, unsigned stat, char *cmd) +static void drawstatus(unsigned hist, int columns, unsigned stat, char *cmd) { char status[cmdsize] = "", *ptr = status; size_t lim = sizeof status; @@ -283,9 +284,13 @@ static void drawstatus(int columns, unsigned stat, char *cmd) if (cmd) { snprintf(status, lim, "%s", cmd); - } else if ((stat & (stat_eof | stat_susp | stat_htmode | stat_ttmode | + } else if (hist > 0 || + (stat & (stat_eof | stat_susp | stat_htmode | stat_ttmode | stat_grep))) { + if (hist > 0) + ptr += snprintf(ptr, end - ptr, "HIST%u ", hist); + if ((stat & stat_eof)) ptr += snprintf(ptr, end - ptr, "EOF "); @@ -325,33 +330,42 @@ static void drawstatus(int columns, unsigned stat, char *cmd) fflush(stdout); } -static unsigned redraw(char **circbuf, int nlines, int hpos, +static void freebuf(char **buf, size_t size) +{ + for (size_t i = 0; i < size; i++) + dsdrop(buf[i]); +} + +static unsigned redraw(char **circbuf, int nlines, unsigned hpos, unsigned hist, int columns, unsigned stat, char *cmd) { if ((stat & (stat_dirty | stat_susp)) == stat_dirty && (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]); + if (snapshot[snhistsize - 1]) { + freebuf(snapshot[snhistsize - 1], snaplines[snhistsize - 1]); + free(snapshot[snhistsize - 1]); } - snaplines = nlines; + memmove(snapshot + 1, snapshot, sizeof *snapshot * (snhistsize - 1)); + memmove(snaplines + 1, snaplines, sizeof *snaplines * (snhistsize - 1)); + snapshot[0] = calloc(sizeof *snapshot[0], nlines); + snaplines[0] = nlines; printf("\r\033[%dA", nlines); for (int i = 0; i < nlines; i++) { - drawline(circbuf[i], hpos, columns); - snapshot[i] = dsref(circbuf[i]); + snapshot[0][i] = dsref(circbuf[i]); + drawline(snapshot[hist][i], hpos, columns); } stat &= ~(stat_dirty | stat_trgrd); } else if ((stat & stat_force)) { - printf("\r\033[%dA", snaplines); - for (int i = 0; i < snaplines; i++) - drawline(snapshot[i], hpos, columns); + printf("\r\033[%dA", snaplines[hist]); + for (int i = 0; i < snaplines[hist]; i++) + drawline(snapshot[hist][i], hpos, columns); stat &= ~stat_force; } else { clrline(); } - drawstatus(columns, stat, cmd); + drawstatus(hist, columns, stat, cmd); return stat; } @@ -409,7 +423,7 @@ static int getms(const char *str, char **err) return msec; } -static void execute(char *cmd, unsigned *pstat) +static void execute(char *cmd, unsigned *pstat, unsigned hist) { char *arg = cmd + 2 + strspn(cmd + 2, " \t"); @@ -430,8 +444,8 @@ static void execute(char *cmd, unsigned *pstat) break; } - for (int i = 0; ok && i < snaplines; i++) - if (fprintf(f, "%s\n", snapshot[i]) < 0) { + for (int i = 0; ok && i < snaplines[hist]; i++) + if (fprintf(f, "%s\n", snapshot[hist][i]) < 0) { sprintf(cmd, "write error!"); ok = 0; break; @@ -456,8 +470,8 @@ static void execute(char *cmd, unsigned *pstat) break; } - for (int i = 0; i < snaplines && ok; i++) - if (fprintf(p, "%s\n", snapshot[i]) < 0) { + for (int i = 0; i < snaplines[hist] && ok; i++) + if (fprintf(p, "%s\n", snapshot[hist][i]) < 0) { sprintf(cmd, "write error!"); ok = 0; break; @@ -645,7 +659,7 @@ int main(int argc, char **argv) if ((circbuf = calloc(sizeof *circbuf, maxlines)) == 0) panic("out of memory"); - if ((snapshot = calloc(sizeof *snapshot, maxlines)) == 0) + if ((snapshot[0] = calloc(sizeof *snapshot[0], maxlines)) == 0) panic("out of memory"); if (isatty(fd)) { @@ -688,7 +702,7 @@ int main(int argc, char **argv) sigaction(SIGWINCH, &sa, NULL); #endif - for (unsigned stat = stat_dirty, hpos = 0, + for (unsigned stat = stat_dirty, hpos = 0, hist = 0, kbd_state = kbd_cmd, kbd_prev = kbd_cmd, lasttime = ~0U, workbout = 1024, work = workbout, histpos = 0, cmdcount = UINT_MAX; @@ -708,7 +722,7 @@ int main(int argc, char **argv) if (feof(stdin) || (errno != EAGAIN && errno != EWOULDBLOCK)) { nfds = 1; stat |= stat_eof; - stat = redraw(circbuf, nlines, hpos, columns, stat, curcmd); + stat = redraw(circbuf, nlines, hpos, hist, columns, stat, curcmd); if (!ferror(stdin)) exit_status = 0; if (auto_quit) { @@ -766,10 +780,11 @@ int main(int argc, char **argv) } else { circbuf[nlines++] = line; if ((stat & stat_susp) == 0) { - snapshot[snaplines++] = dsref(line); + snapshot[0] = resizebuf(snapshot[0], snaplines[0], snaplines[0] + 1); + snapshot[0][snaplines[0]++] = dsref(line); clrline(); drawline(line, hpos, columns); - drawstatus(columns, stat, curcmd); + drawstatus(hist, columns, stat, curcmd); } } line = 0; @@ -783,9 +798,14 @@ int main(int argc, char **argv) winch = 0; if (ioctl(ttyfd, TIOCGWINSZ, &ws) == 0) { if (maxed) { + hist = 0; circbuf = resizebuf(circbuf, maxlines, ws.ws_row - 1); - snapshot = resizebuf(snapshot, maxlines, ws.ws_row - 1); - maxlines = ws.ws_row - 1; + snapshot[0] = resizebuf(snapshot[0], maxlines, ws.ws_row - 1); + for (int i = 1; i < snhistsize; i++) { + freebuf(snapshot[i], snaplines[i]); + free(snapshot[i]); + snapshot[i] = 0; + } } else { if (maxlines >= ws.ws_row) { maxlines = ws.ws_row - 1; @@ -795,8 +815,8 @@ int main(int argc, char **argv) if (nlines > maxlines) nlines = maxlines; - if (snaplines > maxlines) - snaplines = maxlines; + if (snaplines[0] > maxlines) + snaplines[0] = maxlines; columns = ws.ws_col; } @@ -832,17 +852,17 @@ int main(int argc, char **argv) } if (force) - stat = redraw(circbuf, nlines, hpos, columns, stat, curcmd); + stat = redraw(circbuf, nlines, hpos, hist, columns, stat, curcmd); if (poll(pe, nfds, pollms) <= 0) { if (pollms) { if ((stat & stat_dirty) && nlines == maxlines) - stat = redraw(circbuf, nlines, hpos, columns, stat, curcmd); + stat = redraw(circbuf, nlines, hpos, hist, columns, stat, curcmd); if (kbd_state == kbd_esc || kbd_state == kbd_result) { kbd_state = kbd_cmd; curcmd = 0; clrline(); - drawstatus(columns, stat, curcmd); + drawstatus(hist, columns, stat, curcmd); } } work = workbout += workbout / 4; @@ -859,7 +879,8 @@ int main(int argc, char **argv) ttyset(ttyfd, &tty_new); for (int i = 0; i < nlines; i++) puts(""); - stat = redraw(circbuf, nlines, hpos, columns, stat | stat_force, curcmd); + stat = redraw(circbuf, nlines, hpos, hist, columns, + stat | stat_force, curcmd); continue; } @@ -887,6 +908,18 @@ int main(int argc, char **argv) stat |= stat_force; } break; + case 'j': + if (hist > 0) { + hist--; + stat |= stat_force; + } + break; + case 'k': + if (hist < snhistsize - 1 && snapshot[hist + 1]) { + hist++; + stat |= stat_force; + } + break; case ' ': if ((stat & stat_eof) == 0) stat |= stat_susp; @@ -941,7 +974,7 @@ int main(int argc, char **argv) } break; case '+': - if (ws.ws_row && maxlines >= ws.ws_row - 1) { + if (hist > 0 || (ws.ws_row && maxlines >= ws.ws_row - 1)) { break; } else { unsigned count = (cmdcount == UINT_MAX) ? 1 : cmdcount; @@ -954,7 +987,12 @@ int main(int argc, char **argv) } circbuf = resizebuf(circbuf, maxlines, maxlines + 1); - snapshot = resizebuf(snapshot, maxlines, maxlines + 1); + snapshot[0] = resizebuf(snapshot[0], maxlines, maxlines + 1); + for (int i = 1; i < snhistsize; i++) { + freebuf(snapshot[i], snaplines[i]); + free(snapshot[i]); + snapshot[i] = 0; + } } break; case '0': @@ -994,6 +1032,12 @@ int main(int argc, char **argv) case 'H': ch = '0'; goto fakecmd; + case 'A': + ch = 'k'; + goto fakecmd; + case 'B': + ch = 'j'; + goto fakecmd; } switch (ch) { case 'A': @@ -1032,7 +1076,7 @@ int main(int argc, char **argv) } if (kbd_state == kbd_colon && cmdbuf[1]) { - execute(cmdbuf, &stat); + execute(cmdbuf, &stat, hist); if (cmdbuf[0] != 0) { kbd_state = kbd_result; break; @@ -1176,11 +1220,11 @@ int main(int argc, char **argv) } if ((stat & (stat_dirty | stat_force))) { - stat = redraw(circbuf, nlines, hpos, columns, stat, curcmd); + stat = redraw(circbuf, nlines, hpos, hist, columns, stat, curcmd); } else switch (kbd_state) { case kbd_colon: case kbd_trig: case kbd_result: case kbd_cmd: clrline(); - drawstatus(columns, stat, curcmd); + drawstatus(hist, columns, stat, curcmd); } } else { work = workbout += workbout / 4; |