feat: support the startup{,-core} directory#1558
feat: support the startup{,-core} directory#1558akinomyoga wants to merge 5 commits intoscop:mainfrom
startup{,-core} directory#1558Conversation
ff2b028 to
d3c4a5b
Compare
yedayak
left a comment
There was a problem hiding this comment.
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?
README.md
Outdated
| 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 | ||
| files in `<startupdir>`, whose value in the current system can be retrieved | ||
| by `pkg-config bash-completion --variable=startupdir`, and install a | ||
| completion for the commands to override our completion for in them. |
There was a problem hiding this comment.
Maybe this should be split up? Installing system wide doesn't necessarily imply eagerly loaded.
Perhaps How can I override... and How to load completions eagerly on startup?
There was a problem hiding this comment.
Thank you for your review.
Yeah, that makes much more sense. It's been mixed, so I just updated locally, but I agree to separate the question.
There was a problem hiding this comment.
I reorganized related questions and answers. fc6787f
| # 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]_)} |
There was a problem hiding this comment.
Why is this processing needed?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Maybe the name "eagerly loaded settings" is not a good description for startup files that can be overridden by users?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
I also included the description of this behavior in fc6787f.
There was a problem hiding this comment.
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).
fc6787f to
59074b3
Compare
akinomyoga
left a comment
There was a problem hiding this comment.
I probably need to add tests.
31b52ee to
011affa
Compare
test/fixtures/_comp__init_collect_startup_configs/user/startup/000_foo.bash
Show resolved
Hide resolved
bash_completion
Outdated
There was a problem hiding this comment.
I think this isn't needed anymore since we don't ship bash_completion.d in the repo itself anymore
There was a problem hiding this comment.
Thank you. I've fixed this in push d89b679..5a1f187.
| # 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 = |
There was a problem hiding this comment.
We still need to create ${sysconfdir}/bash_completion.d
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
I thought the projects that want to put any file in
/etc/bash-completion.dcan 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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
| # system startup files earlier. | ||
| _comp__init_startup_configs=( | ||
| "${selected_startup_files[@]}" | ||
| ${_comp__init_startup_configs[@]+"${_comp__init_startup_configs[@]}"} |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Bash 4.2 has a bug that "${arr[@]}" fails with set -u for arr=().
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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[@]}"}\'; }',* chore(pkg-config): expose the "startupdir" pkg-config variable Co-authored-by: Yedaya Katsman <yedaya.ka@gmail.com>
This patch reorganizes the descriptions for installing/overriding completion settings to solve multiple issues. * First, the systemwide settings and eagerly loaded settings were conflated. The systemwide settings are not necessarily eagerly loaded completions. * The paths obtained by "pkg-config" usually point to the directory under `/usr/share`, which are the places for system packages provided by the distributions. User startup files and systemwide local settings should not be placed under the tree `/usr/local` in typical distributions or with typical package managers. The user startup files should be installed into the user's directory, and systemwide local settings should be installed in `/usr/local/share`. * We also distinguish the new startup files from the traditional eagerly loaded files
71ae643 to
6c1af0e
Compare
For startup scripts discussed in the separation of directories #1329.