Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: [PATCH] remote files completion: remove double-escaping



On 7/8/24 5:17 PM, Lawrence Velázquez wrote:
On May 28, 2024, at 11:40 AM, Lyn Fugmann <me@xxxxxxxx> wrote:

I finally got around to testing this. The behavior appears to depend only on the local version of rsync, not on the remote version. Tested using local rsync 3.2.3 and 3.2.7, remote rsync 3.1.3 and 3.2.7. So I think the patch should be fine as is. (I would expect very few people to run an over two years old version of rsync and a recent version of zsh on the same local machine.)

A GitHub user is inquiring about the status of this contribution.

https://github.com/zsh-users/zsh/pull/114#issuecomment-2212591419

a possible fix, open to a better option letter for _remote_files than -Q, since compadd has -Q.

diff --git a/Completion/Unix/Command/_rsync b/Completion/Unix/Command/_rsync
index c65266dbd..81d25a3f4 100644
--- a/Completion/Unix/Command/_rsync
+++ b/Completion/Unix/Command/_rsync
@@ -60,7 +60,14 @@ elif compset -P 1 '*::' || compset -P 1 'rsync://*/'; then
 elif compset -P 'rsync://'; then
   _rsync_user_or_host / "$@"
 elif compset -P 1 '*:'; then
-  _remote_files -- ssh
+  if [[ -v opt_args[(i)client---old-args] || $RSYNC_OLD_ARGS = 1 ]]; then
+    _remote_files -- ssh
+  else
+    # the 3.2.4+ way that rsync handles filenames does not protect *, ? and []
+    # so those characters still need to be escaped to prevent being treated as
+    # a pattern in the remote shell.
+    _remote_files -Q '[][*?]' -- ssh
+  fi
 else
   _rsync_user_or_host : "$@"
 fi
@@ -236,6 +243,7 @@ _rsync() {
     '*--include=[do not exclude files matching pattern]:pattern' \
     '--files-from=[read list of source-file names from specified file]:file:_files' \
     '(-0 --from0)'{-0,--from0}'[all *-from file lists are delimited by nulls]' \
+    '--old-args[disable the modern arg-protection idiom]' \
     '(-s --secluded-args)'{-s,--secluded-args}'[use the protocol to safely send arguments]' \
     "--trust-sender[trust the remote sender's file list]" \
     '--copy-as=[specify user & optional group for the copy]:user:_rsync_users_groups' \
diff --git a/Completion/Unix/Type/_remote_files b/Completion/Unix/Type/_remote_files
index 93e1b7f43..3f5459aad 100644
--- a/Completion/Unix/Type/_remote_files
+++ b/Completion/Unix/Type/_remote_files
@@ -11,6 +11,7 @@
 # - -g: specify a pattern to match against files
 #       p, = and * glob qualifiers supported
 # - -h: specify the remote host, default is ${IPREFIX%:}
+# - -Q: specify a pattern of characters to escape in the returned filenames
 # - -W: specify the parent directory to list files from,
 #       default is the home directory
 #
@@ -31,14 +32,14 @@


 # There should be coloring based on all the different ls -F classifiers.
-local expl rempat remfiles remdispf remdispd args cmd suf ret=1
+local expl rempat remfiles remdispf{,q} remdispd{,q} args cmd suf ret=1
 local -a args cmd_args
-local glob host dir dirprefix
+local glob host dir esc dirprefix

 if zstyle -T ":completion:${curcontext}:files" remote-access; then

   # Parse options to _remote_files. Stops at the first "--".
-  zparseopts -D -E -a args / g:=glob h:=host W:=dir
+  zparseopts -D -E -a args / g:=glob h:=host W:=dir Q:=esc
   (( $#host)) && shift host || host="${IPREFIX%:}"

   args=( ${argv[1,(i)--]} )
@@ -85,6 +86,14 @@ if zstyle -T ":completion:${curcontext}:files" remote-access; then
     remdispf=( ${(M)remdispf:#${~glob[2]}} )
   fi

+  if (( $#esc )); then
+    remdispfq=(${${remdispf%[*=|]}//(#b)(${~esc[2]})/\\$match[1]})
+    remdispdq=(${${remdispd%/}//(#b)(${~esc[2]})/\\$match[1]})
+  else
+    remdispfq=(${(q)remdispf%[*=|]})
+    remdispdq=(${(q)remdispd%/})
+  fi
+
   local -a autoremove
   [[ -o autoremoveslash ]] && autoremove=(-r "/ \t\n\-")

@@ -92,9 +101,9 @@ if zstyle -T ":completion:${curcontext}:files" remote-access; then
   while _tags; do
     while _next_label remote-files expl ${suf:-remote directory}; do
       [[ -n $suf ]] &&
-          compadd "$args[@]" "$expl[@]" -d remdispf -- ${(q)remdispf%[*=|]} && ret=0
+        compadd "$args[@]" "$expl[@]" -d remdispf -- $remdispfq && ret=0
       compadd ${suf:+-S/} $autoremove "$args[@]" "$expl[@]" -d remdispd \
-	-- ${(q)remdispd%/} && ret=0
+        -- $remdispdq && ret=0
     done
     (( ret )) || return 0
   done





Messages sorted by: Reverse Date, Date, Thread, Author