.\" Pipe Watch ("pw") .\" Copyright 2022-2023 Kaz Kylheku .\" .\" BSD-2 License .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions are met: .\" .\" 1. Redistributions of source code must retain the above copyright notice, .\" this list of conditions and the following disclaimer. .\" .\" 2. Redistributions in binary form must reproduce the above copyright notice, .\" this list of conditions and the following disclaimer in the documentation .\" and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" .\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE .\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR .\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF .\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS .\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN .\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .TH PW 1 "10 Mar 2022" "Version 3" "Pipe Watch" .SH NAME pw \- Pipe Watch: monitor recent lines of output from pipe .SH SYNOPSIS command | pw [-i interval] [-l interval] [-n number-of-lines] [-dEB] .SH DESCRIPTION .I pw stands for Pipe Watch, a utility that continuously reads lines of text from a pipe or pipe-like source, passes them through a FIFO buffer, and maintains a display based on the occasional sampling of the contents of the FIFO buffer, with useful features such as triggering and filtering. Upon successful startup, .I 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 .B -n option) then .I 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: .IP 1. suspended mode is not in effect; and .IP 2. trigger mode is not in effect; and .IP 3. .I pw isn't executing in the background (see the .B Ctrl-Z command). .PP When the above conditions do not hold, and thus the display is being automatically refreshed, it is refreshed at these times: .IP 1. when there is some keyboard activity from the terminal; or .IP 2. when the interval period has expired without new input having been seen; or else .IP 3. whenever the long period elapses. .PP 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 .I 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 .B > and .B ? commands below. When standard input indicates end-of-data. .I pw terminates, unless the .B -d (do not quit) option has been specified, in which case it .I pw stays in interactive mode. The the end-of-data status is indicated by the string .B EOF being displayed in the status line after the data. .SH DISPLAY Lines displayed by .I pw are trimmed not to exceed the number of terminal columns. When a line is trimmed, it is terminated by the .B < character to indicate that there are more characters. The display may be scrolled interactively to read the long lines. Control characters are replaced as follows. The ASCII .I DEL character (127) is converted to the character sequence .B ^? and other ASCII control characters are converted to .BR ^@ , .BR ^A ", ..." .BR ^Z ", ..." .BR ^_ , except for .I TAB which is expanded into spaces according to the current tab stop. All other characters remain as-is. No attempt is made to account for the width of East Asian Unicode characters, and such. The above replacement of control characters happens when lines are read from the input source, not when they are being displayed. Therefore, changing the tab stop size has no effect on lines which are already captured and displayed. When the display is scrolled horizontally, the .B > 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 .BR >...< . .SH COMMANDS While reading data from standard input, .I 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 .B 0 command. The commands are: .IP "\fBq\fP, \fBCtrl-C\fP" Quit the program. Must be used multiple times in succession if a quit count greater than 1 is in effect. (See the .B -q option). .IP "[\fIcount\fP]\fB.\fP (period)" Repeats the most recent simple command, with the specified .I count or if .I count is omitted, with the original count of that command. If .I count is given, it also replaces the remembered count, for the next time the .B . (period) command is used without a count. Colon and trigger commands are not simple commands; they cannot be repeated by the period command. .IP "[\fIcount\fP]\fBl\fP, [\fIcount\fP]\fILeft Arrow\fP" Scroll the display to the left by .I count characters, defaulting to 8 if .I count is absent. .IP "[\fIcount\fP]\fBh\fP, [\fIcount\fP]\fIRight Arrow\fP" Scroll the display to the right by .I count characters, defaulting to 8 if .I count is absent. .IP "\fB0\fP, \fIHome\fP" Reset scroll to first column. .IP \fBCtrl-L\fP Refresh the display. .IP "[\fIcount\fP]\fB<\fP, [\fIcount\fP]\fB>\fP" Adjust the left vertical split, separating the left pane of the display. The left pane is an area of the display which always shows the prefix of each line, protected from horizontal scrolling. If the line is longer than the prefix, then either the .B > character appears to separate the left pane from the right pane, where the horizontally scrolling portion of remainder of the line appears, or else the .B | character appears to separate the left pane from the middle pane. The left pane has a zero width by default, so that it does not appear. These commands decrease and increase its width by the specified .I count which defaults to one character. .IP "[\fIcount\fP]\fB[\fP, [\fIcount\fP]\fB]\fP" Adjust the right vertical split, separating the middle pane of the display from the right pane. The middle pane is an area of the display which always shows some middle portion of each line, protected from horizontal scrolling. It may appear together with the left split (see the .B < and .B > commands) or by itself. The .B > character separates the middle pane from the right pane. The middle pane has a zero width by default, so that it does not appear. These commands decrease and increase the width by .I count which defaults to one character. Which portion of each line is shown in the middle pane is determined each time the middle pane is increased from zero width to nonzero: in other words, when the middle pane is changed from its hidden state to visible. At that moment, the current horizontal scroll position, together with the size of the left pane, determines the part of the line which is assigned to the middle pane. After that, the width of the pane can be adjusted without affecting what portion of the line it shows, independently of any horizontal scrolling adjustments occurring in the right pane. .IP "[\fIcount\fP]\fB{\fP, [\fIcount\fP]\fB}\fP" Adjust what portion of line is visible in the middle pane, incrementing or decrementing the viewport origin by .I count characters, defaulting to one, without changing the width. The effect is that the content of the middle pane appears to scroll horizontally to the right when .B } is used, or left when .B { is used. When no middle pane is being shown, these commands have no effect other than refreshing the display. .IP "\fBCtrl-I, Tab\fP" Toggle the highlighting of separator characters appearing in the line display. The when toggled on, the .BR > , .B < and .B | characters which indicate line truncation and pane separation are shown in inverse video (dark foreground, light background). .IP [\fIcount\fP]\fBt\fP Set the tab stop size. If count is omitted, zero, or greater than 16, then the value 8 is substituted. The tab stop size does not affect lines which have already been captured and displayed; tabs are expanded to spaces when lines are read from standard input and entered into the FIFO. .IP \fBCtrl-G\fP Shows the status of the display parameters, in a form which can be given to the .B -p option as an argument in order to re-create the same configuration. The parameters are five nonnegative integers, shown in decimal. The first for are in character units; the fifth is a bitmask value. The documentation for the .B -p option explains the numbers. .IP \fISpace\fP Suspend the acquisition of new snapshots. In suspended mode, input continues to pass through the FIFO, but new snapshots of data aren't taken. The display updates only due to horizontal scrolling, history browsing, resize, or .B Ctrl-Z suspend and resume. The status indicator .B SUSPENDED is displayed below the data. If the the status is already .B EOF then suspend mode cannot be entered. .IP \fIEnter\fP Cancel suspended mode, resuming display refresh. The display is refreshed immediately and the .B SUSPENDED status indicator disappears. .IP \fB:\fP Enter colon command mode. In colon command mode, the status line clears and a colon prompt appears there. An extended command can be entered. Pressing .I Enter in colon mode dispatches the command. Colon commands are documented in the COLON COMMANDS section below. Simple editing is available, described in the EDITING COMMANDS section below. .IP "[\fIpos\fP]\fB/[!]\fP\fIpattern\fP, [\fIpos\fP]\fB?[!]\fP\fIpattern\fP" Set a trigger if a non-empty .I pattern is specified, or else cancel a trigger if an empty pattern is specified. The .B / command specifies a .I "head-referenced trigger" mode, whereas .B ? specifies .I "tail-referenced trigger" mode. 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 .I 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 .B /foo or, equivalently, .B 1/foo triggers when the bottom line of the display contains a match for the expression .BR foo . Whereas .B 3/bar triggers when the third line from the bottom matches .BR bar . To cancel the .B 3/bar trigger without canceling the .B 1/foo trigger, the command .B 3/ can be used: .B 3/ with an empty pattern. Inversely, the tail-referenced pattern positions are from the top of the display. Thus .B ?foo or .B 1?foo trigger when the top line contains a match for .BR foo . If the value of .I 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 .B Ctrl-P and .BR 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 .BR 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 .I pos prefix or the .B ? or .B / command. Erroneous patterns, and the patterns of ignored commands are still entered into the history; empty patterns are not. The .I 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 .I pattern is preceded by the character .B ! then it is logically inverted. The trigger will activate on lines which do .I not match the pattern. To write an uninverted pattern which begins with .BR ! , precede the .B ! 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 .B / or .B ? command character. In trigger mode, the status string .B TRIG/ or .B 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. .IP "[\fIcount\fP]\fBa\fP, [\fIcount\fP]\fBd\fP" Advance or delay the currently active triggers by .I count lines, defaulting to 1. Advancing means that all of the triggers are assigned to more recently received lines closer to the head of the FIFO. on earlier data. Delaying is the opposite: the triggers are assigned to less recently received items, closer to the tail of the FIFO. The advance/delay commands will not move any trigger to a position which corresponds to a line that is not displayed. .IP "\fBk\fP, \fIUp Arrow\fP" Switch the display to earlier snapshot. Each time .I pw updates the display with a snapshot of data, the existing snapshot is entered into a history window, where it becomes snapshot 1. The previous snapshot 1 becomes 2, and so on. 19 snapshots are retained. The .B k command switches to an older snapshot: from current to 1, or from 1 to 2, and so on. When snapshot 1 to 19 is being displayed, the status line shows .BI HIST num where .I num is the snapshot number. Tip: the snapshot history is particularly useful when it is gathered by triggering. See the .B / and .B ? 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 .B 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. .IP "\fBl\fP, \fIDown Arrow\fP" Go back to earlier snapshot in history. If snapshot 1 is currently being displayed, then .I pw switches to the current snapshot and the .B HIST indicator in the status line disappears. .IP "[\fIcount\fP]\fB+\fP" Increases the display size by .I count lines, defaulting to 1. This doesn't come into effect immediately; the newly opened position must be filled by a line of data from standard input. There is no way to reduce the size dynamically. Resizing is limited to the terminal height, if the height is known. Resizing clears the snapshot history. The command is disabled when viewing snapshots from the history; it must be executed while viewing the current snapshot. .IP \fB#\fI Toggle the display of line numbers. In tail-referenced trigger mode, the lines are numbered from bottom to top. In all other situations, top to bottom. .IP \fBCtrl-Z\fI Suspends .IR pw , and indeed the entire surrounding process group, to the background to gain shell access. This requires a job control shell. When .IR pw is foregrounded again, it will refresh the display in a new text area below the 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. .IP \fBCtrl-D\fI Toggle the highlighting of differences between snapshots. When this mode is enabled, the currently displayed snapshot is compared to a previous snapshot. If any character in the currently displayed snapshot is different from the corresponding character of the previous snapshot, or if the previous snapshot does not have a corresponding character (because the corresponding line in the previous snapshot is shorter), then the character is displayed in inverse video. When the FIFO isn't full, or the snapshot history is empty, display of differences is suppressed, even if the mode is enabled. The moment the first snapshot recedes into a previously empty history, the first snapshot becomes the previous snapshot being compared with the current snapshot. If no history navigation takes place, then on subsequent snapshots, this stays the same: current will be compared with the .B "HIST 1" snapshot. When the history is navigated to view the previous snapshots, then the previous snapshot is always the previously displayed one which was left behind by the position change. For instance, when navigating from the .B "HIST 3" snapshot to the .B "HIST 4" snapshot, then 3 becomes the previous reference, and 4 current. The display highlights the differences from 3 to 4. Then if a reverse navigation step is performed from .B "HIST 4" back to .BR "HIST 3" , then 3 becomes currently displayed and 4 is the previous reference snapshot used for comparison: the display highlights the 4 to 3 differences, thus chronologically reversed. Furthermore, As the history window moves due to a new snapshot being taken, these positions stay the same. Whatever snapshots are currently 3 and 4 will be compared in the order that had been determined by the last navigational direction. .SH COLON COMMANDS First, some general remarks. The capture of snapshots, driving display refresh, doesn't pause during the editing of a colon command. If that is desired, the suspend command must be used first. The name of a colon command consists of a combination of one or more letters .B a through .R z , upper or lower case. Only the first two letters of a command are significant: for instance, the command .B :save is actually .BR :sa . Commands which are one letter long may not be written with superfluous letters, though. For instance, .B :grep is not understood as .B :g but as the (nonexistent) command .BR :gr . The command may be followed by an argument, which is separated from the command by exactly one space. If the argument does not begin with a lower-case letter, then the space may be omitted. If the command is followed by no characters at all, or exactly one space, then its argument is effectively the empty string; by convention, this is understood as there being no argument. When a command is executed, a message appears in its place, diagnosing an error situation or confirming a successful result. When such a message appears, it persists until a command is issued. If the command is Enter, it has only the effect of dismissing the message and restoring the usual status line, and not the usual effect of resuming .I pw out of suspended capture mode. Colon commands are saved in a history which may be navigated for recall using the up and down arrow keys or .B Ctrl-P and .BR Ctrl-N . The commands are: .IP "\fB:w\fP \fIfilename\fP" Write the currently displayed lines into the specified file. .IP "\fB:a\fP \fIfilename\fP" Append the currently displayed lines into the specified file. .IP "\fB:!\fP \fIfilename\fP" Pipe the currently displayed lines into the specified command. .IP "\fB:g\fP \fIpattern\fP, \fB:v\fP \fIpattern\fP" Push a .I grep pattern onto the grep stack. The .B :g command pushes a plain pattern; the .B :v command pushes a logically inverted pattern. The grep stack holds up to 64 patterns. If the pattern is successfully pushed onto the stack, it restricts which lines are admitted into the FIFO and available for display. The plain pattern admits only the lines which match .IR pattern ; the inverted pattern admits only lines which do .I not match .IR pattern . Lines which are already in the FIFO at the time a new pattern is introduced are not affected. The status line shows .B GREP .BI ( pattern "[, ...])" to indicate that grep mode is in effect, and gives the list of patterns, separated by commas. The inverted patterns are indicated by a leading .B ! character. .IP \fB:r\fP[\fB!\fP] Remove and forget the most recent grep pattern .RB ( :g or :v ) from the grep stack. If the stack depth decrements from 1, the grep mode is disabled and the .B GREP status line disappears. If the optional .B ! modifier is added to the command, then it pops the entire stack, forgetting all the patterns and disabling grep mode. The modifier is not an argument and may not be separated from the command. .IP "\fB:i\fP \fIreal\fP" Set the poll interval to the number of seconds specified by .IR real . See the description of the .B -i command line option for the argument format and semantics. .IP "\fB:l\fP \fIreal\fP" Set the long interval to the number of seconds specified by .IR real . See the description of the .B -i command option for the argument format and the .B -l option for the semantics. .PP .IP "\fB:E\fP, \fB:B\fP" Enable extended regular expressions (EREs) or basic regular expressions (BREs), respectively. If no .B -E option is given to the program, then BRE mode is in effect on start up. This setting does not affect the meaning of patterns that are currently in effect in the grep stack or in the trigger. The setting affects new patterns that will subsequently be presented to the program. Note that the currently active patterns shown in the status line are not accompanied by any indication of whether they were compiled as ERE or BRE. Any other command string results in a brief error message. .IP "\fB:f\fP \fIinteger\fP" Capture a triggered snapshot only once every .I integer times the trigger event occurs If .I integer is 0 or 1, then trigger on every matching event. When .I integer is 1 or more, .I pw counts the number of trigger events which occur. Only when the counter reaches the specified value is a snapshot taken; and then the counter is reset to zero. There is an internal difference between the value 0 and 1 in that 0 disables the feature: no counting takes place. .IP "\fB:c\fP [\fIinteger\fP]" Limit the number of trigger-driven captures to the count specified by .IR integer , after which capture is automatically suspended, as if by the .B Space command. If .IR integer is omitted, then the count of snapshots is reset to zero, without affecting the configuration that was previously specified by a .B :c command with an argument. If .IR integer is zero, then the counting mode is disabled; capture does not suspend regardless of how many capture events occur. Note that capture events are counted, not trigger events. Thus, if the capture frequency is reduced using the .B :f command, then the ignored trigger events are not counted. When the required number of captures is taken, and capture is suspended, the trigger count is reset to zero. Thus when the .B Enter command is used to resume capture, the same number of capture events will have to occur again before the next automatic suspension. .IP "\fB:p\fP [\fIinteger\fP[,\fIinteger\fP[,\fIinteger\fP[,\fIinteger\fP[,\fIinteger\fP[,\fIinteger\fP]]]]]] Sets the display parameters, exactly in the manner of the .B -p option. Any parameters not specified are reset to their default initial values: zero in the case of character positions, off in the case of flags. .IP "\fB:sa\fP [\fIfilename\fP]" Save a snapshot of the configuration state to the specified file. The state is saved as a sequence of colon and trigger commands, such that the resulting file is suitable as an argument to the .B -f option. If saving the state to .I filename is successful, then when .I pw is started up with .I filename as the argument to the .B -f option, the grep stack, trigger state and display parameters will be stored to exactly the same configuration that existed at the time the state was saved. .SH EDITING COMMANDS The colon command mode and trigger entry modes support rudimentary editing. The commands are as follows: .IP "\fBCtrl-B\fP, \fILeft Arrow\fP" Move the cursor one character to the left. .IP "\fBCtrl-F\fP, \fIRight Arrow\fP" Move the cursor one character to the right. .IP "\fBCtrl-A\fP" Move the cursor to the beginning of the line. .IP "\fBCtrl-E\fP" Move the cursor to the end of the line. .IP \fBBackspace\fP Erase the character to the left of the cursor. The ASCII BS and DEL characters are both recognized as backspace (an amazing trick not yet mastered by Unix TTY's). If backspace is used in an empty line, the respective mode terminates without executing a command or setting a trigger. .IP \fBCtrl-D\fP Delete the character under the block cursor, or to the right of a line or I-beam cursor. .IP \fBCtrl-W\fP Delete the word to the left of the cursor, including any trailing whitespace between the word and the cursor. .IP \fBCtrl-U\fP Erase the all the characters to the left of the cursor. .IP \fBCtrl-K\fP Erase the the character under the block cursor, or to the right of a line or I-beam cursor, and all characters which follow. .IP "\fBCtrl-C\fP, \fBESC\fP" Leave edit mode, without executing a colon command or setting a trigger. .SH OPTIONS .IP "\fB-i\fP \fIreal\fP" Set the poll interval to number of seconds specified by .IR real . This is is a floating-point constant such as 3 or 1.5. Exponential notation such as 5E-1 (equivalent to 0.5) is permitted. This interval determines the input poll timeout of .IR pw 's input processing loop. If no data arrives from the primary input, or from the TTY for this amount of time, a timeout occurs, and the display is refreshed if the FIFO has changed since the last refresh. The default poll interval is 1s. .IP "\fB-l\fP \fIreal\fP" Set the long update interval to number of seconds specified by .IR real . The format is the same as .BR -i , and the default value is 10s. Every time the long update interval passes, the display is updated, if the FIFO has changed since the last update. This happens even when input is arriving too rapidly to permit the poll timeout to take place. The purpose of the long interval is to ensure that there are updates even when the data source continuously and rapidly produces data, and there is no TTY input activity. The long interval should be at least several times longer than the short interval. The granularity of the timing of the long interval updates depends on the poll interval; in the absence of TTY input, .I pw will not perform any display updates more often that the poll interval, even if the long interval is made smaller than the poll interval. .IP "\fB-n\fP \fIinteger\fP" Set the number of lines .I N to the specified decimal integer value. The default value is 15. This value must be positive, and is clipped to the number of display lines available in the terminal, less one. .IP "\fB-m\fP \fIinteger\fP" Set the maximum line length to .IR integer . The default value is 4095. Values smaller than 72 are adjusted to 72. The length is measured in display characters, not original characters. A control character like .B ^C counts as two characters. The behavior of .I pw is that when it is collecting a line, and the line has reached the maximum length, it keeps reading characters from the standard input, but discards them, while remaining responsive to TTY input. .IP \fB-d\fP Disable auto-quit: when no more input is available, instead of updating the display one last time and terminating, .I pw will updating the status to .B EOF and staying in the interactive mode. This is useful when the last portion of the input is of interest, and contains long lines that require horizontal scrolling. .IP "\fB-q\fP \fIinteger\fP" Install a quit count specified by .I integer which must be positive. The quit count determines how many times the .B q or .B Ctrl-C commands have to be issued in succession before .I pw will quit. This is a safeguard against quitting accidentally. The default is 1: the commands quit immediately. .IP \fB-E\fP Enable extended regular expressions (EREs). By default, regular expressions processed by .I pw are treated as basic regular expressions (BREs). The mode can be switched at run time using the .B :E and .B :B commands. .IP \fB-B\fP Disable extended regular expressions (EREs), switching to basic (BREs). Since that is the default, this option has no effect unless it appears after a .B -E option. .IP "\fB-g\fP [\fB!\fP]\fIpattern\fP" Push .I pattern onto the grep stack as if using the .B :v or .B :g commands, but prior to startup, and hence prior to reading any input. For more detail, see the .B :g and .B :v run-time commands. A leading .B ! before the pattern indicates inversion, like what is arranged by the .B :v command. Similarly to the convention in the trigger command syntax, to specify a non-inverted pattern which starts with a literal .B ! character, precede that .B ! character with a backslash. This convention is part of the .B -g option's argument syntax, and not a regular expression escape sequence, and is not recognized other than before a non-inverted pattern. If the .B -g option is used one or more times, the status display will show .B GREP followed by the patterns enclosed in parentheses, as usual. Patterns pushed by .B -g may be removed interactively with the .B :r command. Whether the .I pattern argument of a .B -g is compiled as a BRE or ERE depends on whether a .B -B or .B -E option more recently appeared before that .B -g option. If neither option is used, then .I pattern is interpreted as a BRE. .IP "\fB-p\fP [\fIinteger\fP[,[\fIinteger\fP[,\fIinteger\fP[,\fIinteger\fP[,\fIinteger\fP[,\fIinteger\fP]]]]]] Specify the display parameters, as comma-separated non-negative integers. The meaning of these integer values is: .RS .IP 1. horizontal scroll position; .IP 2. width of left pane; .IP 3. width of middle pane; .IP 4. middle pane view offset; .IP 5. bitmask of several flags controlling line number display .RB ( # command), highlighting .RB ( Ctrl-I/Tab command), and suspended mode .RB ( Space command), the values being internal and undocumented; and .IP 6. the tab stop size. .PP All five numbers are optional, and default to zero if omitted. Since .B -p requires an argument, the only way all four may be omitted is if a blank or empty argument is given. The tab stop must be in the range 0 to 16. A value of 0 is interpreted as 8. The .B Ctrl-G command displays these same parameters in the same format, so it is possible to set them up interactively and then copy the values shown by .BR Ctrl-G . .RE .IP "\fB-e\fP \fIcommand\fP" Execute a colon or trigger command. For instance .ft B -e :c15 .ft R sets the capture count to 15. Note that the colon is included in the command. Trigger commands may be preceded by a count. For example: .ft B -e 3/^Failed .ft R sets a head-referenced trigger for the pattern .B ^Failed matching against line 3 of the FIFO. .IP "\fB-f\fP \fIfile\fP" Read colon and trigger commands from .I file and execute them. Each line of .I file must contain either a command in the same form as the argument of the .B -e option, or else a comment indicated by the first character being .B # (hash). If any line is diagnosed as erroneous, a diagnostic is issued and execution continues. In this case, .I pw will terminate unsuccessfully after .I file is read. Command lines with leading whitespace are invalid, and trailing whitespace counts as a command character (for example, as a constituent of a pattern), .SH ENVIRONMENT .I pw ignores the .B TERM environment variable, requiring an ANSI terminal. .I pw requires the following conditions to hold in regard to its execution environment, otherwise it terminates with an error diagnostic: .IP 1. It must be possible to open the .B /dev/tty device, .IP 2. Standard input is either not a TTY device, or else not the same TTY device as .BR /dev/tty . .PP .SH TERMINATION STATUS If .I 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). .SH BUGS 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 .B :w to save the displayed data somewhat compensate for this. During the .B :! 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 .BI :g pattern 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 .I 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. There is some funniness when line number mode is turned on and .I pw is in the middle of filling the FIFO to match the display size. You will see line number values of zero, which then correct themselves when the display is refreshed. This is by design, for very good reasons. Patches to try to fix this will be rejected in the strongest terms. Difference highlighting mode is confusing when comparing snapshots that overlap, or that are entirely unrelated. The way it is implemented makes it primarily useful with snapshots that are triggered and filtered for similarity. It doesn't track insertions or deletions of characters; If 999 changes to 1000, the rest of the line will be be different, except for characters that are still the same by coincidence. .SH SEE ALSO .IR pw-relnotes ( 5 ) .SH AUTHOR Kaz Kylheku .SH COPYRIGHT Copyright 2022-2023, BSD2 License.