coder / serpent

CLI framework for scale and configurability inspired by Cobra
Creative Commons Zero v1.0 Universal
6 stars 1 forks source link

Add auto-completion #7

Open ammario opened 3 months ago

ammario commented 3 months ago

TODO:

Closes #3

ethanndickson commented 1 week ago

Few things to note after spending some time on this:

Let me know if you have any thoughts. I'll make a commit for feedback once I have a bare minimum prototype that I'm happy with.

ammario commented 1 week ago

Are we sure we want to supply a default completion command? I'm in favour of just exposing an API for retrieving all the info one might need to create the command. Library users will likely want to apply their own styling if it's interactive. Even in coder/coder we want to just reuse the cliui boilerplate we have, and I'm not sure we want to recreate that here, or even import it?

Nope, I'm game to provide the tools for people to craft their own command, but then we should put a complete example in the README.

To my surprise, if you disable path auto-completion in fish's complete using -f, fish just straight up ignores arguments if it thinks you're trying to autocomplete a path: e.g, I have some uncommitted fish+go code responsible for figuring out the current word: COMPLETION_MODE=1 CURSOR_POS=21 completetest file ../ will print files in the parent directory, using the Go file handler. Hitting tab on completetest file ../ will not give any suggestions. This means the protocol we use needs a way to tell the shell whether it should use it's file auto-completion. I haven't looked at the bash implementation all that much, but this is currently what Cobra does for all the shells it supports, and I do think it's better than implementing our own path completer in Go.

It's been a while since I was looking at this, but I came to the conclusion that it's better to disable the path completion and do it all within Go since that's pretty easy to implement and then users can easily add filters like "only accept accept directory".

I'd like to get auto-completions in the middle of a line working - I'm currently passing the cursor position to serpent, but I think it'd be better to just pass the args until the currently selected character.

I struggled with this too. I think doing middle-line completion correctly will involve a larger refactor to argument parsing. I think it makes sense, for MVP, to just prune args to cursor.

I wanted to keep the Go API for completions similar to the middleware API, allowing users to compose completion handler functions, but I'm not sure there's that great of a need? The only use case I can envision for composing is when you have a command that has both arguments, and a subcommand with different arguments. Then you would compose a default handler (flags + subcommands) with a custom handler (for your arguments). This doesn't sound like a super popular pattern, afaik there's nothing in coder/coder that does something like this, so I think a single handler for a Command and a single handler for an Option (that has a flag) will do. We can then supply convenience functions for these handlers like func EnumHandler(choices ...string) CompHandler.

Yeah, we don't need to optimize for composition in the MVP.

Bear in mind that coder/coder is the only major user of the library, and it's OK if we make breaking changes down the road.