Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Idea: Add a zsh-completions output extension #250

Open
jona7o opened this issue Feb 23, 2021 · 7 comments
Open

Idea: Add a zsh-completions output extension #250

jona7o opened this issue Feb 23, 2021 · 7 comments

Comments

@jona7o
Copy link

jona7o commented Feb 23, 2021

I think most of the mac users are using zsh instead of bash. zsh has this awesome plugin for auto completion. I think it could be a great extension for "decline" to autogenerate this zsh-autocompletion output from the Opts. I have seen this output in several CLIs like kubectl for kubernetes (source <(kubectl completion zsh)).

So my suggestion is to build an plugin for decline that generates the needed output for example with ./my-decline-cli completion zsh. Perhaps as "com.monovore" %% "decline-zsh-completions" % "1.3.0"?

@bkirwi
Copy link
Owner

bkirwi commented Feb 24, 2021

Yeah, I think this would be a cool enhancement! Some quick thoughts:

  • You'd probably want to support bash too at some point. My understanding is that they're not so different, but I haven't looked into it much!
  • You could do a pretty reasonable version using just the information we already track... completing option names, etc. If you wanted to complete argument types like paths / enums / etc. we'd need to extend the AST and argument interface. I'm usually very hesitant to make core changes like this, but I'd consider it in this case.
  • It should be possible to expose this as a Command[_] => String function in a library somewhere. You could then use that to provide the interface you're suggesting... or folks using native packager could hook it into their build and generate completion files automatically maybe.

I'm unlikely to work on this myself, but I'd certainly be open to contributions of this shape! Labelling as such.

@ziggystar
Copy link

To add to bkirwi: When this will be done, I suggest to make it a general extension with support for multiple shells from the start (even if only one gets implemented initially).

@morgen-peschke
Copy link

One change that could make it easier to experiment with this and other enhancements may be providing access to some of the Opt ADT.

@kubukoz
Copy link
Contributor

kubukoz commented Oct 21, 2021

FYI I have a POC of this for zsh and I'm going to try and generalize it so it doesn't work with just my app. Current work in kubukoz/spotify-next@d3f0d92 (It needs to come from the decline package because Opts's subtypes are scoped like that, so when I have something more generalized I'll push it upstream)

@bkirwi
Copy link
Owner

bkirwi commented Oct 25, 2021

Since it's come up in this thread, a quick note on why the Opts ADT is not public:

Opts implements Alternative, and is required to respect the Alternative laws, including some distribution laws. Usually, the way you ensure you meet the laws is to have the left-hand side generate the same AST as the right-hand side. Unfortunately, for the right distributivity law, the structure on the left turns out to be both very common and substantially more efficient at parse time than the one on the right, which means it's really important to have different internal representations for them. So we basically can't expose the AST without breaking the Alternative laws or killing performance. (And we have test that ensure that the observable / public behaviour of both representations is the same, aside from performance anyways - they parse the same inputs to the same outputs, give identical errors on parse failures, etc.)

@morgen-peschke
Copy link

Would it be possible to expose a method to emit a public ADT (possibly, but not necessarily, one of the two you mentioned)?

That way the internal performance optimizations aren't perturbed, and nobody has to pay for the cost of the more expensive representation unless they need it to do something unusual like generating completions or prototyping functionality (one I've wanted to explore is generating linked markdown readme files, which would greatly benefit from being able to traverse the subcommand tree).

@bkirwi
Copy link
Owner

bkirwi commented Oct 27, 2021

Would it be possible to expose a method to emit a public ADT (possibly, but not necessarily, one of the two you mentioned)?

One idea, which came up in the context of #138, would be to capture more structural information in the Help object. Right now Help is just a bag of Strings, but if we preserved more of the original structure, it could be handy for some of these programmatic uses you have in mind, and adding it to Help means we're not adding another top-level concept to the API.

(In that context, we could satisfy the distributive law by converting the "distributed" representation on the right-hand side to the undistributed form on the left. That's not an option for the original AST because we can't check function equality, but in the context of Help it ought to work.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants