$ cats nobody@supertxt.net:specs/report-progress.s.txt

# Reporting Progress

Command-line tools can take significant time to complete. Sometimes it's unclear whether progress is being made unless there happens to be a steady stream of output going to stdout. People will press the enter key from time-to-time to check whether the shell is still responsive. In some cases tools will make an effort to use the terminal to animate a progress bar, such as curl. There are also tools that made unique design choices and accept a control key sequence (e.g. Ctrl+T for BSD/macOS dd command).

Each of these approaches have certain limitations. Animating a progress bar using the terminal only works when in a terminal context, which a SuperTXT browser may not provide. Pressing enter while a command is running puts extra newlines in your output buffer. Using special control key sequences doesn't work if the terminal doesn't support them. Above all none of these approaches are standardized.

A standardized way for a command to provide progress would be helpful in a number of ways. It helps the tool to provide a good user experience. The tool is freed from having to manage the rendering of that progress for its users. Programs, such as browsers and shells can make use of the progress information to provide a consistent experience across tools.

note: Any standard should take into consideration that tools can run outside of an environment that supports enhanced progress reporting. This is important for incremental adoption and tooling independence.

## Communicating Progress via Stderr

Stderr is a place where extra information about the process can be communicated. Sometimes it's error/warning messages, or even tips. It's commonly a catch-all for information that's not the output for the command, possibly causing corruption in that output if it was combined with it. Unix shells will generally interleave the stderr with the stdout, but there are ways to squelch the stderr if it's unwanted through redirection. Also, redirection or piping of stdout doesn't include the stderr information. In general, there is an expectation that stderr can be read by the user. Stderr is a reasonable place to put progress information.

Here's an example of a progress report line:

PROGRESS: [12345] (1000/1230) Establishing connection...<LF>
^^^^^^^^   ^^^^^   ^^^^ ^^^^  ^^^^^^^^^^^^^^^^^^^^^^^^^^
tag        id      fraction   label 

In order to distinguish a progress report line from any other kind of line that might show up on stderr the prefix for the progress reports is always "PROGRESS:". It's capitalized so that it can be visually distinguished in a regular shell and is also easily "grepped."

The second token is a unique identifier for the report. Whether you're running a single command-line tool that is internally doing multiple concurrent activities or there's a complex command that involves pipes, progress can be coming from multiple places. All of this information comes together in stderr. The unique identifier is there to distinguish between these various concurrent parts. The ID is a range from 0 - 4194304, which is the maximum PID for Linux, which can be one way to avoid collisions. Another is to generate a pseudorandom number in this range, large enough to have a very low probability of collisions. For very simple command-line tools the PID is likely sufficient and easy to get for this purpose.

The fraction can provide the user with a sense of the progress of a task, if possible. In cases where that kind of estimation is not possible then the fraction can be something static like "(0/1)" until it's complete and moves to "(1/1)". The denominator is permitted to grow as the task gathers unexpected work, while the numerator is expected to always increase without exceeding the denominator. If the numerator is ever reported to be equal to the denominator the task is considered complete and there should be no additional progress reports with this unique identifier. Otherwise, progress reports with the same fraction are permitted, possibly on a 3 second timer to indicate liveliness.

The label portion at the end is free-form text and gives task-specific feedback on what is happening at that moment. It can also provide unit-specific details, such as bytes transferred, or elapsed time. Tooling that parses the progress reports should pass along this information verbatim.

warning: The progress reports are potentially interleaved with other tasks from other processes. In order to prevent the lines from becoming mixed together it is important for the tool to flush the progress report as a single line with the linefeed character at the end. Note that the entire report must be smaller than PIPE_BUF constant on the system.


You can provide a conventional comment on this document.

ssh nobody@supertxt.net ccmnt specs/report-progress.s.txt <<EOF
suggestion: Here's my actionable suggestion.