Bash-completion(@2) vs. brew's auto-installed bash completions?

UPDATE: It seems that bash-completion actually finds and sources the files that brew installs. So it seems to be best practice to use bash-completion only.

I found this a bit confusing, not sure if worth adding anything to brew info bash-completion such as “sources all bash_completion files” or something?


$ echo $BASH_VERSION
4.4.23(1)-release

I installed bash-completion@2 and it works well when sourcing in .bash_profile (. /usr/local/share/bash-completion/bash_completion) but I’ve noticed that brew installs bash completions when installing formula that I can also source (although it’s inconvenient because I have to source files individually) (. /usr/local/etc/bash_completion.d/git-completion.bash).

What’s the optimal use between the above? I’m guessing bash-completion only? Can this be clarified in brew info bash-completion and brew info bash-completion@2? Are the brew installed versions just there in case people don’t want to install the formula and choose to just source individual files manually?

Potential downside of sourcing entire bash-completion is that it contains completions that I won’t be using, which may result in a longer shell startup time vs. individually loading the exact files I need?

1 Like

After having dealt with this problem, and seeing no solutions posted online, I figure I’d post my findings somewhere, and this discussion was high on search.

To get started, you first need to uninstall bash-completion. It is absolutely not best practice to continue using it. It’s extremely old (for Bash <3.1) and slow. I can see that you are using Bash 4, so this is for you. You want to use version bash-completion@2 because of its obvious performance benefit: non-eager loading of completion files; doing this radically speeds up shell spawn times.

Now, after doing this, and following the advice of brew to add the completion path to your .bash_profile or.bashrc file for it be sourced, you immediately note the speed, but you unfortunately also note a handful of your commonly used commands no longer complete (like brew and git). Why? These commands are not using the new v2 path. This is where every discussion I’ve come across recommends some hack, or manually finding the completion file and adding/sourcing it in your shell profile. No. This is unnecessary.

bash-completion@2 was designed to support a backwards-compatible directory. The only problem is that most don’t seem to know about it, and most don’t seem to ever set it. Most people don’t even know about v2, which is unfortunate, but that’s a different issue altogether. Have a look at the source: it’s checking for an environment variable, ${BASH_COMPLETION_COMPAT_DIR}, and if it is available, it will then additionally source all of the completion files contained under that path. In other words, all you need to do is define the backwards-compatible directory and you’re done. Both the old completions and modern, non-eager completions are now working simultaneously.

:information_source: Note

Most non-MacOS systems would not need to define this, because they tend to have a /etc/bash_completion.d directory, which is the fallback for that missing environment variable, but because MacOS does not have or use that directory, the environment variable needs to be defined manually.

This is how I source completions in my .bashrc file:

if [[ -e "/usr/local/share/bash-completion/bash_completion" ]]; then
	export BASH_COMPLETION_COMPAT_DIR="/usr/local/etc/bash_completion.d"
	source "/usr/local/share/bash-completion/bash_completion"
elif [[ -e "/usr/local/etc/profile.d/bash_completion.sh" ]]; then
	source "/usr/local/etc/profile.d/bash_completion.sh"
elif [[ -e "/etc/bash_completion" ]]; then
	source "/etc/bash_completion"
fi

Enjoy.

4 Likes

I just symlink any completions that aren’t in bash_completion.d, ex:

ln -s ~/Library/Caches/heroku/autocomplete/bash_setup /usr/local/etc/bash_completion.d

And only have this in my .bash_profile:

. /usr/local/share/bash-completion/bash_completion

You’re talking about missing completions when migrating to v2, which is why you think the best practice is to stick with v1, then write symlinks, which is not best practice. The point I’ve made is that you don’t have to do any symlinking nonsense at all: you simply define the $BASH_COMPLETION_COMPAT_DIR environment variable to point to the old-style completions path and you’re done.

The reason I have more conditions and potential completions is because I use multiple operating systems. For MacOS specifically, you can use this in combination with an install of bash-completion@2:

export BASH_COMPLETION_COMPAT_DIR="/usr/local/etc/bash_completion.d"
source "/usr/local/etc/profile.d/bash_completion.sh"

That will give you the speed of v2, while also picking up on the old eager completions, which solves the problem you were writing about in confusion.

2 Likes

I believe there’s been a slight misunderstanding.

  1. I am using v2
  2. Completions in /usr/local/etc/bash_completion.d are being sourced already, that’s why I symlink to it. Most completions work out of the box, some (such as heroku) need to be symlinked because they aren’t put in bash_completion.d on install.
1 Like

the latest code compat_dir=${BASH_COMPLETION_COMPAT_DIR:-/usr/local/etc/bash_completion.d} indicates you don’t need to set this unless you aren’t using the typical location