I have been working the last few weeks on extending cligen, a generator for commandline parser code. I reported upon at SYCL 2024 Milan
The initial result of this, is zigclc, a program that can do commandline completion for the zig command (and all of the subcommands, options/arguments for those subcommands (that have help)), and does so for the fish, zsh and bash shell.
zigclc based completion can be installed, by invoking a shell specific line (which is displayed for your login shell if you start the program without parameters). This has zigclc generate a small shell function, which itself again invokes zigclc for feeding the shell with (TAB) completion information.
zigclc parses, and caches, the output from zig build --help to get you the steps, project options and system integrations for completion of zig build.
The zigclc program itself compiles with 0.15.2, but the completion has been analsysed from the 0.16 help output (which differs only slightly from the 0.15 output).
I would appreciate any feedback on actual usage, as I usually work with zsh and tend to wrap zig invocations by some other tool.
Some more details:
cligen analysewas implemented to parse the output fromzig -handzig subcommand -hfor all subcommands, and generates a YAML specification forzigclc’s subcommands, sub-subcommands (steps), options, arguments. Given the emulation of other commandszigimplements, this was non-trivial.- The plug-in system for
cligenthat allows global, user-specific and project specific extensions, was expanded. E.g._ext/zig_complete_build_steps.yamlin thezigclcsource tree holds thezig buildparsing code that get inserted inzigclc - The updates to
cligenfor creatingzigclchave NOT been committed yet (cligen download | SourceForge.net). You would need those to generatezigclc.zigfrom the YAML specfication. This needs a bit of cleaning up, and some testing/expanding of the non-completion code generated, which I intend to do next. cligendoes only invokezigwhen it needs to determine the “dynamic”zig buildcompletions (and help). Your shell will still directly invokezigwhen you pressReturnon the commandline.cligencan be used to generate the “front-end” to a Zig commandline program, handing back astructwith variables that are set (or not) from the commandline or a config file. It could also be used forzigthat way, but probably should not do so for the LLVM provided subcommands.zigclchelp output is somewhat nicer than that ofzigitself, as it determines your terminal width and wraps per column (so no help overflow at the beginning of the next line).- I briefly looked at
nushelland it looks like you can invoke an external command for the completion, so that seems to be a possible target. I also want to see ifpowershellcould do this. - You can have different
zigclccompleters for different zig version. - Some
zigsubcommands have over a thousand possibilities. That doesn’t really help with trying to select what to type next for a completion. It is in principle possible to have different priorities for the options, that will let you specify something even though it is not offered as a completion. - There is no real reason why
cligencould not be re-implemented in Zig. Howevercligenuses far more features of YAML than the average program does, so that would require either a fullYAMLimplementation for Zig, or some equally powerful (tags, anchors/aliases, inclusion) alternative data specification.
Working on a Python program that creates a Zig source, that emits a shell scripts that parses completion information generated by the Zig source, can be confusing at times. At times I had problems keeping else if and elif apart, or when to use # and when // for comments, etc.
Curly braces needed doubling when used in Python’s f-string, etc. Fortunately zig will mostly not compile if you generate something incorrectly.
Having both single and double quoted strings in Python helped a bit in preventing multi-backslash insanity while generating Zig code. But still there is a place where to get a colon escaped for the zsh completion (zsh seperates the completion from its help with a colon), required 8 (eight!) backslashes in the string in the Python code for cligen %-)