Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Makefile.am
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
SUBDIRS = doc completions-core completions-fallback helpers-core \
test completions helpers
startup-core test completions helpers startup

pkgdata_DATA = bash_completion

# Empty, but here just to get the compat dir created with install
compatdir = $(sysconfdir)/bash_completion.d
compat_DATA = bash_completion.d/000_bash_completion_compat.bash
compat_DATA =
Comment on lines 6 to +8
Copy link
Collaborator

Choose a reason for hiding this comment

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

We still need to create ${sysconfdir}/bash_completion.d

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Do we? #1399 seemed to want us not to create anything in /etc. I thought the projects that want to put any file in /etc/bash-completion.d can create a directory themselves, but does it actually fail in a typical setup of autoconf? I thought it would automatically create a directory. Is there another reason that we need to create it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I thought the projects that want to put any file in /etc/bash-completion.d can create a directory themselves, but does it actually fail in a typical setup of autoconf? I thought it would automatically create a directory.

When creating a package, one would do make install into a clean directory. So I guess make install is rather required to work without any existing directory structures.

Copy link
Collaborator

@yedayak yedayak Feb 4, 2026

Choose a reason for hiding this comment

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

Yeah that's a good point, any other packages that install there will create the directory there themselves, especially since they can be installed even if bash-completion isn't.
My only worry is for users following guides that tell them to put the completions in /etc/bash-completion.d/. Maybe this calls for another README 🙃
I think creating the directory will be fine from the perspective of the UAPI concerns, since we're not dependent anymore on any files in that directory for a fully working system. Maybe someone from the original PR wants to chime in? @septatrix @bluca

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

My only worry is for users following guides that tell them to put the completions in /etc/bash-completion.d/. Maybe this calls for another README 🙃

I think I already removed that part with 6a78aa3. Is there still a place to modify?

Copy link
Collaborator

Choose a reason for hiding this comment

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

My only worry is for users following guides that tell them to put the completions in /etc/bash-completion.d/. Maybe this calls for another README 🙃

I think I already removed that part with 6a78aa3. Is there still a place to modify?

I mean guides outside of the repo, for example this stack overflow question: https://askubuntu.com/questions/68175/how-to-create-script-with-auto-complete, or the cobra13 docs. Maybe adding a bit more friction for doing the "wrong thing" does make sense though.

Copy link
Collaborator Author

@akinomyoga akinomyoga Feb 4, 2026

Choose a reason for hiding this comment

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

I see. It can sometimes take a long time to update the community's knowledge. Until recently, there have been many articles recommending the use of the old-style command substitutions `...` that were deprecateddiscouraged by the standard about 30 years ago.


profiledir = $(sysconfdir)/profile.d
profile_DATA = bash_completion.sh
Expand Down
138 changes: 90 additions & 48 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ tracing on in it before doing anything else there.

## FAQ

**Q. The bash completion code inhibits some commands from completing on
**Q1. The bash completion code inhibits some commands from completing on
files with extensions that are legitimate in my environment. Do I
have to disable completion for that command in order to complete on
the files that I need to?**
Expand All @@ -136,48 +136,85 @@ A. No. If needed just once in a while,
circumvent any file type restrictions put in place by the bash
completion code. If needed more regularly, see the next question:

**Q. How can I override a completion shipped by bash-completion?**

A. Install a local completion of your own appropriately for the desired
command, and it will take precedence over the one shipped by us. See the
next answer for details where to install it, if you are doing it on per user
basis. If you want to do it system wide, you can install eagerly loaded
files in `compatdir` (see a couple of questions further down for more
info. To get the path of `compatdir` for the current system, the output of
`pkg-config bash-completion --variable compatdir` can be used) and install a
completion for the commands to override our completion for in them.

If you want to use bash's default completion instead of one of ours,
something like this should work (where `$cmd` is the command to override
completion for): `complete -o default -o bashdefault $cmd`

**Q. Where should I install my own local completions?**

A. Put them in the `completions` subdir of `$BASH_COMPLETION_USER_DIR`
(defaults to `$XDG_DATA_HOME/bash-completion` or
`~/.local/share/bash-completion` if `$XDG_DATA_HOME` is not set) to have
them loaded automatically on demand when the respective command is being
completed.
See also the next question's answer for considerations for these
files' names, they apply here as well. Alternatively, you can write
them directly in `~/.bash_completion` which is loaded eagerly by
our main script.

