diff options
-rw-r--r-- | pw.1 | 28 | ||||
-rw-r--r-- | pw.c | 80 |
2 files changed, 85 insertions, 23 deletions
@@ -394,6 +394,34 @@ cursor, avoiding overwriting anything in the terminal. Thus suspending and then immediately foregrounding provides a way to save a snapshot of the window into the terminal sessions history. +It is possible to execute +.I pw +in the job control background. This may happen in two ways: either the +.I pw +job is backgrounded from the beginning using the shell's +.B & +operator, or else it is suspended with +.B Ctrl-Z +and then requested to execute in the background using the shell's +.B bg +command. When +.I pw +executes in the background, it continues reading from the pipe and discard +input, but doesn't update the display. This useful behavior allows +.I pw +to be used for monitoring multiple programs which continuously produce +output, all from the same job control session. Redirecting the output +of such programs to +.I pw +and putting them into the background effectively muffles their output, +while allowing them to execute indefinitely. Because +.I pw +is reading their output, they never block on a pipe write. +At any time any such a backgrounded job can be brought into the foreground to +visualize its most recent output in the +.I pw +display. + .SH COLON COMMANDS First, some general remarks. Display refresh doesn't pause during the editing @@ -68,7 +68,8 @@ enum status_flags { stat_trgrd = 32, // triggered flag stat_grep = 64, // grep mode stat_force = 128, // force refresh even if clean - stat_lino = 256 // render line numbers + stat_lino = 256, // render line numbers + stat_bkgnd = 512 // running in the background }; typedef struct grep { @@ -361,6 +362,9 @@ static void drawstatus(unsigned hist, int columns, unsigned stat, char *cmd) char status[cmdsize] = "", *ptr = status; size_t lim = sizeof status; + if ((stat & stat_bkgnd)) + return; + if (columns - 1 < (int) lim) lim = columns - 1; @@ -426,6 +430,9 @@ static unsigned redraw(char **circbuf, int nlines, unsigned hpos, unsigned hist, { int updln = 0; + if ((stat & stat_bkgnd)) + return stat; + if ((stat & (stat_dirty | stat_susp)) == stat_dirty && (stat & (stat_htmode | stat_trgrd)) != stat_htmode && (stat & (stat_ttmode | stat_trgrd)) != stat_ttmode) @@ -679,9 +686,18 @@ static char **resizebuf(char **buf, size_t nlfrom, size_t nlto) return buf; } +int isbkgnd(FILE *tty) +{ + int fd = fileno(tty); + pid_t grp = getpgrp(); + pid_t fgrp = tcgetpgrp(fd); + return (grp != fgrp); +} + int main(int argc, char **argv) { char *line = 0; + unsigned stat = 0; FILE *tty = fopen("/dev/tty", "r+"); int maxlines = 15, nlines = 0, maxed = 0; int opt; @@ -785,19 +801,22 @@ int main(int argc, char **argv) tty_new.c_cc[VMIN] = 1; tty_new.c_cc[VTIME] = 0; - ttyset(ttyfd, &tty_new); - setvbuf(tty, NULL, _IONBF, 0); if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) panic("unable to set stdin nonblocking"); + if (!isbkgnd(stdout)) + ttyset(ttyfd, &tty_new); + else + stat = stat_bkgnd; + #ifdef SIGWINCH sa.sa_handler = sigwinch; sigaction(SIGWINCH, &sa, NULL); #endif - for (unsigned stat = stat_dirty, hpos = 0, hist = 0, + for (unsigned hpos = 0, hist = 0, kbd_state = kbd_cmd, kbd_prev = kbd_cmd, lasttime = ~0U, workbout = 1024, work = workbout, histpos = 0, cmdcount = UINT_MAX; @@ -871,7 +890,7 @@ int main(int argc, char **argv) } } else { circbuf[nlines++] = line; - if ((stat & stat_susp) == 0) { + if ((stat & (stat_susp | stat_bkgnd)) == 0) { snapshot[0] = resizebuf(snapshot[0], snaplines[0], snaplines[0] + 1); snapshot[0][snaplines[0]++] = dsref(line); clrline(); @@ -929,22 +948,41 @@ int main(int argc, char **argv) work = workbout; - if (!force) - { - struct timeval tv; - unsigned now; - - gettimeofday(&tv, NULL); - 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) - force = 1; - lasttime = now; + if ((stat & stat_bkgnd)) { + if (!isbkgnd(stdout)) { + stat &= ~stat_bkgnd; + ttyset(ttyfd, &tty_new); + for (int i = 0; i < nlines; i++) + puts(""); + stat = redraw(circbuf, nlines, hpos, hist, columns, + stat | stat_force, curcmd); + } else { + if ((stat & stat_eof)) { + sleep(1); + continue; + } else { + pe[0].events = 0; + } } } - if (force) - stat = redraw(circbuf, nlines, hpos, hist, columns, stat, curcmd); + if ((stat & (stat_bkgnd | stat_susp)) == 0) { + if (!force) { + struct timeval tv; + unsigned now; + + gettimeofday(&tv, NULL); + 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) + force = 1; + lasttime = now; + } + } + + if (force) + stat = redraw(circbuf, nlines, hpos, hist, columns, stat, curcmd); + } if (poll(pe, nfds, pollms) <= 0) { if (pollms) { @@ -967,12 +1005,8 @@ int main(int argc, char **argv) if (ch == ctrl('z')) { ttyset(ttyfd, &tty_saved); + stat |= stat_bkgnd; kill(0, SIGTSTP); - ttyset(ttyfd, &tty_new); - for (int i = 0; i < nlines; i++) - puts(""); - stat = redraw(circbuf, nlines, hpos, hist, columns, - stat | stat_force, curcmd); continue; } |