Skip to content

Commit cec82cb

Browse files
mrc0mmandkeszybz
authored andcommitted
bash-completion: correctly react to an unescaped unit name
1 parent 665b0af commit cec82cb

File tree

2 files changed

+31
-7
lines changed

2 files changed

+31
-7
lines changed

shell-completion/bash/journalctl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,16 @@ _journalctl() {
8787
;;
8888
--unit|-u)
8989
comps=$(journalctl -F '_SYSTEMD_UNIT' 2>/dev/null)
90+
# Similarly to systemctl, we need to distinguish between
91+
# escaped and unescaped names in order to be able to correctly
92+
# complete them. In this particular case, if the name we're
93+
# trying to complete is unescaped (i.e. foo\x2dbaz), escape
94+
# it first, so the compgen below works as expected. For more
95+
# information about these shenanigans see the systemctl
96+
# completion file
97+
if ! [[ $cur =~ '\\' ]]; then
98+
cur="$(printf '%q' $cur)"
99+
fi
90100
compopt -o filenames
91101
;;
92102
--user-unit)

shell-completion/bash/systemctl.in

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,7 @@ __get_machines() {
119119

120120
_systemctl () {
121121
local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
122-
local cur_orig=$cur
123-
local i verb comps mode
122+
local i verb comps mode cur_orig
124123

125124
local -A OPTS=(
126125
[STANDALONE]='--all -a --reverse --after --before --defaults --force -f --full -l --global
@@ -223,11 +222,26 @@ _systemctl () {
223222
done
224223

225224
# When trying to match a unit name with certain special characters in its name (i.e
226-
# foo\x2dbar:01) they get escaped by bash along the way, thus causing any possible
227-
# match to fail. Let's unescape such characters in the verb we're trying to
228-
# autocomplete to avoid this, however, use the original verb (cur_orig)
229-
# during the final match (COMPREPLY)
230-
cur="$(echo $cur | xargs echo)"
225+
# foo\x2dbar:01) they get (un)escaped by bash along the way, thus causing any possible
226+
# match to fail.
227+
# The following condition solves two cases:
228+
# 1) We're trying to complete an already escaped unit name part,
229+
# i.e foo\\x2dba. In this case we need to unescape the name, so it
230+
# gets properly matched with the systemctl output (i.e. foo\x2dba).
231+
# However, we need to keep the original escaped name as well for the
232+
# final match, as the completion machinery does the unescaping
233+
# automagically.
234+
# 2) We're trying to complete an unescaped (literal) unit name part,
235+
# i.e. foo\x2dba. That means we don't have to do the unescaping
236+
# required for correct matching with systemctl's output, however,
237+
# we need to escape the name for the final match, where the completion
238+
# expects the string to be escaped.
239+
cur_orig=$cur
240+
if [[ $cur =~ '\\' ]]; then
241+
cur="$(echo $cur | xargs echo)"
242+
else
243+
cur_orig="$(printf '%q' $cur)"
244+
fi
231245

232246
if [[ -z $verb ]]; then
233247
comps="${VERBS[*]}"

0 commit comments

Comments
 (0)