**Q. I author/maintain package X and would like to maintain my own
completion code for this package. Where should I put it to be sure
that interactive bash shells will find it and source it?**

A. [ Disclaimer: Here, how to make the completion code visible to
bash-completion is explained. We do not require always making the
completion code visible to bash-completion. In what condition the
completion code is installed should be determined at the author/maintainers'
own discretion. ]
**Q2. How can I override a completion shipped by bash-completion or install a
new completion for a user account?**

A. To override a completion for a specific command, you can simply install your
own completion file for the command into an appropriate place. It will take
precedence over the one shipped by us or the one installed systemwide. To
install a completion on per user basis, put the completion file at
`<userdir>/completions/<cmd>.bash`, where `<cmd>` is the command name and
`<userdir>` is one of the user directories. The user directories are
specified by the colon-separated `$BASH_COMPLETION_USER_DIR` (defaults to
`$XDG_DATA_HOME/bash-completion` or `~/.local/share/bash-completion` if
`$XDG_DATA_HOME` is not set). They will be loaded automatically on demand
when the respective command is being completed.

> [!NOTE]
> See also the answer to Q4 for considerations for those files' names, they
> apply here as well.

Completion settings that should be loaded on initialization of
bash-completion should be defined in a startup completion file. A startup
completion file can be added in the directory `<userdir>/startup` (see the
previous paragraph for `<userdir>`). A prefix of the form
`[0-9][0-9][0-9]_` may be prepended to the filename of the startup files to
control the loading order. To override a existing startup file installed
systemwide or shipped by us, you can put your own version with the same
filename in `<userdir>/startup`. In identifying the overridden startup
file, the prefixes `[0-9][0-9][0-9]_` are ignored. If you want to disable a
startup completion file, you can put an empty file.

You can also define eagerly loaded settings in the user file
(`${BASH_COMPLETION_USER_FILE:-$HOME/.bash_completion}`). Instead of
preparing separate files for specific commands, you may write completion
settings for specific commands directly in the user file. When you want to
modify the default completion setting set by `complete -D` (which is
available in Bash >= 4.1), you can override it in the user file or in a user
startup file. If you want to use bash's default completion instead of one
of ours, in the user file or in a user startup script, you can define
something like this:

```bash
complete -o default -o bashdefault $cmd
```

where `$cmd` is the command to override completion for.

**Q3. How can I override a completion shipped by bash-completion systemwide?**

A. Install a local completion appropriately for the desired command, and it
will take precedence over the one shipped by us.

A completion file for a specific command `<cmd>` can be placed at
`<localdir>/completions/<cmd>.bash`, where `<localdir>` is
`/usr/local/share/bash-completion` if `XDG_DATA_DIRS` is not defined, or
`<datadir>/bash-completion` where `<datadir>` is one of the directories
listed in `XDG_DATA_DIRS`.

> [!NOTE]
> See also the answer to Q4 for considerations for those files' names, they
> apply here as well.

Similarly, systemwide startup files can be placed in the directory
`<localdir>/startup`.

**Q4. I author/maintain a distribution package and would like to maintain my
own completion code for this package. Where should I put it to be sure that
interactive bash shells will find it and source it?**

A. > [!NOTE]
> Here, how to make the completion code visible to bash-completion is
> explained. We do not require always making the completion code visible to
> bash-completion. In what condition the completion code is installed
> should be determined at the author/maintainers' own discretion.

Install it in one of the directories pointed to by bash-completion's
`pkgconfig` file variables. There are two alternatives:
`pkgconfig` file variables.

