Style question: writing multi-line usage messages

Bruce Evans brde at optusnet.com.au
Wed May 5 21:46:07 UTC 2010


On Tue, 4 May 2010, Gary Jennejohn wrote:

> On Tue, 4 May 2010 19:17:49 +1000
> Peter Jeremy <peterjeremy at acm.org> wrote:
>
>> I would appreciate some input on the preferred style for writing
>> multi-line usage messages.  Should:

I have strong opinions about this of course.

>> 1) printf() print a series of 1-line strings

I prefer 1 printf per output line in most cases, but for printing several
lines of literals as in some usage messages, I prefer (2), since (2) allows
making the source string look like the output messsage only in simple cases
with literal strings.

>> 2) should string gluing be used to turn multiple strings into one for printing

I prefer to only use string gluing at newline boundaries.

>> 3) should continuation lines be used to create a single string

I prefer to avoid using continuation lines.

>> I can't see anything in style(9) to cover this.

The examples of printfs in style(9) are only for usage(), and they
are too simple to cover the multi-line case.

>> Variants of the tunefs(8) usage() function follow as examples:
>>
>> void
>> usage(void)
>> {
>>
>> 	fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n",
>> "usage: tunefs [-A] [-a enable | disable] [-e maxbpg] [-f avgfilesize]",
>> "              [-J enable | disable] [-j enable | disable]",
>> "              [-L volname] [-l enable | disable] [-m minfree]",
>> "              [-N enable | disable] [-n enable | disable]",
>> "              [-o space | time] [-p] [-S size] [-s avgfpdir]",
>> "              special | filesystem");
>> 	exit(2);
>> }
>
> This version requires you to remmeber to add %s\n to the format if you
> add a new line, something which I personally forget to do all the time.

This is OK (except for the line splitting -- see below) if pre-StandardC
compilers are to be supported.  I might prefer a version with harder
newlines:

 	fprintf("\
first line\n\
second line\n\
...
"
 	    );

>
>> void
>> usage(void)
>> {
>>
>> 	fprintf(stderr,
>> "usage: tunefs [-A] [-a enable | disable] [-e maxbpg] [-f avgfilesize]\n"
>> "              [-J enable | disable] [-j enable | disable]\n"
>> "              [-L volname] [-l enable | disable] [-m minfree]\n"
>> "              [-N enable | disable] [-n enable | disable]\n"
>> "              [-o space | time] [-p] [-S size] [-s avgfpdir]\n"
>> "              special | filesystem\n");
>> 	exit(2);
>> }

This is best now, except it splits some lines too early.  The correct
splitting is the same as the one produced by nroff for formatting the
man page -- there is no need to split before "[-L volname]" to fit in
80 columns at either the source or output level.  Hopefully the addition
of "\n" to the source strings doesn't make them long enough to need
reformatting, though it might.  The source strings were already 5
columns takes wider than the man page output and the usage() output
remains 2 columns wider than the man page output (since man page output
is indented 5 columns with spaces, while usage() output is indented 7
columns with "usage: " or spaces, and usage() source takes 3 more
columns for 2 quotes and 1 comma, and now 2 more columns for the quoted
newline.  If the man page output were wider than 78 columns, then the
usage() output format should be different to avoid long lines in the
output, and if the man page output were wider than 75 or now 73 columns,
then the usage source format should be different to avoid long lines in
the source.

>>
>> void
>> usage(void)
>> {
>>
>> 	fprintf(stderr,
>> "usage: tunefs [-A] [-a enable | disable] [-e maxbpg] [-f avgfilesize]\n\
>>               [-J enable | disable] [-j enable | disable]\n\
>>               [-L volname] [-l enable | disable] [-m minfree]\n\
>>               [-N enable | disable] [-n enable | disable]\n\
>>               [-o space | time] [-p] [-S size] [-s avgfpdir]\n\
>>               special | filesystem\n");
>> 	exit(2);
>> }
>>
>
> I personally don't see all that much difference between these.  The first variant
> has the advantage that it's very clear that you're looking at strings, which might
> be a good thing.
>
> I vote for 2.

I agree.

>
> Couldn't you replace all the leading spaces with \t's?

That would:
- add a gratuitous dependency on the output file being a terminal
   configured with 8-column tabs
- require the programmer to count the spaces needed after expansion of
   these tabs
- make it harder to see that the results of the previous step are correct.

Bruce


More information about the freebsd-arch mailing list