Skip to content

Commit 538838c

Browse files
committed
refactor(scp): factorize common codes
1 parent 898fed7 commit 538838c

File tree

1 file changed

+43
-28
lines changed

1 file changed

+43
-28
lines changed

completions/ssh

+43-28
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,42 @@ _comp_cmd_sftp()
461461
# things we want to backslash escape in scp paths
462462
_comp_cmd_scp__path_esc='[][(){}<>"'"'"',:;^&!$=?`\\|[:space:]]'
463463

464+
# Escape shell special characters in filenames by backslash. This also
465+
# suffixes a space or a slash based on the file type.
466+
#
467+
# Note: With a non-empty prefix ($1 of _comp_xfunc_scp_compgen_local_files),
468+
# Bash will not recognize any filenames, so we need to perform the proper
469+
# quoting manually. We also need to manually suffix a space or a slash based
470+
# on the file type because "-o nospace" is specified. One might think of using
471+
# "compopt +o nospace" instead, but it would suffix a space to directory names
472+
# unexpectedly.
473+
#
474+
# @param $1 dirs_only - If a non-empty value is specified, only directory names
475+
# are selected.
476+
# @param $2 escape_replacement - If a non-empty value is specified, special
477+
# characters are replaced with the specified value (instead of the default
478+
# '\\&').
479+
# @stdin - List of filenames in the "ls -1F" format, where filenames are
480+
# separated by newlines, and characters /=@|* are suffixed based on the
481+
# types of the files.
482+
_comp_cmd_scp__escape_path()
483+
{
484+
local dirs_only=$1 escape_replacement=${2:-'\\&'}
485+
if [[ $dirs_only ]]; then
486+
# escape problematic characters; remove non-dirs
487+
command sed \
488+
-e '/[^/]$/d' \
489+
-e 's/'"$_comp_cmd_scp__path_esc"'/'"$escape_replacement"'/g'
490+
else
491+
# escape problematic characters; remove executables, aliases, pipes
492+
# and sockets; add space at end of file names
493+
command sed \
494+
-e 's/[*@|=]$//g' \
495+
-e 's/'"$_comp_cmd_scp__path_esc"'/'"$escape_replacement"'/g' \
496+
-e 's/[^/]$/& /g'
497+
fi
498+
}
499+
464500
# Complete remote files with ssh. Returns paths escaped with three backslashes
465501
# (unless -l option is provided).
466502
# Options:
@@ -505,20 +541,9 @@ _comp_xfunc_scp_compgen_remote_files()
505541
fi
506542

507543
local _files
508-
if [[ $_dirs_only ]]; then
509-
# escape problematic characters; remove non-dirs
510-
_files=$(ssh -o 'Batchmode yes' "$_userhost" \
511-
command ls -aF1dL "$_path*" 2>/dev/null |
512-
command sed -e 's/'"$_comp_cmd_scp__path_esc"'/'"$_escape_replacement"'/g' -e '/[^/]$/d')
513-
else
514-
# escape problematic characters; remove executables, aliases, pipes
515-
# and sockets; add space at end of file names
516-
_files=$(ssh -o 'Batchmode yes' "$_userhost" \
517-
command ls -aF1dL "$_path*" 2>/dev/null |
518-
command sed -e 's/[*@|=]$//g' \
519-
-e 's/'"$_comp_cmd_scp__path_esc"'/'"$_escape_replacement"'/g' \
520-
-e 's/[^/]$/& /g')
521-
fi
544+
_files=$(ssh -o 'Batchmode yes' "$_userhost" \
545+
command ls -aF1dL "$_path*" 2>/dev/null |
546+
_comp_cmd_scp__escape_path "$_dirs_only" "$_escape_replacement")
522547
_comp_compgen -R split -l -- "$_files"
523548
}
524549

@@ -543,20 +568,10 @@ _comp_xfunc_scp_compgen_local_files()
543568

544569
local files
545570
_comp_expand_glob files '"$cur"*' || return 0
546-
if [[ $_dirsonly ]]; then
547-
_comp_compgen -RU files split -l ${1:+-P "$1"} -- "$(
548-
command ls -aF1dL "${files[@]}" 2>/dev/null |
549-
command sed -e "s/$_comp_cmd_scp__path_esc/\\\\&/g" \
550-
-e '/[^/]$/d'
551-
)"
552-
else
553-
_comp_compgen -RU files split -l ${1:+-P "$1"} -- "$(
554-
command ls -aF1dL "${files[@]}" 2>/dev/null |
555-
command sed -e 's/[*@|=]$//g' \
556-
-e "s/$_comp_cmd_scp__path_esc/\\\\&/g" \
557-
-e 's/[^/]$/& /g'
558-
)"
559-
fi
571+
_comp_compgen -RU files split -l ${1:+-P "$1"} -- "$(
572+
command ls -aF1dL "${files[@]}" 2>/dev/null |
573+
_comp_cmd_scp__escape_path "$_dirsonly"
574+
)"
560575
}
561576

562577
# @deprecated 2.12

0 commit comments

Comments
 (0)