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

auto-completions for bb.cli/dispatch #95

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

Sohalt
Copy link
Contributor

@Sohalt Sohalt commented Mar 21, 2024

You can test it with

# install test script
bbin install io.github.sohalt/bbct

# install completions

# bash
bbct --org.babashka.cli/completion-snippet bash >> ~/.bashrc

# zsh
# ~/.zsh needs to be on the $fpath variable for zsh
# if it's not, add this to your ~/.zshrc before a line with "compinit":
# fpath+=(~/.zsh)
bbct --org.babashka.cli/completion-snippet zsh > ~/.zsh/_bbct

# fish
bbct --org.babashka.cli/completion-snippet fish > ~/.config/fish/completions/bbct.fish

@borkdude
Copy link
Contributor

@Sohalt Trying to test:

bbct --babashka.cli/completion-snippet zsh > /usr/local/share/zsh/site-functions/_bbct

I'm getting:

zsh: no such file or directory: /usr/local/share/zsh/site-functions/_bbct

@Sohalt
Copy link
Contributor Author

Sohalt commented Mar 21, 2024

The installation for zsh can vary a bit, depending on how your distro packages zsh.
Try echo $fpath from within zsh and put the _bbct file somewhere in a directory on that path.

@Sohalt
Copy link
Contributor Author

Sohalt commented Mar 21, 2024

Also I just rebased on main and force pushed a new version of bbct with the latest sha

@borkdude
Copy link
Contributor

What is the recommended approach for this Rust-based CLI package? I suppose they must have some user-friendly docs for this?

@Sohalt
Copy link
Contributor Author

Sohalt commented Mar 21, 2024

They use
$ your_program --bpaf-complete-style-zsh > ~/.zsh/_your_program (https://docs.rs/bpaf/latest/bpaf/_documentation/_2_howto/_1_completion/index.html)
Though that depends on ~/.zsh/ being on your $fpath (e.g. on my system ~/.zsh/ doesn't exist).

@Sohalt
Copy link
Contributor Author

Sohalt commented Mar 21, 2024

What definitely should work is this:

  1. mkdir ~/.zsh
  2. Add fpath+=($HOME/.zsh)" in your .zshrc before a line that says compinit or similar.
  3. Then bbct --babashka.cli/completion-snippet zsh > ~/.zsh/_bbct.

@borkdude
Copy link
Contributor

Nice! First working result after doing that:

Screenshot 2024-03-21 at 12 00 49

@Sohalt
Copy link
Contributor Author

Sohalt commented Mar 21, 2024

Tests are failing due to line endings on Windows. Does any of bash, zsh or fish even work on Windows? What's the situation there when using something like Cygwin?

@Sohalt
Copy link
Contributor Author

Sohalt commented Mar 21, 2024

Current limitations:

  • only works with cli/dispatch
  • only works with gnu-style options (starting with -or --)
  • doesn't work well with options that take lists (e.g. :coerce [:string])

@borkdude
Copy link
Contributor

We might want to add Powershell completions or so in the future, but let's not worry about that for now. Does the example Rust library support this? You can disable those tests for Windows

@Sohalt
Copy link
Contributor Author

Sohalt commented Mar 21, 2024

Does the example Rust library support this?

no afaics

You can disable those tests for Windows

how?

@borkdude
Copy link
Contributor

By wrapping the whole test body in:

(when-not (fs/windows?) ...)

@Sohalt
Copy link
Contributor Author

Sohalt commented Mar 21, 2024

By wrapping the whole test body in:

(when-not (fs/windows?) ...)

Sometimes things can be so simple :) I thought there was some yaml programming involved to configure the test runner or similar 😅

"--babashka.cli/completion-snippet"
(if-let [command-name (get-in opts [:completion :command])]
(do (print-completion-shell-snippet (keyword shell) command-name)
(System/exit 0))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer not to call System/exit in function that are supposed to be non-side-effecting. I'd rather throw exceptions or whatever

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to short circuit all following execution in this case though, since we're printing the shell completion snippet and any other code running after this might print stuff that messes this up. It only happens when you pass the internal --babashka.cli/completion-snippet opt, so regular user code should never hit this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to short circuit if you just put the logic after all the parsing logic though?
Also removing the System/exit stuff makes it more REPL friendly

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I put the code after the parsing logic the consuming code could still print extra stuff. e.g.

(defn -main [& args]
  (cli/parse-opts args opts)
  (println "this does not belong in the completions script"))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The alternative would be to make it the responsibility of the user to call print-completion-shell-snippet (and make sure nothing else is printed in that case)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, we control format-opts so we can decide to filter those options out, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, but then you'll have a format-opts, that magically swallows some options.
I also don't particularly like the magic in parse-opts, but at least that means you get completions without any setup on your part.
Changing format-opts means you still have magic and need to do setup.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm also ok with just providing the complete * functions and having the user wire everything up themselves. Then it's even more work, but absolutely no magic.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, we control format-opts so we can decide to filter those options out, right?

Or do you mean the caller filters them out?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

magically swallows some options

The fact that org.babashka.cli/... options are internal, makes this non-magic imo. Users of this library should never make up options with that namespace themselves

(System/exit 0))
(binding [*out* *err*]
(println "Need `:completion {:command \"<name>\"}` in opts to support shell completions")
(System/exit 1)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

src/babashka/cli.cljc Outdated Show resolved Hide resolved
@Sohalt Sohalt force-pushed the auto-completions branch 2 times, most recently from ef3539e to 3d1a9ed Compare March 21, 2024 16:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants