peterbourgon / ff

Flags-first package for configuration
Apache License 2.0
1.34k stars 59 forks source link

ffcli: use ShortHelp field as tagline #87

Closed marco-m closed 1 year ago

marco-m commented 2 years ago

Hello @peterbourgon,

Consider the help output of a program with subcommands:

$ xprog -h
USAGE
  xprog [flags] <command> ...

SUBCOMMANDS
  ssh          upload and run the test binary via SSH
  passthrough  run the test binary directly on the host

FLAGS
  -v=false  verbose output

if then we ask the help for a subcommand we "loose" the ShortHelp:

$ xprog ssh -h
USAGE
  xprog ssh [flags] <test-binary> [go-test-flags]

FLAGS
  -v=false  verbose output

This proposal is to use the Name and ShortHelp field of the subcommand as a "tagline":

$ xprog ssh -h
ssh -- upload and run the test binary via SSH

USAGE
  xprog ssh [flags] <test-binary> [go-test-flags]

FLAGS
  -v=false  verbose output

Actually this could be used also for the tagline of the root command itself:

$ xprog -h
xprog -- a test runner for "go test -exec"

USAGE
  xprog [flags] <command> ...

SUBCOMMANDS

What do you think?

peterbourgon commented 2 years ago

Is a "tagline" a well-defined concept? Can you point me to any prior art you might be aware of?

It's true that the ShortHelp of a Command is only consumed and displayed by its parent Command(s), but that's by design: the assumption is that when you know to type a given [sub]command, you are already aware of what it itself should be doing. Maybe this assumption is worth revisiting — I could be convinced that a nonzero ShortHelp should act as a prefix to any help output. Would you advocate for that?

For the record, we're discussing the behavior of the DefaultUsageFunc provided by the package, which you're under no obligation to use! You can easily write your own UsageFunc with the behavior you're after.

marco-m commented 2 years ago

Is a "tagline" a well-defined concept? Can you point me to any prior art you might be aware of?

The docker utility does something similar, I think this could be obtained with ffcli as-is if LongHelp where the same as ShortHelp (but then one could not provide a real LongHelp):

$ docker --help | cat -n
     1
     2  Usage:  docker [OPTIONS] COMMAND
     3
     4  A self-sufficient runtime for containers
     5
     6  Options:
    ....
    40  Commands:
    41    attach      Attach local standard input, output, and error streams to a running container
    ...

above, the tagline for the root is line 4.

$ docker attach --help | cat -n
     1
     2  Usage:  docker attach [OPTIONS] CONTAINER
     3
     4  Attach local standard input, output, and error streams to a running container
     5
     6  Options:
    ...

here we see line 4, the tagline, is the same as ShortHelp at line 41 in the previous output.

Another example is mercurial:

$ hg -h | cat -n
     1  Mercurial Distributed SCM
     2
     3  list of commands:
     4
     5  Repository creation:
     6
     7   clone         make a copy of an existing repository

and

hg clone -h | cat -n | head
     1  hg clone [OPTION]... SOURCE [DEST]
     2
     3  make a copy of an existing repository
     4
    ...

the tagline is line 4, which comes from the ShortHelp at line 7 in the previous output.

It's true that the ShortHelp of a Command is only consumed and displayed by its parent Command(s), but that's by design: the assumption is that when you know to type a given [sub]command, you are already aware of what it itself should be doing.

I do agree that probably the majority of the utilities out there follow this assumption.

Maybe this assumption is worth revisiting — I could be convinced that a nonzero ShortHelp should act as a prefix to any help output. Would you advocate for that?

This is what I was proposing, yes. At the end, I don't think that in this case there is a "right" and "wrong". It is a question of taste and ffcli is yours :-)

For the record, we're discussing the behavior of the DefaultUsageFunc provided by the package, which you're under no obligation to use! You can easily write your own UsageFunc with the behavior you're after.

Agreed. On the other hand, as a user feedback, using ffcli in the style of objectctl (with separate packages for commands, and also for the root command) is already verbose, although I understand the reason, so if one could avoid providing also a UsageFunc, it would be, in my opinion, better :-)

peterbourgon commented 2 years ago

using ffcli in the style of objectctl (with separate packages for commands, and also for the root command) is already verbose

Just parenthetically: if you find this to be true, then don't use it that way! :) The examples are meant to be showcases, not necessarily templates to follow. I agree that package-per-command doesn't make sense at all unless your commands each encapsulate a lot of logic.