Conversation
| local i | ||
| for i in "${!dirs[@]}"; do | ||
| dir=${dirs[i]}/completions | ||
| for dir in "${dirs[@]}"; do |
There was a problem hiding this comment.
The result of this is that we end up loading completions without the .bash suffix from more dirs we did before this change. We may want to tighten that up some.
Could check if the dir ends with -core or -fallback and load only .bash for them. That isn't 100% correct in the case if someone has for whatever reason configured their BASH_COMPLETION_USER_DIR to have one of those suffixes (we'd want to load both with and without .bash from there for backwards compatibility).
There was a problem hiding this comment.
I agree to check the suffix -{core,fallback} (probably inside _comp_load__visit_file).
There was a problem hiding this comment.
Thank you for creating the PR! This is exactly the issue that I described in #1557 (comment).
When using the new version, I also noticed a search-order problem of
_comp_loadwhen the systembash-completion < 2.18and the user'sbash-completion >= 2.18coexist. I'll later describe it. I would like to discuss it and fix issues of_comp_loadincluding it.
I was naively thinking of swapping the directory precedence of 2) and 3), and inserting the search for completions-core before 4), but I haven't yet considered it deeply enough.
| @@ -3478,15 +3478,15 @@ _comp_load() | |||
| if [[ ${BASH_COMPLETION_USER_DIR-} ]]; then | |||
| _comp_split -F : dirs "$BASH_COMPLETION_USER_DIR" | |||
There was a problem hiding this comment.
BASH_COMPLETION_USER_DIR is supposed to contain a path like ~/.local/share/bash-completion, so we need to suffix /completion to them too. I think we can use _comp_compgen. For example, something like this: _comp_compgen -Rv dirs -F : -- -W '$BASH_COMPLETION_USER_DIR' -S /completions, though I haven't tested this carefully.
| # Completions in the system data dirs. | ||
| _comp_split -F : paths "${XDG_DATA_DIRS:-/usr/local/share:/usr/share}" && | ||
| dirs+=("${paths[@]/%//bash-completion}") | ||
| dirs+=("${paths[@]/%//bash-completion}"/completions{,-core,-fallback}) |
There was a problem hiding this comment.
Should we search the system completions-{core,fallback} after none were found in the in-tree completions-{core,fallback} (i.e., $_comp__base_directory/completions-{core,fallback} in the tree of the current bash_completion)? I think all default/fallback completions should already be found in the in-tree completions-{core,fallback}. Are there cases where the completion file is not found in the in-tree completions-{core,fallback} but found in the system completions-{core,fallback}?
I also think loading external completions-{core,fallback} would cause the compatibility problem with the internal API. We've been assuming that we can use the latest internal APIs defined in bash_completion inside the in-tree completions of the same version. When the in-tree completions-{core,fallback} doesn't contain the completion for a command while the system completions-{core,fallback} contains one, I think that implies the system bash-completion is newer than the current bash-completion. In this case, we should avoid loading the system completions-{core,fallback} because it is likely to contain uses of new internal APIs.
In short, I think the completions in completions-{core,fallback} are tightly bound, in the sense of internal API, to the exact version of bash_completion in the same tree. It's not safe to load completions-{core,fallback} outside the tree.
| for dir in "${paths[@]%/}"; do | ||
| [[ $dir == ?*/@(bin|sbin) ]] && | ||
| dirs+=("${dir%/*}/share/bash-completion") | ||
| dirs+=("${dir%/*}/share/bash-completion"/completions{,-core,-fallback}) |
There was a problem hiding this comment.
For the same reason, I think we don't want to load completions-{core,fallback} in the bin directories.
Also, as I mentioned above, I would like to suggest exchanging the ordering of 2) and 3).
|
Another issue is that when, the current
|
Or, maybe we can keep the current Or, another possibility is to search i) |
Currently, I like this idea, though I need to think about it more later. It seems to solve the main issues cleanly with the minimum change. diff --git a/bash_completion b/bash_completion
index e67cc3d51..d9c1d1cce 100644
--- a/bash_completion
+++ b/bash_completion
@@ -3508,15 +3508,17 @@ _comp_load()
shift
local -a source_args=("$@")
- local i
- for i in "${!dirs[@]}"; do
- dir=${dirs[i]}/completions
- [[ -d $dir ]] || continue
- for compfile in "$cmdname.bash" "$cmdname"; do
- _comp_load__visit_file "$dir/$compfile" && return 0
- done
+ local dir
+ for dir in "${dirs[@]}"; do
+ _comp_load__visit_file "$dir/completions/$cmdname.bash" && return 0
done
+
_comp_load__visit_file "$_comp__base_directory/completions-core/$cmdname.bash" && return 0
+
+ for dir in "${dirs[@]}"; do
+ _comp_load__visit_file "$dir/completions/$cmdname" && return 0
+ done
+
_comp_load__visit_file "$_comp__base_directory/completions-fallback/$cmdname.bash" && return 0
# Look up simple "xspec" completions |
This might not be spot on off the bat, but it restores some of the way we used to load completions from.
In particular, before this, completions-core and completions-fallback from the bash_completion location were not attempted, which is a regression at least for my workflow: I rely on being able to modify files in my bash-completion working dir and have them take precendence over any system installed ones.