CLI11 icon indicating copy to clipboard operation
CLI11 copied to clipboard

Autocomplete for CLI11

Open jbriales opened this issue 4 years ago • 14 comments

About "Autocomplete: This might eventually be added to both Plumbum and CLI11, but it is not supported yet." Is there any plans or thoughts on this feature at this point?

I've been thinking about giving this a try myself for some time. Before going for it, I'd appreciate any pointers/caveats/ideas in this regard :)

jbriales avatar Nov 15 '19 06:11 jbriales

No thoughts here? :)

jbriales avatar Nov 18 '19 18:11 jbriales

Yes, thoughts are just slow coming. :)

I looked into this a bit, and have some general ideas. I'll try to collect my ideas and would be happy to have someone work on this. Ping me on Thursday-Friday if I don't do something by then (have to prepare materials to teach a class Wednesday).

henryiii avatar Nov 18 '19 18:11 henryiii

Haha thanks, that sounds good! Now I can align my plans on this better too ;)

jbriales avatar Nov 18 '19 19:11 jbriales

Hey @henryiii friendly ping here :)

jbriales avatar Nov 22 '19 22:11 jbriales

I’ll write it up when I get home today. :) Edit: midday/evening tomorrow, too late now.

henryiii avatar Nov 23 '19 16:11 henryiii

I've previously talked briefly with the author of argcomplete:

https://github.com/kislyuk/argcomplete/issues/116

It would be nice to be able to reuse as much as possible from argcomplete, possibly even have a general completer. Not sure how much would work for C++, since the procedure would have been different, though plumbum and other CLI toolkits for scripting languages could. I don't know how to ensure a text string is near the beginning of a binary; you probably cannot as that might be used for indexing. So that method is probably out.

How familiar are you with argcomplete? The basics there would be the same here. There would be a way to run the program to get just the completions, given a string and a location. It would predict the possible options that would make sense for that string and location. It would then return the list of completions. The hard parts are letting the system know that an executable supports completions; the trick of reading the first few bytes of a program would probably be quite hard in a compiled program.

So I think we would need:

  • A general .completions(string in, int loc) method that could do the work
  • A way to trigger and run this. Ideally matching argcomplete to the degree reasonable.
  • A way to tell the shell this can be done.

Your thoughts?

I've worked through the beginnings of this in a branch somewhere in plumbum, quite a while ago.

henryiii avatar Nov 25 '19 02:11 henryiii

I've used argcomplete in the past, so I have some very high-level idea how it works , although I've never looked into the internal implementation. I'm not sure what's your idea of reusing argcomplete as a general completer. Are you thinking of emulating the logic there in C++ or how?

I don't know how to ensure a text string is near the beginning of a binary; you probably cannot as that might be used for indexing. So that method is probably out.

Not sure I follow your thought here. Can you provide an example of what are you pursuing here?

A general .completions(string in, int loc) method that could do the work

Where would that completions method live? As part of the Option interface? Or App? Or both (probably this)?

A way to trigger and run this. Ideally matching argcomplete to the degree reasonable.

To run the program in the completion mode we might probably add a special option or subcommand to check for? Akin to --help, say __complete?

A way to tell the shell this can be done.

To let the system know about completion I'd probably just register the foo __complete function as completion function for foo in bash: I.e. sth like calling complete -F 'foo __complete' foo (need to check the exact syntax).

So from the comments above I feel like you have definitely thought through this before in the past. I also feel like you're pursuing some kind of general abstraction/tool? To be honest I haven't a huge amount of time so I might be up for trying to just find a working solution for CLI11. I'll start by quickly checking argcomplete when I get a while to get some common perspective. Let me know if you have any suggestion/pointers to the most relevant/reusable part of the code.

A possible different approach is the one mentioned here: I.e. have a special command/option/flag again to generate some bash-completion files that you can then source to enable completion via bash.

jbriales avatar Nov 25 '19 08:11 jbriales

There are several ways to go.

Argcomplete looks in the first X bytes of a file to see if a special string is there. If it is, it then runs the file with (I think) a special environment variable (a command line option would also work, I think). There's just one argcomplete script, so if someone installed argcomplete, then any executable that has the argcomplete special string and supports the argcomplete method of requesting a completion would work without installing any other scripts.

Having a special argument that generates an autocomplete script would be a possibility too, though then there might be a bit of extra work to make sure we eventually can support bash/zsh/fish (at a minimum). It might be the most natural approach for C++. It's disappointing that you'd have to install it for each app, but might be much more useful for compiled apps being distributed than asking users to install a general tool, like argcomplete.

A one line registration would be an acceptable alternative somewhere in-between the two methods.

The basic work would be the same for the first or the third idea above, the completions method is the most important part, the rest is mostly plumbing (and it is important to look into them just a bit to make sure the completions method is flexible enough to handle them).

The second example is quite a bit different and probably would be more work, though would make a fairly nice result, as it could run quickly without having to load the executable.

If Option 3 works, that's probably what we should target as the simplest way to get this in, otherwise 1 or 2 are fine. I'm most familiar with 1. Your call. If you do 3, eventually maybe I can work on Plumbum completion as well and adapt it to option 1 so either would work.

henryiii avatar Nov 25 '19 15:11 henryiii

Sounds good!

I'd avoid using/having argcomplete as a strict requirement because this would introduce an external dependency for the completion feature. I'd rather have a solution that can be plumbed into the user's environment choice (like bash, etc.) following the usual workflow for that system. I think having multiple simple integration approaches external to the core completion feature is going to scale and maintain better.

I'd start implementing a solution and trying it with bash because, being selfish, it's what I use and because hopefully keeping the right abstract completion interface at the CLI level it should be possible to plumb with any other typical shell.

Will let you know once I have any progress/questions in here :)

jbriales avatar Nov 25 '19 18:11 jbriales

Sounds good. I use fish, so will probably will try to extend it to fish once fairly far along.

henryiii avatar Nov 25 '19 18:11 henryiii

I've given you access so you can make a branch directly in the repository, if you'd like.

henryiii avatar Nov 25 '19 19:11 henryiii

Hi @henryiii , Thanks for the great library!

Are you open for a PR that adds a complete(args, arg_index, in_arg_index) and just runs a cb giving all possible completions for the argument + its metadata?

Later it could be used as a building block for other projects to build completion lists from that, offline or online.

I don't have a clear idea, but if you think it's the right direction, I'll try to sketch a design.

elazarl avatar May 15 '22 10:05 elazarl

Hi @henryiii,

I've just implemented autocompletion in a very basic way in my forked repository here. You can try playing with it by calling the function cli11_install_completion_file(<target name>) from your CMakeLists.txt file and then installing the project. Don't forget to open another bash or simply execute the autogenerated script.

I'd like to hear what you think about it :)

hailo-oro avatar Aug 09 '22 13:08 hailo-oro