c-blake / cligen

Nim library to infer/generate command-line-interfaces / option / argument parsing; Docs at
https://c-blake.github.io/cligen/
ISC License
509 stars 24 forks source link

Weird line breaks #109

Closed SolitudeSF closed 5 years ago

SolitudeSF commented 5 years ago

I extracted this snippet that demonstrates the issue

# test.nim
import cligen

type
  PassType = enum
    ptLong = "long", ptMedium = "medium", ptShort = "short",
    ptMaximum = "maximum", ptPin = "pin", ptBasic = "basic"

proc test(kind = ptLong): int = discard

dispatch test, help = {
  "kind": """type of a password:
maximum | 20 characters, contains symbols.
long    | 14 characters, symbols.
medium  | 8 characters, symbols.
basic   | 8 characters, no symbols.
short   | 4 characters, no symbols.
pin     | 4 numbers.
"""}

./test -h gives

Usage:
  test [optional-params]
  Options(opt-arg sep :|=|spc):
  -h, --help                     print this cligen-erated help
  --help-syntax                  advanced: prepend,plurals,..
  -k=, --kind=   PassType  long  type of a password:
                                 maximum | 20 characters, contains symbols.
                                 long    | 14 characters,
                                 symbols.
                                 medium  | 8 characters, symbols.
                                 basic   | 8 characters, no symbols.
                                 short   |
                                 4 characters, no symbols.
                                 pin     | 4 numbers.

Notice the linebreaks in the long and short descriptions.

c-blake commented 5 years ago

Yeah..So, for long help text my cligen/textUt.alignTable just uses std/wordwrap.wrapWords (formerly wordWrap). Almost anything like this is going to defeat/weirdify "pre-formatted text" like yours.

What I do for the main doc comment text is try to auto-detect pre-formatting by checking if mainDocCommentText.count("\n ") > 1 (arguably that should maybe be > 0, but I think my thinking was to wrap a single indent but leave alone a multi-row table). So, right now with no changes you could do:

import cligen
type
  PassType = enum
    ptLong = "long", ptMedium = "medium", ptShort = "short",
    ptMaximum = "maximum", ptPin = "pin", ptBasic = "basic"
proc test(kind = ptLong): int =
  ## PassType can be:
  ##   maximum | 20 characters, contains symbols.
  ##   long    | 14 characters, symbols.
  ##   medium  | 8 characters, symbols.
  ##   basic   | 8 characters, no symbols.
  ##   short   | 4 characters, no symbols.
  ##   pin     | 4 numbers.
  discard
dispatch test, help = { "kind": "type of a password"}

For me (and probably you) that leads to help output like:

Usage:
  test [optional-params]
PassType can be:
  maximum | 20 characters, contains symbols.
  long    | 14 characters, symbols.
  medium  | 8 characters, symbols.
  basic   | 8 characters, no symbols.
  short   | 4 characters, no symbols.
  pin     | 4 numbers.
  Options(opt-arg sep :|=|spc):
  -h, --help                     print this cligen-erated help
  --help-syntax                  advanced: prepend,plurals,..
  -k=, --kind=   PassType  long  type of a password

which looks better (to me) in the 62-ish column limited text of github markdown preformatted boxes. It would also probably be more robust to variable run-time user terminal widths than putting it as a sub-table of the help table.

I just added a similar heuristic for help text as well. For just help text itself the rule is '\n' in helpTextForParam, i.e. any newline in there and cligen considers it "pre-formatted". Does that make sense to you? A reverse fix would have been to strip newlines before word wrapping, but that would have destroyed any CLI author-intended structure.

I do expect that it's going to be harder for a pre-formatted table within an auto-formatted help table to look good. The main doc area has a bigger text column budget. For example, your original code now produces this:

Usage:
  test [optional-params]
  Options(opt-arg sep :|=|spc):
  -h, --help                     print this cligen-erated help
  --help-syntax                  advanced: prepend,plurals,..
  -k=, --kind=   PassType  long  type of a password:
                                 maximum | 20 characters, contains symbols.
                                 long    | 14 characters, symbols.
                                 medium  | 8 characters, symbols.
                                 basic   | 8 characters, no symbols.
                                 short   | 4 characters, no symbols.
                                 pin     | 4 numbers.

The default value long there kind of threw me off visually because it's the only one and looks like a C type. Makes me think we need @[ (short,long)option key, type, default, help ] column headers. I had been thinking of adding the option for such anyway, but that is a feature for another time. EDIT: formatting/grammar fixes.