bash-completion: correctly react to an unescaped unit name

This commit is contained in:
Frantisek Sumsal 2019-04-25 12:33:25 +02:00 committed by Zbigniew Jędrzejewski-Szmek
parent 665b0af866
commit cec82cb943
2 changed files with 31 additions and 7 deletions

View File

@ -87,6 +87,16 @@ _journalctl() {
;; ;;
--unit|-u) --unit|-u)
comps=$(journalctl -F '_SYSTEMD_UNIT' 2>/dev/null) comps=$(journalctl -F '_SYSTEMD_UNIT' 2>/dev/null)
# Similarly to systemctl, we need to distinguish between
# escaped and unescaped names in order to be able to correctly
# complete them. In this particular case, if the name we're
# trying to complete is unescaped (i.e. foo\x2dbaz), escape
# it first, so the compgen below works as expected. For more
# information about these shenanigans see the systemctl
# completion file
if ! [[ $cur =~ '\\' ]]; then
cur="$(printf '%q' $cur)"
fi
compopt -o filenames compopt -o filenames
;; ;;
--user-unit) --user-unit)

View File

@ -119,8 +119,7 @@ __get_machines() {
_systemctl () { _systemctl () {
local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
local cur_orig=$cur local i verb comps mode cur_orig
local i verb comps mode
local -A OPTS=( local -A OPTS=(
[STANDALONE]='--all -a --reverse --after --before --defaults --force -f --full -l --global [STANDALONE]='--all -a --reverse --after --before --defaults --force -f --full -l --global
@ -223,11 +222,26 @@ _systemctl () {
done done
# When trying to match a unit name with certain special characters in its name (i.e # When trying to match a unit name with certain special characters in its name (i.e
# foo\x2dbar:01) they get escaped by bash along the way, thus causing any possible # foo\x2dbar:01) they get (un)escaped by bash along the way, thus causing any possible
# match to fail. Let's unescape such characters in the verb we're trying to # match to fail.
# autocomplete to avoid this, however, use the original verb (cur_orig) # The following condition solves two cases:
# during the final match (COMPREPLY) # 1) We're trying to complete an already escaped unit name part,
cur="$(echo $cur | xargs echo)" # i.e foo\\x2dba. In this case we need to unescape the name, so it
# gets properly matched with the systemctl output (i.e. foo\x2dba).
# However, we need to keep the original escaped name as well for the
# final match, as the completion machinery does the unescaping
# automagically.
# 2) We're trying to complete an unescaped (literal) unit name part,
# i.e. foo\x2dba. That means we don't have to do the unescaping
# required for correct matching with systemctl's output, however,
# we need to escape the name for the final match, where the completion
# expects the string to be escaped.
cur_orig=$cur
if [[ $cur =~ '\\' ]]; then
cur="$(echo $cur | xargs echo)"
else
cur_orig="$(printf '%q' $cur)"
fi
if [[ -z $verb ]]; then if [[ -z $verb ]]; then
comps="${VERBS[*]}" comps="${VERBS[*]}"