This article is part number 10 of the CLI design series.


In a world of terminal emulators within graphical environments, there is no longer a “standard” window size. 80x24 is still the default, sure, but it’s trivial for users to resize the terminal. Why does this matter?

Consider the most obvious case: the help message of your program. It is incredibly common to see carefully-formatted embedded strings into the program’s code designed to fit within a 80x24 window (which is especially true for the width of the text). Other than being a nightmare to maintain such a piece of code, what happens when the user resizes the terminal? If he increases the number of columns, the output of the application won’t make use of such extra space and will continue to use the same number of lines — a situation that may be undesirable in a widescreen setting. If he decreases the number of columns, the output of the application will get wrapped at weird boundaries.

So the question is: should you make your program detect the width of the screen and explicitly wrap its output on word boundaries so that proper alignment can be maintained? Or should it not? As usual, “it depends.” Let’s see the various cases.

Help messages, tables, etc.

For any kind of output that requires “pretty-printing” (e.g. anything that involves alignment of text into paragraphs or tabular environments), explicit screen wrapping is OK and, in my opinion, a good idea. If you do this, then the text will remain readable no matter what terminal size the user has chosen, as words will not be broken at unexpected points and any alignment will be respected.

Of course, this is easier said than done. Implementing proper line wrapping is tricky, especially if what you are trying to print has any kind of tabular data. The help message of the application is an obvious example of a piece of text explicitly for user consumption; it is also a piece of text composed of two columns: the column that lists the available options and the meaning of the arguments, and the column that provides their descriptions. Aligning these columns properly and automatically, regardless of the screen width, requires a fair amount of code but results in an interface that is nicer to use and easier to maintain.

Errors, warnings, informational messages, etc.

Don’t. Most informational messages printed by the application, be them errors, warnings or just status messages, are usually prefixed with the name of your binary. I’ve made the mistake in the past of trying to wrap these messages on screen boundaries in a smart way by splitting the long lines on word boundaries and repeating the line prefix on every line. The results were not great because this is broken for two reasons.

The first reason you should not do this is because the user is not accustomed to this behavior. When the user sees a long error message on the console, the user expects it to run over the right margin and continue on the next line. If you manually cut the message, it very quickly becomes non-intuitive because the output seems to contain more than one individual message due to the repetition of the prefix.

The second reason is that explicit line refilling breaks copy/paste functionality. Some terminal emulators are smart enough to understand when a line wraps and memorize that fact in their history so that, if you triple-click a long wrapped line, the terminal can select the full error message (even if wrapped) for later copying into the clipboard. If your program breaks lines explicitly, the same error message will appear as different lines to the terminal emulator and thus it will be impossible to just copy the whole message by selecting a single line.

As you can see in this commit to Kyua, I had to revert the automatic line breaking soon after submission due to the frustration that this inspired.

Comments from the original Blogger-hosted post: