Skip to content

Commit c555c90

Browse files
committed
fix(scp): keep tilde in local paths by using _filedir instead of _expand
Do not replace `~` by `/home/user/` for local files to get behavior consistent with other tools like `ls`. Previous variant of candidates generating using `ls` is slightly modified to match literal tilde after a prefix like in `-F~configfile`. Earlier attempt to suppress `_expand` of tilde for whole bash completion [Debian #521406. bash-completion: leading tilde always expanded](https://bugs.debian.org/521406) was reverted since it broke tilde completion for `scp` [Ville Skyttä \[Bash-completion-devel\] `_expand`, scp and quoting](https://alioth-lists-archive.debian.net/pipermail/bash-completion-devel/2009-February/000973.html)
1 parent f575693 commit c555c90

File tree

1 file changed

+56
-10
lines changed

1 file changed

+56
-10
lines changed

completions/ssh

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,48 @@ _comp_xfunc_ssh_scp_remote_files()
473473

474474
_comp_deprecate_func _scp_remote_files _comp_xfunc_ssh_scp_remote_files
475475

476+
# Like `_filedir' but accepts a prefix similar to `compgen -P'
477+
# and intended for usage with `compopt -o nospace' and` mixed completions
478+
# `host:', `file ', and `folder/'. Postprocessing is required to escape
479+
# shell special characters and to remove trailing backslash added
480+
# to distinguish files with trailing space and spaces added after file names.
481+
# @param $1 If `-d', complete only on directories (actually unused).
482+
# Otherwise add `$1' prefix to each variant.
483+
# Warning! `-d' can not be specified as a prefix,
484+
# but `scp' does not have such option.
485+
_comp_xfunc_ssh_scp_local_filedir()
486+
{
487+
local COMPREPLY=()
488+
local dirsonly=
489+
if [[ ${1-} == -d ]]; then
490+
dirsonly=-d
491+
shift
492+
fi
493+
local prefix=${1-}
494+
495+
# Do not expand tilde after prefix.
496+
# Such case should be handled by caller.
497+
[[ -z "$prefix" || "$cur" != \~* ]] || return
498+
499+
_filedir $dirsonly
500+
501+
local f expanded append
502+
for f in "${COMPREPLY[@]}"; do
503+
expanded=$f
504+
__expand_tilde_by_ref expanded
505+
if [[ -d "$expanded" ]]; then
506+
append=/
507+
elif [[ -e "$expanded" ]]; then
508+
append=' '
509+
elif [[ "$f" = *[\ \\] ]]; then
510+
append=\\
511+
else
512+
append=
513+
fi
514+
printf "%s" "$prefix$f$append$IFS"
515+
done
516+
}
517+
476518
# This approach is used instead of _filedir to get a space appended
477519
# after local file/dir completions, and -o nospace retained for others.
478520
# If first arg is -d, complete on directory names only. The next arg is
@@ -481,20 +523,26 @@ _comp_xfunc_ssh_scp_local_files()
481523
{
482524
local IFS=$'\n'
483525

484-
local dirsonly=false
526+
local dirsonly
485527
if [[ ${1-} == -d ]]; then
486-
dirsonly=true
528+
dirsonly=-d
487529
shift
488530
fi
489-
490-
if $dirsonly; then
491-
COMPREPLY+=($(command ls -aF1dL $cur* 2>/dev/null |
531+
local prefix=${1-}
532+
# e.g. "-F~file" should be completed with literal tilde
533+
if [[ -z "$prefix" || "$cur" != \~* ]]; then
534+
local i=${#COMPREPLY[@]}
535+
# Unescape trailing "\ " and drop trailing "\\".
536+
COMPREPLY+=($(_comp_xfunc_ssh_scp_local_filedir $dirsonly "$@" |
537+
command sed -e "s/$_comp_cmd_scp__path_esc/\\\\&/g" -e 's/\\ $/ /' -e 's/\\$//'))
538+
elif [ -n "$dirsonly" ]; then
539+
COMPREPLY+=($(command ls -aF1dL "$cur"* 2>/dev/null |
492540
command sed -e "s/$_comp_cmd_scp__path_esc/\\\\&/g" -e '/[^\/]$/d' \
493-
-e "s/^/${1-}/"))
541+
-e "s/^/$prefix/"))
494542
else
495-
COMPREPLY+=($(command ls -aF1dL $cur* 2>/dev/null |
543+
COMPREPLY+=($(command ls -aF1dL "$cur"* 2>/dev/null |
496544
command sed -e "s/$_comp_cmd_scp__path_esc/\\\\&/g" -e 's/[*@|=]$//g' \
497-
-e 's/[^\/]$/& /g' -e "s/^/${1-}/"))
545+
-e 's/[^\/]$/& /g' -e "s/^/$prefix/"))
498546
fi
499547
}
500548

@@ -557,8 +605,6 @@ _scp()
557605
;;
558606
esac
559607

560-
_expand || return
561-
562608
case $cur in
563609
!(*:*)/* | [.~]*) ;; # looks like a path
564610
*:*)

0 commit comments

Comments
 (0)