- The recommended directory is `<completionsdir>`, which you can get with
`pkg-config --variable=completionsdir bash-completion`. From this
- The recommended directory for the completions of specific commands is
`<completionsdir>`, which you can get with
`pkg-config --variable=completionsdir bash-completion`. From this
directory, completions are automatically loaded on demand based on invoked
commands' names, so be sure to name your completion file accordingly, and
to include (for example) symbolic links in case the file provides
Expand All @@ -189,6 +226,11 @@ A. [ Disclaimer: Here, how to make the completion code visible to
--variable=helpersdir bash-completion`. The completion files in
`<completionsdir>` can reference the helper script `<helpersdir>/<helper>`
as `${BASH_SOURCE[0]%/*}/../helpers/<helper>`.
- The directory for startup files is `<startupdir>`, whose value in the
current system can be retrieved by
`pkg-config bash-completion --variable=startupdir`. A typical value is
`/usr/share/bash-completion/startup`. Typically, the startup file can be
used to override the `complete -D` settings set by bash-completion.
- The other directory, which is only present for backwards compatibility and
is not recommended to use, is `<compatdir>` (get it with
`pkg-config --variable=compatdir bash-completion`). From this
Expand Down Expand Up @@ -235,8 +277,7 @@ A. [ Disclaimer: Here, how to make the completion code visible to
bash-completion is 2.12 or higher, the completion script can actually be
installed to `$PREFIX/share/bash-completion/completions/` under the same
installation prefix as the target program installed under `$PREFIX/bin/` or
`$PREFIX/sbin/`. For the detailed search order, see also "Q. What is the
search order for the completion file of each target command?" below.
`$PREFIX/sbin/`. For the detailed search order, see also Q10 below.

Example for `Makefile.am`:

Expand All @@ -251,7 +292,7 @@ A. [ Disclaimer: Here, how to make the completion code visible to
install(FILES your-completion-file DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/bash-completion/completions")
```

**Q. When completing on a symlink to a directory, bash does not append
**Q5. When completing on a symlink to a directory, bash does not append
the trailing `/` and I have to hit <kbd>&lt;Tab></kbd> again.
I don't like this.**

Expand All @@ -264,7 +305,7 @@ A. This has nothing to do with `bash_completion`. It's the default for
mark-symlinked-directories on` in your `/etc/inputrc` or
`~/.inputrc` file.

**Q. Completion goes awry when I try to complete on something that contains
**Q6. Completion goes awry when I try to complete on something that contains
a colon.**

A. This is actually a 'feature' of bash. bash recognises a colon as
Expand Down Expand Up @@ -292,7 +333,7 @@ A. This is actually a 'feature' of bash. bash recognises a colon as
Unfortunately, there's no way to turn this off. The only thing you
can do is escape the colons with a backslash.

**Q. Why is `rpm` completion so slow with `-q`?**
**Q7. Why is `rpm` completion so slow with `-q`?**

A. Probably because the database is being queried every time and this uses a
lot of memory.
Expand All @@ -315,7 +356,7 @@ A. Probably because the database is being queried every time and this uses a
unless it detects that the database has changed since the file was created,
in which case it will still use the database to ensure accuracy.

**Q. bash-completion interferes with my `command_not_found_handle` function
**Q8. bash-completion interferes with my `command_not_found_handle` function
(or the other way around)!**

A. If your `command_not_found_handle` function is not intended to address
Expand All @@ -335,7 +376,7 @@ A. If your `command_not_found_handle` function is not intended to address
> context. It is safer to test `COMP_POINT` as one does not need to care
> about the differences between the set and non-empty states of variables.

**Q. Can tab completion be made even easier?**
**Q9. Can tab completion be made even easier?**

A. The `readline(3)` library offers a few settings that can make tab
completion easier (or at least different) to use.
Expand Down Expand Up @@ -364,7 +405,8 @@ A. The `readline(3)` library offers a few settings that can make tab
This turns off the use of the internal pager when returning long
completion lists.

**Q. What is the search order for the completion file of each target command?**
**Q10. What is the search order for the completion file of each target
command?**

A. The completion files of commands are looked up by the shell function
`_comp_load`. Here, the search order in bash-completion >= 2.18 is
Expand Down
1 change: 1 addition & 0 deletions bash-completion.pc.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ sysconfdir=@sysconfdir@
compatdir=${sysconfdir}/bash_completion.d
completionsdir=${datadir}/@PACKAGE@/completions
helpersdir=${datadir}/@PACKAGE@/helpers
startupdir=${datadir}/@PACKAGE@/startup

Name: @PACKAGE@
Description: programmable completion for the bash shell
Expand Down
79 changes: 70 additions & 9 deletions bash_completion
Original file line number Diff line number Diff line change
Expand Up @@ -3584,7 +3584,60 @@ _comp__init_collect_startup_configs()
local base_path=${1:-${BASH_SOURCE[1]}}
_comp__init_startup_configs=()

# source compat completion directory definitions
# list startup directories
local -a startup_dirs=()
local paths
_comp_split -F : paths "${BASH_COMPLETION_USER_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion}" &&
startup_dirs+=("${paths[@]/%//startup}")
_comp_split -F : paths "${XDG_DATA_DIRS:-/usr/local/share:/usr/share}" &&
startup_dirs+=("${paths[@]/%//bash-completion/startup}")
startup_dirs+=("$_comp__base_directory/startup")
startup_dirs+=("$_comp__base_directory/startup-core")

# collect startup files
local -A startup_visited=()
for startup_dir in "${startup_dirs[@]}"; do
[[ -d $startup_dir && -r $startup_dir && -x $startup_dir ]] || continue

local -a startup_files=()
_comp_expand_glob startup_files "$startup_dir/*.bash" || continue

local -a selected_startup_files=()
local startup_dir
for startup_file in "${startup_files[@]}"; do
[[ ! -d $startup_file && -r $startup_file ]] || continue

# Disable the startup files with the same name as one of already
# selected startup files. This allows users to override a startup
# file with another file with the same name placed in an earlier
# directory in "${startup_files[@]}".
local name=${startup_file##*/?([0-9][0-9][0-9]_)}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why is this processing needed?

Copy link
Collaborator Author

@akinomyoga akinomyoga Jan 26, 2026

Choose a reason for hiding this comment

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

I think this comment discusses the same thing as the following cover comment, so let me answer together in this sub-thread.

Can you explain the reason for keeping track of what we loaded to allow for overriding? Is there a specific use-case you're thinking about?

The original motivation that I thought of this mechanism is #1399. Although the OP of #1399 didn't explain or show a reference to any technical details that they tried to use to reason the PR, I found the UAPI spec and other materials myself. They explain the usage of /etc/<app> and /usr/etc/<app> (or /usr/lib/<app>, /usr/share/<app>, or whatever). I'm neutral on whether to adopt their specific use of the specific directories, /etc and /usr/etc, but I found the underlying idea useful.

Meanwhile, I've been thinking it is very annoying that some distribution packages put in /etc/bash_completion.d completion settings that affect the global behavior of completion, such as fzf and _python-argcomplete. For example, even if I don't intend to use fzf for Bash completion, when some application packages require the fzf package as a dependency in order to provide a menu for their UI, the fzf completion is unintentionally turned on through /etc/bash_completion.d/fzf installed by dependency. I believe the fzf package and the package for the fzf-bash integration should be separated ideally, but I guess the package maintainers of fzf consider fzf a tool for shell completion (rather than a general selector).

This also becomes an issue in a shared system, for which I do not have the administrator privilege. If there are any files in /etc/bash_completion.d/*, they are all forcibly loaded. Even if I want to disable any of them partially, there is no way to realize that. Actually, I ended up doing a very ugly hack of overriding the source builtin and the dot (.) builtin, but I would rather avoid such a hack if possible. Then, if those system-wide startup completion settings are moved to /usr/share/bash-completion/startup/<xxx>.bash, and if bash-completion provides a way to disable each setting by putting an empty file at e.g. ~/.local/share/bash-completion/startup/<xxx>.bash (or a way to override the behavior by putting a non-empty file), it will be useful.

Even if we forget about those arguments, when different versions of the same application install the same name of startup completion files at different paths, such as /usr/share/bash-completion/startup/xyz.bash, /usr/local/share/bash-completion/startup/xyz.bash, and ~/.local/share/bash-completion/startup/xyz.bash, I doubt we should source all of them. I think it would make more sense to pick up one of them, particularly the one installed by the current user.

Why is this processing needed?

If you mean by "this" the entire processing described by the code comment, I think I answered it above.

If you mean by "this" particularly the stripping of ?([0-9][0-9][0-9]_), it is to remove the prefix used to control the loading order. We already have 000_ prefixed to our 000_bash_completion_compat.bash, so other startup settings may also be prefixed by numbers. However, such a prefix number isn't controlled by the upstream project of the application, but the package distributions, or the system administrator may also change the number. Thus, when multiple startup completions of the same application are installed to different paths, they are not guaranteed to have the matching prefix numbers (if any). Then, the prefix numbers used to control the loading order should be ignored in identifying the initialization of the same application.

Copy link
Collaborator Author

@akinomyoga akinomyoga Jan 26, 2026

Choose a reason for hiding this comment

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

Maybe the name "eagerly loaded settings" is not a good description for startup files that can be overridden by users?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I realized I haven't considered users' directories in looking up the users' startup files. I added the support for it in commit a45e2ab. I'll squash this commit into the first commit later.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I also included the description of this behavior in fc6787f.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thank you for pointing out the existence of the configuration variable, BASH_COMPLETION_COMPAT_IGNORE! I haven't thought about using it to select valid startup files rather than buggy ones, (though it's not sufficient to process the UAPI-type overriding and selection from multiple versions of the same startup file).

[[ ${startup_visited[$name]-} ]] && continue
startup_visited[$name]=set

selected_startup_files+=("$startup_file")
done
((${#selected_startup_files[@]})) || continue

# Note: bash < 4.4 has a bug that all elements are connected with
# ${a[@]+"${a[@]}"} when IFS does not contain whitespace.
local IFS=$' \t\n'
# Prepend the selected startup files because we want to source the
# system startup files earlier.
_comp__init_startup_configs=(
"${selected_startup_files[@]}"

# Note: bash < 4.3 has a bug that "${a[@]}" fails for "set -u" when
# an array "a" exists but has no elements. We use
# ${a[@]+"${a[@]}"} as a workaround. Similar patterns are also
# used in completions/*.bash, 000_bash_completion_compat.bash, and
# test_unit_compgen.py. They need to be updated when the minimum
# required Bash version is lifted up.
${_comp__init_startup_configs[@]+"${_comp__init_startup_configs[@]}"}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Side note: I see we have this pattern in other places, but I don't understand why it's needed, doesn't just doing

_comp__init_startup_configs=( "${selected_startup_files[@]}" ${_comp__init_startup_configs[@]} )

work?

Copy link
Collaborator Author

@akinomyoga akinomyoga Feb 4, 2026

Choose a reason for hiding this comment

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

Bash 4.2 has a bug that "${arr[@]}" fails with set -u for arr=().

Copy link
Owner

Choose a reason for hiding this comment

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

Just a random off-context comment, as I haven't been following this MR yet, ref #1479 (reply in thread): I think we should drop support for bash < 5.0 (or at least < 4.3) for the next release.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

So they can finally be removed, but I believe it should be done in a separate PR for consistency (and for later research in case something happens). In the first place, the code doesn't pass the CI tests without the workaround in the current setup of the test environment.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I added a clarification in 71ae643..6c1af0e.

I also considered adding the same comments to other cases, but I gave it up because there seem to be many, and I didn't feel that we needed to bother with what would soon be removed for the version requirement change. There have been 13 cases, and none of them had comments:

./bash_completion:975:    _comp_compgen -F "$_ifs" -U input -- ${_compgen_options[@]+"${_compgen_options[@]}"} -W '$input'
./bash_completion:1101:    local "$2" "$3" "$4" && _comp_upvars -a"${#words[@]}" "$2" ${words[@]+"${words[@]}"} \
./bash_completion:1379:    _comp_compgen -U toks set ${toks[@]+"${toks[@]}"}
./bash_completion:2657:    _comp_compgen_known_hosts ${options[@]+"${options[@]}"} -- "$cur"
./bash_completion:3413:    elif . "$compfile" "$cmd" ${source_args[@]+"${source_args[@]}"}; then
./completions-core/gdb.bash:32:                find ${path_array[@]+"${path_array[@]}"} . -name . -o \
./completions-core/ri.bash:23:            "$(ri ${classes[@]+"${classes[@]}"} 2>/dev/null | ruby -ane \
./completions-core/ri.bash:31:            "$(ruby -W0 "$ri_path" ${classes[@]+"${classes[@]}"} 2>/dev/null | ruby -ane \
./completions-core/strace.bash:60:                                '${syscalls[@]+"${!syscalls[@]}"} file process
./completions-core/update-rc.d.bash:20:        _comp_compgen -- -W '"${options[@]}" ${services[@]+"${services[@]}"}' \
./startup-core/000_bash_completion_compat.bash:338:        args=(-c "$REPLY" ${opt[@]+"${opt[@]}"})
./startup-core/000_bash_completion_compat.bash:362:        args=(-c "$REPLY" ${opt[@]+"${opt[@]}"})
./test/t/unit/test_unit_compgen.py:22:            '_comp__test_words() { local -a input=("${@:1:$#-1}"); _comp__test_compgen -c "${@:$#}" -- -W \'${input[@]+"${input[@]}"}\'; }',

)
done

# collect compat completion directory definitions
local -a compat_dirs=()
local compat_dir
if [[ ${BASH_COMPLETION_COMPAT_DIR-} ]]; then
Expand All @@ -3599,25 +3652,33 @@ _comp__init_collect_startup_configs()
# functions.
if [[ $_comp__base_directory == */share/bash-completion ]]; then
compat_dir=${_comp__base_directory%/share/bash-completion}/etc/bash_completion.d
else
compat_dir=$_comp__base_directory/bash_completion.d
[[ ${compat_dirs[0]} == "$compat_dir" ]] ||
compat_dirs+=("$compat_dir")
fi
[[ ${compat_dirs[0]} == "$compat_dir" ]] ||
compat_dirs+=("$compat_dir")
fi
local -A compat_visited=()
for compat_dir in "${compat_dirs[@]}"; do
[[ -d $compat_dir && -r $compat_dir && -x $compat_dir ]] || continue
local compat_files
_comp_expand_glob compat_files '"$compat_dir"/*'
_comp_expand_glob compat_files '"$compat_dir"/*' || continue
local compat_file
for compat_file in "${compat_files[@]}"; do
[[ ${compat_file##*/} != @($_comp_backup_glob|Makefile*|${BASH_COMPLETION_COMPAT_IGNORE-}) &&
-f $compat_file && -r $compat_file ]] &&
_comp__init_startup_configs+=("$compat_file")
-f $compat_file && -r $compat_file ]] || continue

