Skip to content

improve readability of help text #2075

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
3 tasks done
slawo opened this issue Mar 11, 2025 · 11 comments
Open
3 tasks done

improve readability of help text #2075

slawo opened this issue Mar 11, 2025 · 11 comments
Labels
area/v3 relates to / is being considered for v3 status/triage maintainers still need to look into this

Comments

@slawo
Copy link

slawo commented Mar 11, 2025

Checklist

  • Are you running the latest v3 release? The list of releases is here.
  • Did you check the manual for your release? The v3 manual is here.
  • Did you perform a search about this feature? Here's the GitHub guide about searching.

What problem does this solve?

Currently help text for flags is not very readable and looks all over the place, even when defining a custom Printer with a custom wrapAt

ex:

GLOBAL OPTIONS:
   --listen value, --address value     address on which the router will be listening on, ie: "localhost:11434"
                                              (default: "localhost:11434") [$GOLLAMAS_LISTEN, $LISTEN]
   --level value, --error-level value  error level, can be any of panic|fatal|error|warning|info|debug|trace
                                              (default: "error") [$GOLLAMAS_LEVEL, $LEVEL]
   --proxy value [ --proxy value ] assigns a destination for a model, can be a url or a connection id ex: --proxy
      'llama3.2-vision=http://server:11434'] ex: --proxy 'llama3.2-vision=c1 --connection c1=http://server:11434'
   --proxies value assigns destinations for the models, in the list of model=destination pairs ex: --proxies
      'llama3.2-vision=http://server:11434,deepseek-r1:14b=http://server2:11434' [$GOLLAMAS_PROXIES, $PROXIES]
   --connection value [ --connection value ] assigns an identifier to a connection which can be reffered to by
      proxy declarations ex: --connection c1=http://server:11434 --proxy llama=c1

GLOBAL OPTIONS:
   --listen value, --address value address on which the router will be listening
      on, ie: "localhost:11434"
               (default: "localhost:11434") [$GOLLAMAS_LISTEN, $LISTEN]
   --level value, --error-level value error level, can be any of
      panic|fatal|error|warning|info|debug|trace
               (default: "error") [$GOLLAMAS_LEVEL, $LEVEL]
   --proxy value [ --proxy value ] assigns a destination for a model, can be a url
      or a connection id ex: --proxy 'llama3.2-vision=http://server:11434'] ex:
      --proxy 'llama3.2-vision=c1 --connection c1=http://server:11434'
   --proxies value assigns destinations for the models, in the list of
      model=destination pairs ex: --proxies
      'llama3.2-vision=http://server:11434,deepseek-r1:14b=http://server2:11434'
      [$GOLLAMAS_PROXIES, $PROXIES]
   --connection value [ --connection value ] assigns an identifier to a connection
      which can be reffered to by proxy declarations ex: --connection
      c1=http://server:11434 --proxy llama=c1
   --connections value provides a list of connections which can be reffered to by
      id ex: --connections c1=http://server:11434,c2=http://server2:11434
      [$GOLLAMAS_CONNECTIONS, $CONNECTIONS]

Notice when a default is declared the line for default indents further and is more readable.

Solution description

The lines which have been wrapped should also be indented to the same level as the (default: ... ) text or simply to the start of the description column like in the docker documentation:


Global Options:
      --config string      Location of client config files (default
                           "/home/vscode/.docker")
  -c, --context string     Name of the context to use to connect to the daemon
                           (overrides DOCKER_HOST env var and default context
                           set with "docker context use")
  -D, --debug              Enable debug mode
  -H, --host list          Daemon socket to connect to
  -l, --log-level string   Set the logging level ("debug", "info", "warn",
                           "error", "fatal") (default "info")
      --tls                Use TLS; implied by --tlsverify

currently I use this function to wrap the lines in the helper:

	cli.HelpPrinter = func(w io.Writer, templ string, data interface{}) {
		funcMap := map[string]interface{}{
			"wrapAt": func() int {
				w := 10000
				tid := int(os.Stdout.Fd())
				if term.IsTerminal(tid) {
					width, _, err := term.GetSize(tid)
					println("width", width)
					if err == nil {
						w = width - 1
					}
				}
				return w
			},
		}

		cli.HelpPrinterCustom(w, templ, data, funcMap)
	}

I would like the behavior to be:

  • wrapped lines start at the beginning of the description column
  • if there is not enough space they display like the default line
  • if necessary I would like to pass a function to override that behavior with something like "wrapTo":func(int) or "indentBy":func(int)

Describe alternatives you've considered

A clear and concise description of any alternative solutions or
features you've considered.

@slawo slawo added area/v3 relates to / is being considered for v3 status/triage maintainers still need to look into this labels Mar 11, 2025
@Skeeve
Copy link
Contributor

Skeeve commented Mar 11, 2025

Or maybe, to save on horizontal screen real estate:

