Upon successful startup, pw simultaneously monitors its standard input for the arrival of new data, as well as the TTY for interactive commands. Lines from standard input are placed into a FIFO buffer. While the FIFO buffer is not yet full, lines are displayed immediately. After the FIFO buffer fills up with the specified number of lines (controlled by the -n option) then pw transitions into the free-running mode in which, old lines are removed from the tail of the FIFO as new ones are added to the head, and the display is no longer refreshed for every new line arriving into the FIFO.
In free-running mode, the display is automatically refreshed with the latest FIFO data only if:
When the above conditions do not hold, and thus the display is being automatically refreshed, it is refreshed at these times:
In other words, while the input is rapidly producing data, and there is no keyboard input, the display is updated infrequently, only according to the long interval.
If pw is executing in the foreground, and if display updates aren't suspended, and if trigger mode is effect, then the display updates automatically only when a trigger is activated by a pattern match on the FIFO contents. Trigger mode is activated using the > and ? commands below.
When standard input indicates end-of-data. pw terminates, unless the -d (do not quit) option has been specified, in which case it pw stays in interactive mode. The the end-of-data status is indicated by the string EOF being displayed in the status line after the data.
Lines displayed by pw are trimmed not to exceed the number of terminal columns. When a line is trimmed, it is terminated by the < character to indicate that there are more characters. The display may be scrolled interactively to read the long lines.
The ASCII DEL character (127) is displayed as ^? and ASCII control characters are displayed as ^@, ^A, ... ^Z, ... ^_. All other characters are sent to the display as-is. No attempt is made to account for the width of East Asian Unicode characters, and such.
When the display is scrolled horizontally, the > character appears at the start of each line to indicate this state. Thus, if neither end of a long line is currently visible, then its visible portion appears delimited by >...<.
While reading data from standard input, pw monitors the TTY for input, providing the following commands.
The commands may be prefixed by a numeric argument, which is ignored by commands to which it is not applicable. The numeric argument is specified by entering digits, which are not echoed. The last 3 digits of the input are retained, so that the argument has an effective range from 0 to 999. Leading zeros are interpreted as the 0 command.
The commands are:
Under trigger mode, the display is suspended, similarly to suspend mode. It is only refreshed when data arrives into the FIFO such that the state of the FIFO then matches certain regular expression patterns.
A head-referenced trigger is relative to most recently received data which appears at the bottom of the display. A tail-referenced trigger is on least-recently received data, relative to the top of the display. If one or more triggers are set, then trigger mode is in effect. If all triggers are removed, trigger mode is canceled.
Tail-referenced and head-referenced triggers are mutually exclusive. If a tail-referenced trigger command is successfully executed, then all head-referenced triggers are removed. Vice versa, a tail-referenced trigger command cancels all head-referenced triggers.
If the numeric prefix pos is omitted, or specified as zero, then it defaults to 1. The prefix specifies the relative position of the pattern. A head-referenced trigger's position is relative to the most recent data in the FIFO, and therefore is effectively a reverse line number relative to the bottom of the display. For example /foo or, equivalently, 1/foo triggers when the bottom line of the display contains a match for the expression foo. Whereas 3/bar triggers when the third line from the bottom matches bar. To cancel the 3/bar trigger without canceling the 1/foo trigger, the command 3/ can be used: 3/ with an empty pattern. Inversely, the tail-referenced pattern positions are from the top of the display. Thus ?foo or 1?foo trigger when the top line contains a match for foo.
If the value of pos specifies a line beyond the display range, or a value greater than 100, the command is ignored.
Trigger patterns saved in a history which may be navigated for recall using the up and down arrow keys or Ctrl-P and Ctrl-N. While the trigger pattern is being edited, the current set of triggers remains in effect. Editing a trigger pattern may be canceled with ESC, in which case it is not entered into the history and and the trigger command isn't executed. The history stores only the patterns, not the pos prefix or the ? or / command. Erroneous patterns, and the patterns of ignored commands are still entered into the history; empty patterns are not.
The pattern of a newly issued command interpreted as either an extended regular expression (ERE) or (BRE) depending on the current setting. This is true even if it is recalled from a history entry which had been created under a different mode.
If the pattern is preceded by the character ! then it is logically inverted. The trigger will activate on lines which do not match the pattern. To write an uninverted pattern which begins with !, precede the ! with a backslash. This is not a regex character escape sequence, but part of the trigger command syntax. It must not be used anywhere in a pattern, other than immediately after the / or ? command character.
In trigger mode, the status string TRIG/ or TRIG? is shown followed by the list of triggers in parentheses. Patterns which have a position other than 1 are preceded by the position shown in square brackets.
Tip: the snapshot history is particularly useful when it is gathered by triggering. See the / and ? commands above. Triggered snapshots can reveal recurring patterns in the input. The history can be used to identify differences among triggered snapshots which appear and disappear too rapidly to be read in real time. One of the possible uses of that information is to refine the trigger patterns in order to capture snapshots that are more similar to each other. In the absence of triggering, historic snapshots may be completely unrelated.
Tip: it is usually useful to pause the acquisition of snapshots when browsing the history: see the Space command above. Snapshot acquisition is be observed while browsing the history, since every historic snapshot moves to a higher number when a snapshot is taken, while the displayed number stays the same, and the display updates accordingly.
Resizing clears the snapshot history. The command is disabled when viewing snapshots from the history; it must be executed while viewing the current snapshot.
It is possible to execute pw in the job control background. This may happen in two ways: either the pw job is backgrounded from the beginning using the shell's & operator, or else it is suspended with Ctrl-Z and then requested to execute in the background using the shell's bg command. When pw executes in the background, it continues reading from the pipe and discard input, but doesn't update the display. This useful behavior allows 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 pw and putting them into the background effectively muffles their output, while allowing them to execute indefinitely. Because 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 pw display.
First, some general remarks. Display refresh doesn't pause during the editing of a colon command. If that is required, the suspend command must be used. The space between the command and the argument may be omitted. After a command is executed, a result message appears in its place. This message persists over the poll interval period. The longer the poll interval (-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 Ctrl-P and Ctrl-N.
Any other command string results in a brief error message.
pw ignores the TERM environment variable, requiring an ANSI terminal.
pw requires the following conditions to hold in regard to its execution environment, otherwise it terminates with an error diagnostic:
If pw reaches EOF on standard input without encountering a read error, then its termination status will be successful. This is regardless of whether it automatically quits, or whether it stays in interactive mode and then quits due to a quit command. If the data ends prematurely due to a read error, or if the program is asked to quit before all of the data has been read, then unsuccessful termination status will be indicated.
Incorrect usage, such as nonexistent options or bad arguments to options, result in a diagnostic on standard error and an unsuccessful termination.
Unexpected conditions like out of memory result in abnormal termination (abort).
This was written over the course of a couple of hours, and tested only interactively.
Many of the issues which follow are easy; patches welcome.
The display format, such as the handling of control characters, is hard-coded.
The program uses hard-coded ANSI sequences, so it doesn't support interesting old terminals. On the other hand, it carries no dependency on any terminal abstraction library/data.
There is no support for unwrapping long lines, which would be useful for copy and paste. However, the features like :w to save the displayed data somewhat compensate for this.
During the :! command's execution, the TTY settings are not restored.
The timeout isn't applied to the arrival of data into the FIFO, but on the arrival of data into the program. Therefore, the grep stack feature doesn't necessarily do what you want in terms of the timeout-based refresh behavior. Consider a situation in which ten lines are arriving per second at a steady rate. The default 1s timeout therefore never goes off. The long refresh interval is what is updating the display, every 10s by default. Now suppose you put in a :gpattern command which only passes every 20th line. Effectively, it now looks as if a line appears every 2s, and so the 1s timeout should be going off to refresh the display. Unfortunately, that's not how it works. The program is still receiving ten lines per second from standard input, and that's where the timeout is applied. Until that is fixed, the way to get more timely refresh behavior under heavy filtering is to play with the long interval.
If the terminal window is resized to a narrower size, many terminals wrap any lines that would get truncated by the operation and this makes a mess of the display. While pw recovers the display area, wrapped lines get pushed above it and remain. This issue is likely unfixable, other than by implementing a text-editor-like full screen mode which has no scroll back above the display, and which recovers the prior content when exiting.