Add dir-only handling to scp remote/local completion functions, operate directly on $cur.

This commit is contained in:
Ville Skyttä 2009-12-26 16:19:24 +02:00
parent 76383dd49d
commit 000cae95bc
2 changed files with 37 additions and 13 deletions

View File

@ -70,7 +70,7 @@ _rsync()
break break
fi fi
done done
[ "$shell" = ssh ] && _scp_remote_files "$cur" [ "$shell" = ssh ] && _scp_remote_files
fi fi
;; ;;
*) *)

View File

@ -246,12 +246,14 @@ shopt -u hostcomplete && complete -F _sftp sftp
# things we want to escape in remote scp paths # things we want to escape in remote scp paths
_scp_path_esc="[][(){}<>\",:;^&\!$=?\`|\\ ']" _scp_path_esc="[][(){}<>\",:;^&\!$=?\`|\\ ']"
# Complete remote files with ssh. If the first arg is -d, complete on dirs
# only. Returns paths escaped with three backslashes.
_scp_remote_files() _scp_remote_files()
{ {
local IFS=$'\t\n' local IFS=$'\t\n'
# remove backslash escape from the first colon # remove backslash escape from the first colon
local cur=${1/\\:/:} cur=${cur/\\:/:}
local userhost=${cur%%?(\\):*} local userhost=${cur%%?(\\):*}
local path=${cur#*:} local path=${cur#*:}
@ -264,23 +266,45 @@ _scp_remote_files()
path=$(ssh -o 'Batchmode yes' $userhost pwd 2>/dev/null) path=$(ssh -o 'Batchmode yes' $userhost pwd 2>/dev/null)
fi fi
# escape spaces; remove executables, aliases, pipes and sockets; local files
# add space at end of file names if [ "$1" = -d ] ; then
COMPREPLY=( "${COMPREPLY[@]}" $( ssh -o 'Batchmode yes' $userhost \ # escape problematic characters; remove non-dirs
files=$( ssh -o 'Batchmode yes' $userhost \
command ls -aF1d "$path*" 2>/dev/null | \
sed -e 's/'$_scp_path_esc'/\\\\\\&/g' -e '/[^\/]$/d' )
else
# escape problematic characters; remove executables, aliases, pipes
# and sockets; add space at end of file names
files=$( ssh -o 'Batchmode yes' $userhost \
command ls -aF1d "$path*" 2>/dev/null | \ command ls -aF1d "$path*" 2>/dev/null | \
sed -e 's/'$_scp_path_esc'/\\\\\\&/g' -e 's/[*@|=]$//g' \ sed -e 's/'$_scp_path_esc'/\\\\\\&/g' -e 's/[*@|=]$//g' \
-e 's/[^\/]$/& /g' ) ) -e 's/[^\/]$/& /g' )
fi
COMPREPLY=( "${COMPREPLY[@]}" $files )
} }
# This approach is used instead of _filedir to get a space appended # This approach is used instead of _filedir to get a space appended
# after local file/dir completions, and -o nospace retained for others. # after local file/dir completions, and -o nospace retained for others.
# Args: 1=prefix to strip (optional) # If first arg is -d, complete on directory names only. The next arg is
# an optional prefix to add to returned completions.
_scp_local_files() _scp_local_files()
{ {
local IFS=$'\t\n' local IFS=$'\t\n'
local dirsonly=false
if [ "$1" = -d ]; then
dirsonly=true
shift
fi
if $dirsonly ; then
COMPREPLY=( "${COMPREPLY[@]}" $( command ls -aF1d $cur* 2>/dev/null | \
sed -e "s/$_scp_path_esc/\\\\&/g" -e '/[^\/]$/d' -e "s/^/$1/") )
else
COMPREPLY=( "${COMPREPLY[@]}" $( command ls -aF1d $cur* 2>/dev/null | \ COMPREPLY=( "${COMPREPLY[@]}" $( command ls -aF1d $cur* 2>/dev/null | \
sed -e "s/$_scp_path_esc/\\\\&/g" -e 's/[*@|=]$//g' \ sed -e "s/$_scp_path_esc/\\\\&/g" -e 's/[*@|=]$//g' \
-e 's/[^\/]$/& /g' -e "s/^/$1/") ) -e 's/[^\/]$/& /g' -e "s/^/$1/") )
fi
} }
# scp(1) completion # scp(1) completion
@ -321,7 +345,7 @@ _scp()
_expand || return 0 _expand || return 0
if [[ "$cur" == *:* ]]; then if [[ "$cur" == *:* ]]; then
_scp_remote_files "$cur" _scp_remote_files
return 0 return 0
fi fi