GLOBAL OPTIONS:
   --listen value
   --address value
         address on which the router will be listening on, ie: "localhost:11434"
            (default: "localhost:11434") [$GOLLAMAS_LISTEN, $LISTEN]
   --level value
   --error-level value
         error level, can be any of panic|fatal|error|warning|info|debug|trace
            (default: "error") [$GOLLAMAS_LEVEL, $LEVEL]
   --proxy value [ --proxy value ]
         assigns a destination for a model, can be a url or a connection id ex:
         --proxy 'llama3.2-vision=http://server:11434'] ex: --proxy 'llama3.
         2-vision=c1 --connection c1=http://server:11434'
   --proxies value
         assigns destinations for the models, in the list of model=destination
         pairs ex: --proxies
         'llama3.2-vision=http://server:11434,deepseek-r1:14b=http://server2:11434'
           [$GOLLAMAS_PROXIES, $PROXIES]
   --connection value [ --connection value ]
         assigns an identifier to a connection which can be reffered to by proxy
         declarations ex: --connection c1=http://server:11434 --proxy llama=c1
   --connections value
         provides a list of connections which can be reffered to by id ex: --connections
         c1=http://server:11434,c2=http://server2:11434
           [$GOLLAMAS_CONNECTIONS, $CONNECTIONS]

@slawo
Copy link
Author

slawo commented Mar 11, 2025

@Skeeve it does look neater, but wrapping the flags can lead to confusion. For example the 2 first lines don't make it obvious it is the same options.
My current case is not the nicest for real estate as I have multiple flags for the same thing currently due exploring and renaming features before a proper release.

@Skeeve
Copy link
Contributor

Skeeve commented Mar 11, 2025

Maybe this way?

GLOBAL OPTIONS:
   --listen value OR
   --address value
         address on which the router will be listening on, ie: "localhost:11434"
            (default: "localhost:11434") [$GOLLAMAS_LISTEN, $LISTEN]
   --level value OR
   --error-level value
         error level, can be any of panic|fatal|error|warning|info|debug|trace
            (default: "error") [$GOLLAMAS_LEVEL, $LEVEL]
   --proxy value [ --proxy value ]
         assigns a destination for a model, can be a url or a connection id ex:
         --proxy 'llama3.2-vision=http://server:11434'] ex: --proxy 'llama3.
         2-vision=c1 --connection c1=http://server:11434'
   --proxies value
         assigns destinations for the models, in the list of model=destination
         pairs ex: --proxies
         'llama3.2-vision=http://server:11434,deepseek-r1:14b=http://server2:11434'
           [$GOLLAMAS_PROXIES, $PROXIES]
   --connection value [ --connection value ]
         assigns an identifier to a connection which can be reffered to by proxy
         declarations ex: --connection c1=http://server:11434 --proxy llama=c1
   --connections value
         provides a list of connections which can be reffered to by id ex: --connections
         c1=http://server:11434,c2=http://server2:11434
           [$GOLLAMAS_CONNECTIONS, $CONNECTIONS]

Alternatively, options without a help text could get an empty line. So let's assume the first two are different options where --listen doesn't have a help text:

GLOBAL OPTIONS:
   --listen value

   --address value
         address on which the router will be listening on, ie: "localhost:11434"
            (default: "localhost:11434") [$GOLLAMAS_LISTEN, $LISTEN]
   --level value
   --error-level value
         error level, can be any of panic|fatal|error|warning|info|debug|trace
            (default: "error") [$GOLLAMAS_LEVEL, $LEVEL]

Doesn't look nice, but on the other hand: What good is an option you do not explain?

Or, instead of empty:

GLOBAL OPTIONS:
   --listen value
         /no help available/
   --address value
         address on which the router will be listening on, ie: "localhost:11434"
            (default: "localhost:11434") [$GOLLAMAS_LISTEN, $LISTEN]
   --level value
   --error-level value
         error level, can be any of panic|fatal|error|warning|info|debug|trace
            (default: "error") [$GOLLAMAS_LEVEL, $LEVEL]

@dearchap
Copy link
Contributor

Or maybe something like this

GLOBAL OPTIONS:
   --listen value/
   --address value
         address on which the router will be listening on, ie: "localhost:11434"
            (default: "localhost:11434") [$GOLLAMAS_LISTEN, $LISTEN]
....

@Skeeve
Copy link
Contributor

Skeeve commented Mar 11, 2025

T.b.h. A "/" would confuse me.

Personally I would prefer a hint that there is no help for that option. As I said before: What good is an option you don't explain? With that hint the author might be tempted to add at least something.

So any options on consecutive lines are the alternatives.

If we really want a visual hint that they are alternatives, I guess the "OR" would be good. Maybe, to not confuse it with any flag-related values, indent it by a few blanks?

