💾 Archived View for dmerej.info › blog › 0097-crafting-command-line-outputs.gmi captured on 2022-01-08 at 13:43:27. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2021-11-30)

-=-=-=-=-=-=-

2019, Mar 25 - Dimitri Merejkowsky
License: CC By 4.0

I've used many command line tools. It always makes me feel happy when I come across a tool that has a nice, usable and friendly output. I always try to make those I create or maintain as good as possible in this regard.

Along the way, I've learned a few tricks I'd like to share with you.


Start with the contents

When designing command line output, start with the *contents*, not the style. In other words, think about *what* to print before thinking about *how* to print it - this is helpful in a lot of other situations.

Error messages

The absolute minimum your command line tool needs are *good error messages*. Pay attention to those - good error messages can go a long way in helping your users and may even save you from having to answer a bunch of bug reports!

A good error message should:

Bad example:

Could not open cfg file. ENOENT 2

Good example:

Error while reading config file (~/.config/foo.cfg)
Error was: No such file or directory
Please make sure the file exists and try again

Standard out and standard error

Speaking of error messages, note that your can choose to write text to *two* different channels (often called `stdout` and `stderr` for short). Use `stderr` for error messages and error messages only. People sometimes need to hide "normal" messages from your tool, but they'll need to know about those errors!

Colors

Things to know about colors:

https://bixense.com/clicolors/[1]).

1: https://bixense.com/clicolors/

Progress

If your comman-line tool does some lengthy work, you should output *something* to your users so that they know your program is not stuck.

The best possible progress indicator contains:

`wget` does that really well. Your favorite language probably has one or two ready-to-use libraries for this.

If you can't achieve the full progress bar, as a lightweight alternative you can just display a counter: (`1/10`, `2/10`, etc.). If you do so, please make sure the user knows *what is being counted* !

Remove noise

We already saw that people maybe running your tool without a terminal attached. In this case, you should skip displaying progress bars and the like.

Also, try to remove things that are only useful when debugging (or don't display them by default).

This includes the time taken to perform a given action (unless it's useful to the end-user, like if you are writing a test runner for instance). Also, don't forget that users can and will prefix their command line with `time` to get precise results if they need to.

A good technique to remove noise is to completely erase the last line before writing a new one.

Here's how to do it in Python:

size = shutil.get_terminal_size()   # get the current size of the terminal
print(first_message, end="\r")
do_something()
print(" " * size.columns, end="\r")  # fill up the line with blanks
                                     # so that lines don't overlap
print(second_message)

Of course, this only works if the user does not need to know about the whole suite of messages!

Tests

End-to-end tests are a great way to tweak the output without having to do a bunch of setup by hand, *and* check the error messages look good.

Parting words

Well, that's all I've got today. Please keep those tips in mind when creating your own command line tool, and if you find a program that does not adhere to these rules, feel free to send patches. Until next time!

----

Back to Index

Contact me