c-blake / cligen

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

Sharing param help messages between commands #203

Closed geotre closed 2 years ago

geotre commented 2 years ago

I have a few commands that have parameters in common. For the help messages attached to those parameters, I'd like to keep them in one place to avoid duplication.

Here is a basic example of what I'm starting with, where the messages are duplicated:

import
  std/tables,
  pkg/cligen

proc commandA(a, b, c: int) = discard
proc commandB(a, b, d: int) = discard

dispatchMulti(
  [commandA, help={
    "a": "help message for param A",
    "b": "help message for param B",
    "c": "help message for param C",
  }],
  [commandB, help={
    "a": "help message for param A",
    "b": "help message for param B",
    "d": "help message for param D"
  }]
)

I thought I'd be able to do something like this:

...

const helpTable = {
  "a": "help message for param A",
  "b": "help message for param B",
  "c": "help message for param C",
  "d": "help message for param D"
}.toTable()

dispatchMulti(
  [commandA, help=helpTable],
  [commandB, help=helpTable]
)

But it errors: Error: commandA has no param matching 'help' key "d"

So I tried:

...

const
  helpA = "help message for param A"
  helpB = "help message for param B"

dispatchMulti(
  [commandA, help={
    "a": helpA,
    "b": helpB,
    "c": "help message for param C",
  }],
  [commandB, help={
    "a": helpA,
    "b": helpB,
    "d": "help message for param D"
  }]
)

But that doesn't work either - it compiles but the help messages are replaced with the identifiers:

> helptest.nim commandA -h

Usage:
  commandA [required&optional-params] 
Options:
  -h, --help                    print this cligen-erated help
  --help-syntax                 advanced: prepend,plurals,..
  -a=, --a=      int  REQUIRED  helpA
  -b=, --b=      int  REQUIRED  helpB
  -c=, --c=      int  REQUIRED  help message for param C

I've looked through the documentation and played around with generating tables differently but I can't figure it out. Should I just stick to duplicated help messages?

c-blake commented 2 years ago

You can do an entire Table as in test/PassValues.nim, not individual values, but Nim should be able to construct that entire Table similarly to what you wanted in a const section.

import std/tables, cligen

proc commandA(a, b, c: int) =
  ## cmd A
  discard
proc commandB(a, b, d: int) =
  ## cmd B
  discard

const
  helpA = "help message for param A"
  helpB = "help message for param B"

const helpsA = {"a": helpA,
                "b": helpB,
                "c": "help message for param C"}.toTable

const helpsB = {"a": helpA,
                "b": helpB,
                "d": "help message for param D"}.toTable

dispatchMulti [commandA, help=helpsA],
              [commandB, help=helpsB]

What you want exactly is not impossible, but relates to how much "re-parsing/re-interpreting" cligen code has to do for all of the input parameters to dispatchGen. In this case, I'd have to re-example the whole alist {} constructor which is a bit of work.

geotre commented 2 years ago

Good point, thanks for the quick reply!