Extract scp local/remote file treatment into functions, reuse them in rsync.
This commit is contained in:
parent
878b9a3e99
commit
329890a73b
@ -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
|
||||||
|
70
contrib/ssh
70
contrib/ssh
@ -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
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user