Skip to content

Commit c55ee7f

Browse files
authored
Merge pull request #1412 from akinomyoga/scp-refactor-2
2 parents b6d4335 + dfa6222 commit c55ee7f

File tree

1 file changed

+56
-28
lines changed

1 file changed

+56
-28
lines changed

completions/ssh

Lines changed: 56 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,54 @@ _comp_cmd_sftp()
457457
# things we want to backslash escape in scp paths
458458
_comp_cmd_scp__path_esc='[][(){}<>"'"'"',:;^&!$=?`\\|[:space:]]'
459459

460+
# Escape shell special characters in filenames by backslash. This also
461+
# suffixes a space or a slash based on the file type.
462+
#
463+
# Note: With a non-empty prefix ($1 of _comp_xfunc_scp_compgen_local_files),
464+
# Bash will not recognize any filenames, so we need to perform the proper
465+
# quoting manually. We also need to manually suffix a space or a slash based
466+
# on the file type because "-o nospace" is specified. One might think of using
467+
# "compopt +o nospace" instead, but it would suffix a space to directory names
468+
# unexpectedly.
469+
#
470+
# Options:
471+
# -d Only directory names are selected.
472+
# @param $1 escape_replacement - If a non-empty value is specified, special
473+
# characters are replaced with the specified value (instead of the default
474+
# '\\&').
475+
# @stdin List of filenames in the "ls -1F" format, where filenames are
476+
# separated by newlines, and characters /*@|=> are suffixed based on the
477+
# types of the files.
478+
_comp_cmd_scp__escape_path()
479+
{
480+
local OPTIND=1 OPTARG="" OPTERR=0 opt dirs_only=""
481+
while getopts ':d' _flag "$@"; do
482+
case $_flag in
483+
d) dirs_only=set ;;
484+
*)
485+
echo "bash_completion: $FUNCNAME: usage error: $*" >&2
486+
return 1
487+
;;
488+
esac
489+
done
490+
shift "$((OPTIND - 1))"
491+
local escape_replacement=${1:-'\\&'}
492+
493+
if [[ $dirs_only ]]; then
494+
# escape problematic characters; remove non-dirs
495+
command sed \
496+
-e '/[^/]$/d' \
497+
-e 's/'"$_comp_cmd_scp__path_esc"'/'"$escape_replacement"'/g'
498+
else
499+
# escape problematic characters; remove executable, symlink, pipe,
500+
# socket and door indicators; add space at end of file names
501+
command sed \
502+
-e 's/[*@|=>]$//g' \
503+
-e 's/'"$_comp_cmd_scp__path_esc"'/'"$escape_replacement"'/g' \
504+
-e 's/[^/]$/& /g'
505+
fi
506+
}
507+
460508
# Complete remote files with ssh. Returns paths escaped with three backslashes
461509
# (unless -l option is provided).
462510
# Options:
@@ -501,20 +549,10 @@ _comp_xfunc_scp_compgen_remote_files()
501549
fi
502550

503551
local _files
504-
if [[ $_dirs_only ]]; then
505-
# escape problematic characters; remove non-dirs
506-
_files=$(ssh -o 'Batchmode yes' "$_userhost" \
507-
command ls -aF1dL "$_path*" 2>/dev/null |
508-
command sed -e 's/'"$_comp_cmd_scp__path_esc"'/'"$_escape_replacement"'/g' -e '/[^/]$/d')
509-
else
510-
# escape problematic characters; remove executables, aliases, pipes
511-
# and sockets; add space at end of file names
512-
_files=$(ssh -o 'Batchmode yes' "$_userhost" \
513-
command ls -aF1dL "$_path*" 2>/dev/null |
514-
command sed -e 's/[*@|=]$//g' \
515-
-e 's/'"$_comp_cmd_scp__path_esc"'/'"$_escape_replacement"'/g' \
516-
-e 's/[^/]$/& /g')
517-
fi
552+
_files=$(ssh -o 'Batchmode yes' "$_userhost" \
553+
command ls -aF1dL "$_path*" 2>/dev/null |
554+
_comp_cmd_scp__escape_path ${_dirs_only:+'-d'} -- \
555+
"$_escape_replacement")
518556
_comp_compgen -R split -l -- "$_files"
519557
}
520558

@@ -539,20 +577,10 @@ _comp_xfunc_scp_compgen_local_files()
539577

540578
local files
541579
_comp_expand_glob files '"$cur"*' || return 0
542-
if [[ $_dirs_only ]]; then
543-
_comp_compgen -RU files split -l ${1:+-P "$1"} -- "$(
544-
command ls -aF1dL "${files[@]}" 2>/dev/null |
545-
command sed -e "s/$_comp_cmd_scp__path_esc/\\\\&/g" \
546-
-e '/[^/]$/d'
547-
)"
548-
else
549-
_comp_compgen -RU files split -l ${1:+-P "$1"} -- "$(
550-
command ls -aF1dL "${files[@]}" 2>/dev/null |
551-
command sed -e 's/[*@|=]$//g' \
552-
-e "s/$_comp_cmd_scp__path_esc/\\\\&/g" \
553-
-e 's/[^/]$/& /g'
554-
)"
555-
fi
580+
_comp_compgen -RU files split -l ${1:+-P "$1"} -- "$(
581+
command ls -aF1dL "${files[@]}" 2>/dev/null |
582+
_comp_cmd_scp__escape_path ${_dirs_only:+'-d'}
583+
)"
556584
}
557585

558586
# @deprecated 2.12

0 commit comments

Comments
 (0)