Extract scp local/remote file treatment into functions, reuse them in rsync.

This commit is contained in:
Ville Skyttä 2009-12-25 12:30:01 +02:00
parent 878b9a3e99
commit 329890a73b
2 changed files with 57 additions and 58 deletions

View File

@ -5,11 +5,9 @@ _rsync()
{ {
# TODO: _split_longopt # TODO: _split_longopt
local cur prev shell i userhost path
COMPREPLY=() COMPREPLY=()
cur=`_get_cword :` local cur=`_get_cword :`
prev=${COMP_WORDS[COMP_CWORD-1]} local prev=`_get_pword :`
_expand || return 0 _expand || return 0
@ -63,42 +61,27 @@ _rsync()
--no-detach' -- "$cur" ) ) --no-detach' -- "$cur" ) )
;; ;;
*:*) *:*)
if type _scp_remote_files &>/dev/null; then
# find which remote shell is used # find which remote shell is used
shell=ssh local i shell=ssh
for (( i=1; i < COMP_CWORD; i++ )); do for (( i=1; i < COMP_CWORD; i++ )); do
if [[ "${COMP_WORDS[i]}" == -@(e|-rsh) ]]; then if [[ "${COMP_WORDS[i]}" == -@(e|-rsh) ]]; then
shell=${COMP_WORDS[i+1]} shell=${COMP_WORDS[i+1]}
break break
fi fi
done done
if [[ "$shell" == ssh ]]; then [ "$shell" = ssh ] && _scp_remote_files "$cur"
# remove backslash escape from :
cur=${cur/\\:/:}
userhost=${cur%%?(\\):*}
path=${cur#*:}
# unescape spaces
path=${path//\\\\\\\\ / }
if [ -z "$path" ]; then
# default to home dir of specified user on remote host
path=$(ssh -o 'Batchmode yes' $userhost pwd 2>/dev/null)
fi
# escape spaces; remove executables, aliases, pipes and sockets;
# add space at end of file names
COMPREPLY=( $( ssh -o 'Batchmode yes' $userhost \
command ls -aF1d "$path*" 2>/dev/null | \
sed -e 's/ /\\\\\\\ /g' -e 's/[*@|=]$//g' \
-e 's/[^\/]$/& /g' ) )
fi fi
;; ;;
*) *)
_known_hosts_real -c -a "$cur" _known_hosts_real -c -a "$cur"
_filedir type _scp_local_files &>/dev/null && _scp_local_files || _filedir
;; ;;
esac esac
return 0 return 0
} && } &&
complete -F _rsync -o nospace -o filenames rsync complete -F _rsync -o nospace rsync
# Local variables: # Local variables:
# mode: shell-script # mode: shell-script

View File

@ -243,12 +243,51 @@ _sftp()
} }
shopt -u hostcomplete && complete -F _sftp sftp shopt -u hostcomplete && complete -F _sftp sftp
# things we want to escape in remote scp paths
_scp_path_esc="[][(){}<>\",:;^&\!$=?\`|\\ ']"
_scp_remote_files()
{
local IFS=$'\t\n'
# remove backslash escape from the first colon
local cur=${1/\\:/:}
local userhost=${cur%%?(\\):*}
local path=${cur#*:}
# unescape (3 backslashes to 1 for chars we escaped)
path=$( sed -e 's/\\\\\\\('$_scp_path_esc'\)/\\\1/g' <<<"$path" )
# default to home dir of specified user on remote host
if [ -z "$path" ]; then
path=$(ssh -o 'Batchmode yes' $userhost pwd 2>/dev/null)
fi
# escape spaces; remove executables, aliases, pipes and sockets;
# add space at end of file names
COMPREPLY=( "${COMPREPLY[@]}" $( ssh -o 'Batchmode yes' $userhost \
command ls -aF1d "$path*" 2>/dev/null | \
sed -e 's/'$_scp_path_esc'/\\\\\\&/g' -e 's/[*@|=]$//g' \
-e 's/[^\/]$/& /g' ) )
}
# This approach is used instead of _filedir to get a space appended
# after local file/dir completions, and -o nospace retained for others.
# Args: 1=prefix to strip (optional)
_scp_local_files()
{
local IFS=$'\t\n'
COMPREPLY=( "${COMPREPLY[@]}" $( command ls -aF1d $cur* 2>/dev/null | \
sed -e "s/$_scp_path_esc/\\\\&/g" -e 's/[*@|=]$//g' \
-e 's/[^\/]$/& /g' -e "s/^/$1/") )
}
# scp(1) completion # scp(1) completion
# #
_scp() _scp()
{ {
local configfile cur prev userhost path prefix local configfile cur prev prefix
COMPREPLY=() COMPREPLY=()
cur=`_get_cword ":"` cur=`_get_cword ":"`
@ -281,30 +320,12 @@ _scp()
_expand || return 0 _expand || return 0
# things we want to backslash escape
local esc="[][(){}<>\",:;^&\!$=?\`|\\ ']"
if [[ "$cur" == *:* ]]; then if [[ "$cur" == *:* ]]; then
local IFS=$'\t\n' _scp_remote_files "$cur"
# remove backslash escape from the first colon
cur=${cur/\\:/:}
userhost=${cur%%?(\\):*}
path=${cur#*:}
# unescape (3 backslashes to 1 for chars we escaped)
path=$( sed -e 's/\\\\\\\('$esc'\)/\\\1/g' <<<"$path" )
if [ -z "$path" ]; then
# default to home dir of specified user on remote host
path=$(ssh -o 'Batchmode yes' $userhost pwd 2>/dev/null)
fi
# escape spaces; remove executables, aliases, pipes and sockets;
# add space at end of file names
COMPREPLY=( $( ssh -o 'Batchmode yes' $userhost \
command ls -aF1d "$path*" 2>/dev/null | \
sed -e 's/'$esc'/\\\\\\&/g' -e 's/[*@|=]$//g' -e 's/[^\/]$/& /g' ) )
return 0 return 0
fi fi
if [[ "$cur" = -F* ]]; then if [[ "$cur" == -F* ]]; then
cur=${cur#-F} cur=${cur#-F}
prefix=-F prefix=-F
else else
@ -339,12 +360,7 @@ _scp()
esac esac
fi fi
# This approach is used instead of _filedir to get a space appended _scp_local_files "$prefix"
# after local file/dir completions, and -o nospace retained for others.
local IFS=$'\t\n'
COMPREPLY=( "${COMPREPLY[@]}" $( command ls -aF1d $cur* 2>/dev/null | \
sed -e "s/$esc/\\\\&/g" -e 's/[*@|=]$//g' -e 's/[^\/]$/& /g' \
-e "s/^/$prefix/") )
return 0 return 0
} }