Hacker News new | past | comments | ask | show | jobs | submit login
Creating a bash completion script (2018) (iridakos.com)
87 points by laz_arus on March 2, 2022 | hide | past | favorite | 16 comments



Writing shell completions is a surprisingly tricky - especially for larger CLI tools or when you want to provide more advanced suggestions. Everything has to be done imperatively, usually as a shell script! It can get hairy quickly.

As a point of comparison, see the difference between the git completions written in bash [1] vs the declarative equivalent [2].

[1] https://github.com/git/git/blob/master/contrib/completion/gi...

[2] https://github.com/withfig/autocomplete/blob/master/src/git....


Great that someone is thinking about this, doesn't seem very usefull though, it requires MacOS. But the bash one has been there since the beginning, so you are comparing a project that seems to be created in 2021 without any need for backward compatibilty with one that has grown organically for 15 years.


It doesn't have to be pure shell. I've written a few tools that have built-in completion helpers. All their completion scripts have to do is run the tool with the right environment variables, and return the results.

That's also how autocompletion works with Python's excellent Click library.


Here's a tutorial on creating zsh completion scripts: https://github.com/zsh-users/zsh-completions/blob/master/zsh...

The zsh completion system is better than the bash one; it has a builtin menu system, or you can use fzf: https://github.com/junegunn/fzf


Symfony 5.4 just added support for bash completion to PHP CLI commands using the library so we were able to add a very nice and easy to use interface to Winter CMS to take advantage of it: https://wintercms.com/blog/post/console-improvements-winter-...

Defining completion values for a given argument in a Winter CMS CLI command is as easy as adding a single method to the command's class now:

    public function suggestMyArgumentValues(string $currentValue, array $allInput): array
    {
        return ['array', 'of', 'suggested', 'values'];
    }


For folks writing a Go CLI, the Cobra library (used by the kubectl and docker CLIs) comes with completions for bash, zsh, and fish out of the box. Completion scripts are indeed a hairy mess (see the instructions for installing Bash completions on kubectl!) and we were very pleasantly surprised at how trivial Cobra made it. (I've no affiliation with Cobra; just a very happy user)


I use Cleo for python, same thing, has the ability to generate completion scripts. I also find the API far saner than argparse or click. I don't really use the docstring-parser, I prefer using the Command api for finer control, but it's really cool to just write the help docs and automagically get options.

https://github.com/sdispater/cleo


Cobra is awesome. Was surprised the same at how easy it was to add completion support. Here is +1 from this satisfied end user, no affiliation with cobra team.


I gave up on Bash completion when I ran into a silly thing that can't be turned off: when you complete something which is quoted 'foo.b_[Tab] it will complete, close the quote and add a space: 'foo.bar' _. When you wanted 'foo.bar_ so then you could continue, for instance, like 'foo.bar(arg, _. There isn't anything the completion handler can do to fix this.

Bash completion is designed for simple arguments like command line options and path names; anything else was not envisioned, in spite of embedded scripts being a pattern in the traditional Unix command line.

E.g. Awk completion could go like this:

   awk 'BE_[Tab]

   awk 'BEGIN {_


completion scripts are very very useful, but writing them is a disorganized mess.

It would almost be easier to modify the bash source itself to read and use a regular grammar, say:

  foo [-p <pid>] [-f <configfile>]
  <pid>: {ps -eo pid}
  <configfile>: {ls -1 *.cfg}
or maybe something even nicer with help text


I wrote long ago about writing competion scripts in any language: https://saveriomiroddi.github.io/Using-scripts-in-any-langua....

Although it's not ideal (one ends up duplicating the arguments parsing logic of the program), it's actually not complicated, just some boilerplate.


well, your completion script doesn't _need_ to be written in bash. If you're writing a completion script for an executable, that executable can be called with an option that generates the completions for bash to consume. You just need to generate the output in the expected format and install a softlink . Hope this can give you some comfort.


Bash completion for the domterm command (a terminal emulator) calls the domterm command itself with a special "#complete-for-bash" option:

    complete -o nospace -C 'domterm "#complete-for-bash" "$COMP_LINE" "$COMP_POINT"' domterm
It works pretty well has the advantage that it automatically ties the completion to the executable, avoiding version mismatches.

It would be great if other shells could use a similar mechanism. Then you could use the same completion logic for multiple shells. A complication is that zsh and fish completion provide descriptive help text; there would need to be a mechanism for a "completion option" to provide such help text.


>It would almost be easier to modify the bash source itself to read and use a regular grammar

It's an interesting idea that we're using for zio-cli [1].

[1] https://github.com/zio/zio-cli/pull/119


argcomplete[1] is worth an honorable mention ~ it makes it really easy to add shell completion to any Python program that uses argparse.

[1] https://pypi.org/project/argcomplete/


fish shell attempts to parse completions from man pages.

https://fishshell.com/docs/current/cmds/fish_update_completi...




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: