Howdy, I’m pretty green to ocaml so I decided to take some of my existing bash scripts and rewrite them using ocaml. I wrote a cli for one of them in the hopes of making it more idiomatic to have completions. Currently I am using cmdliner and it is pretty sweet, but I’m confused at how to get the completions working. According to the docs, using dirpath should auto complete directories without checks, that’s a great start for what I’m doing and I want to eventually do something more complex. However, after compiling it, I can’t seem to get the completion to trigger. Any tips are welcome and appreciated. Here is the bit that I’m referring to:
let target_dir =
let doc = “Target directory, optionally with #devShell” in
Arg.(required & pos 0 (some dirpath) None & info [] ~docv:“DIR[#ATTR]” ~doc)
;;
let cmd =
let doc = “Enter a nix shell in the target directory” in
let info = Cmd.info “ns” ~doc ~version in
Cmd.v info Term.(const main $ target_dir)
;;
This builds _mach file with zsh shell completion driver for an executable called mach. Next I need to configure FPATH environment variable to point to a dir which has this _mach file (while developing I just put it in .envrc like this):
export FPATH="$PWD/bin:$FPATH"
This then should work completing mach <TAB> and similar lines.
Oh, interesting. I didn’t see this in the docs but that makes sense. Previously, I’ve used cargo clap-completions and it just spits out a script to stdout and I eval that. It rebuilds it on changes using a build.rs file, so nearly the same type of thing.
It’s a bit unclear to me the context in which you are trying to make things work. But the end user documentation for completion is here. Did you go through this ?
@andreypopp if you already have the cmdliner generic support in your environment what you are doing is needlessly complicated. As mentioned in the last paragraph here. You just need to invoke:
I prefer to produce standalone completion scripts — this makes it so cmdliner is not needed to be installed and found on $PATH. In fact for some of the tools, I even vendor cmdliner sources as an amalgamated cmdliner.ml.
The shell hook is a complicated one, I agree but it is made so I can switch between projects and direnv will make sure to load/unload completions.
Otherwise it is (1) a dune rule to produce scripts and (2) dune install sections for the scripts. Doesn’t look complicated to me. Although I’d prefer dune to make it for me — maybe we can have (cmdliner_completion) thing in (executable) stanza?
This is a misunderstanding. You don’t need the cmdliner tool in your PATH you need the generic cmdliner completion script to be in your completion environment.
With a properly setup environment the direnv is all you need.
But your direnv likely extends variables to look in the dev env’s unix prefix to lookup the completion of these other tools you are using. The generic cmdliner script will be there too.
I don’t know, to each one their setup :–) But before people start adding ad-hoc rules to their projects along the lines they found above I’d just like to mention that the recommended way of installing completion (and manpages) for your tools with dune is documented here.
I meant the direnv machinery, not sure if your shell hook is needed :–)
The only thing I had to do for a change to take effect was close my current shell and open a new one, but I can see how for fast iteration that would be a bit annoying. For me, it’s convenient enough. I don’t have to manage anything, nix just figures it out automatically for me.
(Possibly with --standalone-completion, but note that it may be slower in some shells)
This will also install man page in the prefix and add support for more shells as they are added to cmdliner (e.g. you did not install powershell’s completions). Directories are created as needed by the tool. Invoke with --dry-run for a description of the effects.
Out of curiosity, what makes the standalone script slower, and in which shells? Nix doesn’t support powershell, which is why I just selected the two which both nix and cmdliner support.
I don’t remember (and don’t really want :–), I wrote that in the doc string of --standalone-completion. I think some shells reparse/execute the whole completion support file on each completion and since the completion function is there they have to reparse it aswell.
From a maintenance perspective you are just better off using tool-support. Btw. I’m not familiar with nix but isn’t that powershell on nix ?