GLOBAL OPTIONS:
   --listen value      OR
   --address value
         address on which the router will be listening on, ie: "localhost:11434"
            (default: "localhost:11434") [$GOLLAMAS_LISTEN, $LISTEN]
....

@Skeeve
Copy link
Contributor

Skeeve commented Mar 11, 2025

I just checked a few man pages (ls, curl, git). All of them go the "Comma-way" and "Option on its own line"

       -H, --header <header/@file>
              (HTTP IMAP SMTP) Extra header to include in information sent. When used within an HTTP request, it is
              added to the regular request headers.

Except when the option is short:

     -B      Force printing of non-printable characters (as defined by ctype(3) and current locale settings) in
             file names as \xxx, where xxx is the numeric value of the character in octal.  This option is not
             defined in IEEE Std 1003.1-2008 (“POSIX.1”).

     -C      Force multi-column output; this is the default when output is to a terminal.

     -D format
             When printing in the long (-l) format, use format to format the date and time output.  The argument
             format is a string used by strftime(3).  Depending on the choice of format string, this may result in
             a different number of columns in the output.  This option overrides the -T option.  This option is not
             defined in IEEE Std 1003.1-2008 (“POSIX.1”).

     -F      Display a slash (‘/’) immediately after each pathname that is a directory, an asterisk (‘*’) after

And they always have an empty line between options.

@slawo
Copy link
Author

slawo commented Mar 11, 2025

@Skeeve I like the idea of going with a more standardized output.

Although curl help looks like this and doesn't wrap

curl --help      
Usage: curl [options...] <url>
 -d, --data <data>           HTTP POST data
 -f, --fail                  Fail fast with no output on HTTP errors
 -h, --help <category>       Get help for commands
 -i, --include               Include response headers in output
 -o, --output <file>         Write to file instead of stdout
 -O, --remote-name           Write output to file named as remote file
 -s, --silent                Silent mode
 -T, --upload-file <file>    Transfer local FILE to destination
 -u, --user <user:password>  Server user and password
 -A, --user-agent <name>     Send User-Agent <name> to server
 -v, --verbose               Make the operation more talkative
 -V, --version               Show version number and quit

@dearchap would it be acceptable for the project to include a few different standardized output printer as an option?

@Skeeve
Copy link
Contributor

Skeeve commented Mar 11, 2025

@Skeeve I like the idea of going with a more standardized output.

Although curl help looks like this and doesn't wrap

curl --help      
Usage: curl [options...] <url>
 -d, --data <data>           HTTP POST data
 -f, --fail                  Fail fast with no output on HTTP errors
 -h, --help <category>       Get help for commands
 -i, --include               Include response headers in output
 -o, --output <file>         Write to file instead of stdout
 -O, --remote-name           Write output to file named as remote file
 -s, --silent                Silent mode
 -T, --upload-file <file>    Transfer local FILE to destination
 -u, --user <user:password>  Server user and password
 -A, --user-agent <name>     Send User-Agent <name> to server
 -v, --verbose               Make the operation more talkative
 -V, --version               Show version number and quit

@dearchap would it be acceptable for the project to include a few different standardized output printer as an option?

Yes. That's the help page. I looked ad the man page. Usually they are different, as we can see here. Otoh: There is no man page option in cli, or is it? So the help is more or less also the man page. At least for me that is. And if you look at a standard help output of cli programs, the similarities to man pages are there, don't you think?

@dearchap
Copy link
Contributor

Yes I've been dreaming up the idea of a "help personality". User can set the "help personality" to say ls or git style and the help output will match that of those commands. !!!!

@Skeeve
Copy link
Contributor

Skeeve commented Mar 12, 2025

Maybe take a look at what Pod::Usage in perl does. Okay… It extracts man and help text from "Plain Old Documentation", but maybe there is something which inspires you?

Depending on what you pass to pod2usage, it shows different sections of the usage text. Maybe that's something to consider. So you could call any cli --help to get just the options displayed, or cli --man to get a full man-page.

@slawo
Copy link
Author

slawo commented Mar 12, 2025

I had a look at the template system and I roughly understand how it works.
I have a question, I assume HelpPrinter existed first and HelpPrinterCustom was added afterwards and now there are 2 functions due to backwards compatibility. For a full release would it not make sense to keep only one and avoid the issue of having 2 functions which are used in 2 different scenarios?

If it's OK to break compatibility before release would you consider something along these lines:

type HelpPrinterConfig struct {
	Template    string
	CustomFuncs map[string]interface{}
}

// printHelpCustom is the default implementation of HelpPrinterCustom.
//
// The customFuncs map will be combined with a default template.FuncMap to
// allow using arbitrary functions in template rendering.
func printHelpCustom(out io.Writer, templ HelpPrinterConfig, data interface{}) {
...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/v3 relates to / is being considered for v3 status/triage maintainers still need to look into this
Projects
None yet
Development

No branches or pull requests

3 participants