# Disable the compat files with the same name as one of already
# selected ones. This allows users to override a compat file with
# another file with the same name placed in an earlier directory in
# "${compat_dirs[@]}".
local name=${compat_file##*/}
[[ ${compat_visited[$name]-} ]] && continue
compat_visited[$name]=set

_comp__init_startup_configs+=("$compat_file")
done
done

# source user completion file
# collect the user completion file
#
# Remark: We explicitly check that $user_completion is not '/dev/null'
# since /dev/null may be a regular file in broken systems and can contain
Expand Down
2 changes: 2 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ completions-fallback/Makefile
doc/Makefile
helpers/Makefile
helpers-core/Makefile
startup/Makefile
startup-core/Makefile
test/Makefile
test/t/Makefile
test/t/unit/Makefile
Expand Down
4 changes: 4 additions & 0 deletions startup-core/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
startupcoredir = $(datadir)/$(PACKAGE)/startup-core
startupcore_DATA = 000_bash_completion_compat.bash

EXTRA_DIST = $(startupcore_DATA)
4 changes: 4 additions & 0 deletions startup/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
startupdir = $(datadir)/$(PACKAGE)/startup
startup_DATA = README.md

EXTRA_DIST = $(startup_DATA)
26 changes: 26 additions & 0 deletions startup/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# External startup directory - bash-completion

This directory `startup` is the place to put _external startup scripts_
for initializing [bash-completion](https://github.com/scop/bash-completion).

The `bash-completion` framework has been providing `/etc/bash_completion.d` as
a directory to put scripts that are eagerly loaded on the initialization stage
of `bash-completion`. However, the historical purpose of
`/etc/bash_completion.d` has been the place to put completion files for
`bash-completion < 2.0`, which did not support dynamic loading through
`complete -D` (only available in `bash >= 4.1`). This original usage was
already deprecated. Apart from that, there are scripts that need to be loaded
on the initialization stage of `bash-completion`, such as
`/etc/bash_completion.d/fzf` and `/etc/bash_completion.d/_python-argcomplete`,
which want to set up a custom default completion with `complete -D`.

In `bash-completion >= 2.18`, we started to provide the `startup` directory as
a dedicated directory for such scripts that need to be loaded on the
initialization stage.

* Eagerly loaded scripts should be placed in this directory instead of
`/etc/bash_completion.d`.
* External completion files of API v1 should be updated to use API v2 or v3 and
should be moved to `completions/<cmd>.bash`. Although we recommend to update
the completion file to use newer API, the completion file relying on API v1
should continue to be placed in `/etc/bash_completion.d`.
Loading