Skip to content

Commit 38855ad

Browse files
committed
fix(java,rsync,ssh): complete syntactically incomplete cur
#1255 (comment)
1 parent eac9fd4 commit 38855ad

File tree

6 files changed

+43
-3
lines changed

6 files changed

+43
-3
lines changed

bash_completion

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,24 @@ _comp_dequote()
251251
fi
252252
}
253253

254+
# Try to reconstruct an incomplete word and apply _comp_dequote.
255+
# @since 2.16
256+
_comp_dequote_incomplete()
257+
{
258+
local word=${1-}
259+
if ! [[ $word =~ $_comp_dequote__regex_safe_word ]]; then
260+
# shellcheck disable=SC1003
261+
if [[ ${word%'\'} =~ $_comp_dequote__regex_safe_word ]]; then
262+
word=${word%'\'}
263+
elif [[ $word\' =~ $_comp_dequote__regex_safe_word ]]; then
264+
word=$word\'
265+
elif [[ $word\" =~ $_comp_dequote__regex_safe_word ]]; then
266+
word=$word\"
267+
fi
268+
fi
269+
_comp_dequote "$word"
270+
}
271+
254272
# Unset the given variables across a scope boundary. Useful for unshadowing
255273
# global scoped variables. Note that simply calling unset on a local variable
256274
# will not unshadow the global variable. Rather, the result will be a local

completions/java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ _comp_cmd_java__packages()
114114
local -a sourcepaths=("${REPLY[@]}")
115115

116116
local REPLY
117-
_comp_dequote "$cur"
117+
_comp_dequote_incomplete "$cur"
118118
local cur_val=${REPLY-}
119119

120120
# convert package syntax to path syntax

completions/ssh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,7 @@ _comp_xfunc_scp_compgen_remote_files()
533533
# unescape (3 backslashes to 1 for chars we escaped)
534534
REPLY=$(command sed -e 's/\\\\\\\('"$_comp_cmd_scp__path_esc"'\)/\\\1/g' <<<"$REPLY")
535535
fi
536-
_comp_dequote "$REPLY"
536+
_comp_dequote_incomplete "$REPLY"
537537
local cur_val=${REPLY-}
538538

539539
local _userhost=${cur_val%%:*}
@@ -576,7 +576,7 @@ _comp_xfunc_scp_compgen_local_files()
576576
fi
577577

578578
local REPLY
579-
_comp_dequote "$cur"
579+
_comp_dequote_incomplete "$cur"
580580
local cur_val=${REPLY-}
581581

582582
local files

test/fixtures/scp/local_path-backslash-a b.txt

Whitespace-only changes.

test/fixtures/scp/local_path-backslash-a\ b.txt

Whitespace-only changes.

test/t/test_scp.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,19 @@ def test_remote_path_with_spaces(self, bash):
115115
assert_bash_exec(bash, "unset -f ssh")
116116
assert completion == r"\\\ in\\\ filename.txt"
117117

118+
def test_remote_path_with_backslash(self, bash):
119+
assert_bash_exec(
120+
bash, "ssh() { printf '%s\\n' 'abc def.txt' 'abc\ def.txt'; }"
121+
)
122+
completion = assert_complete(bash, "scp remote_host:abc\\")
123+
assert_bash_exec(bash, "unset -f ssh")
124+
125+
# Note: The number of backslash escaping differs depending on the scp
126+
# version.
127+
assert completion == sorted(
128+
[r"abc\ def.txt", r"abc\\\ def.txt"]
129+
) or completion == sorted([r"abc\\\ def.txt", r"abc\\\\\\\ def.txt"])
130+
118131
def test_xfunc_remote_files(self, bash):
119132
with bash_env_saved(bash) as bash_env:
120133
bash_env.save_variable("COMPREPLY")
@@ -193,3 +206,12 @@ def test_local_path_with_spaces_1(self, completion):
193206
@pytest.mark.complete("scp spaced\\ ", cwd="scp")
194207
def test_local_path_with_spaces_2(self, completion):
195208
assert completion == "\\ conf"
209+
210+
@pytest.mark.complete("scp local_path-backslash-a\\", cwd="scp")
211+
def test_local_path_backslash(self, completion):
212+
assert completion == sorted(
213+
[
214+
r"local_path-backslash-a\ b.txt",
215+
r"local_path-backslash-a\\\ b.txt",
216+
]
217+
)

0 commit comments

Comments
 (0)