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

How to bold usage and clCfg.useHdr text from code? #218

Closed binaryben closed 1 year ago

binaryben commented 1 year ago

Hello. I like the gh CLI help formatting and am trying to replicate it using cligen (great package btw!).

I have gotten a significant chunk of the way using the following provided options:

const ConfigUsage = "ssh-keys $command <section.key> <value>\n\nOPTIONS\n$options"

when isMainModule:
  # ...
  clCfg.hTabCols = @[ clOptKeys, clDescrip ]
  clCfg.useHdr = "${doc}\nUSAGE\n  "
  # ...

  dispatchMulti(
    [ "multi", cmdName=binName, doc=docLine, usage=GlobalUsage ],
    [ configCommand, cmdName="config", doc=ConfigDoc, help=ConfigHelp, usage=ConfigUsage ]
  )

Link to full source code

Is there a way to configure the render option from the source code rather than having to rely on the user specific config file? I am assuming/hoping there is based on the presence of clCfg.render, but I'm not sure how to make use of that config option to achieve the desired result. I've also tried %(bold) which works in the user config files, but not when set in code.

c-blake commented 1 year ago

So, by default I, of course, cannot assume a lot about the environment that help is dumped to - even a terminal at all could be wrong. (Not that you say otherwise - just to be clear.)

I just use the user config myself, but this worked for me:

proc foo =
  ## hey there, *red*
  discard

when isMainModule:
  import cligen, cligen/humanUt, tables
  let r = initRstMdSGR({"singlestar": "bold ; -bold"}.toTable())
  proc renderMarkup(m: string): string = r.render(m)
  clCfg.render = renderMarkup
  dispatch foo
c-blake commented 1 year ago

(I would probably have to look at your code more closely to best evaluate how to integrate various humanUt APIs with it - the above, lifted from cligen/clCfgInit.nim, was really just to show an easy way to set .render at compile time which seemed the crux of your question.)

c-blake commented 1 year ago

But, as per this rST parsing/formatting, I think - you can also probably just use the above (EDIT: to set up singlestar binding to ANSI SGR bold) and then do things like "*COMMANDS*" and "*LEARN MORE*" inside your usage string.

binaryben commented 1 year ago

But, as per this rST parsing/formatting, I think - you can also probably just use the above (EDIT: to set up singlestar binding to ANSI SGR bold) and then do things like "*COMMANDS*" and "*LEARN MORE*" inside your usage string.

Unfortunately, no such luck. Just tried here, but maybe I did something wrong?

So, by default I, of course, cannot assume a lot about the environment that help is dumped to - even a terminal at all could be wrong. (Not that you say otherwise - just to be clear.)

Of course 😄 I am considering adding a flag to skip the GitHub-esque formatting for cases where it isn't going to a terminal. Although I may just wait until someone asks for that...

c-blake commented 1 year ago

Hmm. Let me look into that. Since you are just using a big string constant for global usage anyway, you can definitely just put ESC-[-1-m and ESC-[-m around your capitalized section headings. If that is too ugly, you could use std/strformat and interpolate some local vars at compile-time to make that less ugly.

binaryben commented 1 year ago

Is ESC-[-1-m and ESC-[-m supposed to be written just like that in the string constants? I tried that and it didn't work. Forgive me, I am new to Nim. I'm using this project to learn it.

c-blake commented 1 year ago

It's ok. I had meant the chr(27) escape character like "\e[1mLEARN MORE\e[0m".

binaryben commented 1 year ago
const GlobalUsage = """${doc}*USAGE*
  $command <command> [flags] [args]

\e[1mCOMMANDS\e[0m
$subcmds
\e[1mFLAGS\e[0m
  --help      Show help for a command
  --version   Show ssh-keys version
# ...

Also no luck. I had tried something similar (using as many different variations of escape codes) as one of my earliest attempts to get it working a couple of days ago. No matter what I put in, it just prints it out literally.

c-blake commented 1 year ago

Ok. I am working on a kind of hacked up/pared down version of your code trying things. Give me a few minutes. echo "\e[1mLEARN MORE\e[m here" does work, though. :-)

c-blake commented 1 year ago

So, Nim triple quotes does not seem to interpret the \e. If you do this it works to give you bold faced USAGE:

const GlobalUsage = "${doc}\e[1mUSAGE\e[m" & """

but only for USAGE. You could do similar how-strings-are-quoted tricks in your other section headings, do single-quote strings throughout, probably declare some const bold0, bold1 for on/off, etc. It might be hard to use strformat on that string since it also has targets for strutils.% interpolation as well.

Sorry it took so long - I was struggling to find where I stripped the escape, but I never do. Nim just never put it in there in the first place! Oops. :-)

c-blake commented 1 year ago

Basically like this:


const bon = "\e[1m"
const boff = "\e[m"

const GlobalUsage = "${doc}" & bon & "USAGE" & boff & """
  $command <command> [flags] [args]
""" & bon & "COMMANDS" & boff & """
$subcmds
""" & bon & "FLAGS" & boff & """
  --help      Show help for a command
  --version   Show ssh-keys version
""" & bon & "EXAMPLES" & boff & """
  λ $command install
  λ $command add --user=binaryben
  λ $command sync
""" & bon & "LEARN MORE" & boff & """
  Use '$command help <command>' for more information about a command
  Read the docs at https://github.com/binaryben/sync-ssh-keys
""" & bon & "FEEDBACK" & boff & """
  Open an issue at https://bnry.be/ssk-issues
  Request help at https://bnry.be/ssk-help
  Submit feature requests at https://bnry.be/ssk-idea"""

but (I think) you could also just use structured comments and teach users how to config cligen. Then if they want RED instead of bold they can do that, etc.

binaryben commented 1 year ago

Thanks @c-blake, got pretty much to what you have in your last comment - just without the const definitions.

but (I think) you could also just use structured comments and teach users how to config cligen. Then if they want RED instead of bold they can do that, etc.

Definitely something I will consider, but will be a stretch goal for now 😄

binaryben commented 1 year ago

Sorry it took so long

Also I hope this is a joke. I don't think I've ever seen an issue on a FOSS project resolved so fast 😂👍🏼

c-blake commented 1 year ago

The definitions are more for your "if some user asks to turn it off" or just to look "less ugly" if that is even true. They could (probably) be let with isatty-type checking or something, too, but the string may need to be a compile time constant.

Glad you appreciate the fast service! No patch/PR/release even necessary here. :-)

c-blake commented 1 year ago

BTW, if you do not care about somehow turning off the bolding and you wanted to be less compile-time string building, you can put the literal ESC character in the string. That was what I meant at first by ESC-[-1-m.

How you do so depends on your editor. In neovim, I can usually type Ctrl-V ESCkey.

How this renders may also depend on your environment, but "^[" is not uncommon since '[' comes right after 'Z' in ASCII and that fits the 64+ASCII code convention of ^A, ^B, ^C.

This way is not usually as cut & paste friendly, though, at least via Unix mouse selections.

binaryben commented 1 year ago

Ah that is useful information, never knew there was a way to type in a literal escape character. I'll have to look into how to do it in VSCodium. I think I will leave it for this project because it's possible I will make use of isatty or similar eventually, but I appreciate the new knowledge