zsh-workers
 help / color / mirror / code / Atom feed
* Directory completion acts as if CHASE_LINKS is set
@ 2013-09-05  1:23 Jan Larres
  2013-09-05  2:15 ` Jan Larres
  2013-09-05 15:31 ` Bart Schaefer
  0 siblings, 2 replies; 13+ messages in thread
From: Jan Larres @ 2013-09-05  1:23 UTC (permalink / raw)
  To: zsh-workers

Hi,

I recently noticed that completion of directories acts as if the 
CHASE_LINKS option is set, that is if you are in a symlinked directory 
and you want to complete its siblings then it will complete using the 
physical siblings instead of the ones from the directory that the 
symlink resides in.

Here's an example. Note that neither CHASE_LINKS nor CHASE_DOTS is set.

$ zsh --version
zsh 5.0.2 (x86_64-pc-linux-gnu)
$ zsh -f
vanadis% tree -F
.
├── bar/
└── foo/
     ├── bar -> ../bar/
     └── baz/

4 directories, 0 files
vanadis% cd foo/bar
vanadis% cd ../[TAB]
bar/  foo/


Jan


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Directory completion acts as if CHASE_LINKS is set
  2013-09-05  1:23 Directory completion acts as if CHASE_LINKS is set Jan Larres
@ 2013-09-05  2:15 ` Jan Larres
  2013-09-05 15:31 ` Bart Schaefer
  1 sibling, 0 replies; 13+ messages in thread
From: Jan Larres @ 2013-09-05  2:15 UTC (permalink / raw)
  To: zsh-workers

On 05/09/13 13:23, Jan Larres wrote:
> I recently noticed that completion of directories acts as if the
> CHASE_LINKS option is set, that is if you are in a symlinked directory
> and you want to complete its siblings then it will complete using the
> physical siblings instead of the ones from the directory that the
> symlink resides in.

Quick clarification: this doesn't just apply to directories, any file 
completion that tries to complete siblings of a symlinked directory is 
affected.

Jan


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Directory completion acts as if CHASE_LINKS is set
  2013-09-05  1:23 Directory completion acts as if CHASE_LINKS is set Jan Larres
  2013-09-05  2:15 ` Jan Larres
@ 2013-09-05 15:31 ` Bart Schaefer
  2013-09-06  1:42   ` Jan Larres
  2013-09-06 20:09   ` Peter Stephenson
  1 sibling, 2 replies; 13+ messages in thread
From: Bart Schaefer @ 2013-09-05 15:31 UTC (permalink / raw)
  To: zsh-workers

On Sep 5,  1:23pm, Jan Larres wrote:
}
} I recently noticed that completion of directories acts as if the 
} CHASE_LINKS option is set, that is if you are in a symlinked directory 
} and you want to complete its siblings then it will complete using the 
} physical siblings instead of the ones from the directory that the 
} symlink resides in.

"cd" itself is smart enough to interpret "../foo" as a physical path when
using it as a symbolic path does not work, so the completion list in this
example is incomplete rather than incorrect, which is probably why no one
has ever noticed.

In any case, this is a problem inherent in the way globbing interprets
"../" -- filename generation does not obey the same rules as "cd" path
resolution.

torch% print ../*(/)
../bar ../foo
torch% print $PWD:h/*(/)
/tmp/cdtest/foo/baz

Completion uses globbing to generate the target file names, so this has
to be fixed up somehow in _cd before _path_files is called.

This patch is a step in the right direction, but has the side-effect of
expanding ".." into $PWD:h which is probably not desirable.  There may
be other nuances [particularly with completion in the middle of a word]
that are not handled.  So I'm not going to commit it, just presenting it
for purposes of discussion.

diff --git a/Completion/Zsh/Command/_cd b/Completion/Zsh/Command/_cd
index 476947f..9c82a2f 100644
--- a/Completion/Zsh/Command/_cd
+++ b/Completion/Zsh/Command/_cd
@@ -51,6 +51,14 @@ else
     _directory_stack && ret=0
   fi
 
+  if [[ $PREFIX = (|*/)..(|/*) ]]; then
+    local tmpprefix
+    # Use cd in a subshell to properly [not] resolve symlinks
+    tmpprefix=$(cd $PREFIX >&/dev/null && print $PWD) ||
+      tmpprefix=$(cd $PREFIX:h >&/dev/null && print $PWD/$PREFIX:t)
+    [[ -n $tmpprefix ]] && PREFIX=$tmpprefix
+  fi
+
   if [[ $PREFIX != (\~|/|./|../)* ]]; then
     local tmpcdpath alt
 

-- 
Barton E. Schaefer


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Directory completion acts as if CHASE_LINKS is set
  2013-09-05 15:31 ` Bart Schaefer
@ 2013-09-06  1:42   ` Jan Larres
  2013-09-06  6:13     ` Bart Schaefer
  2013-09-06 20:09   ` Peter Stephenson
  1 sibling, 1 reply; 13+ messages in thread
From: Jan Larres @ 2013-09-06  1:42 UTC (permalink / raw)
  To: zsh-workers

On 06/09/13 03:31, Bart Schaefer wrote:
> In any case, this is a problem inherent in the way globbing interprets
> "../" -- filename generation does not obey the same rules as "cd" path
> resolution.
>
> torch% print ../*(/)
> ../bar ../foo
> torch% print $PWD:h/*(/)
> /tmp/cdtest/foo/baz
>
> Completion uses globbing to generate the target file names, so this has
> to be fixed up somehow in _cd before _path_files is called.
>
> This patch is a step in the right direction, but has the side-effect of
> expanding ".." into $PWD:h which is probably not desirable.  There may
> be other nuances [particularly with completion in the middle of a word]
> that are not handled.  So I'm not going to commit it, just presenting it
> for purposes of discussion.

Thanks, that patch does solve the issue with cd to a certain degree. But 
as you said yourself it is not specific to cd – for example, 'ls 
../[TAB]' has the same problem. So I assume that patching the individual 
command completions is not the best way to go about it, but I'm not 
familiar enough with the zsh internals to know what the right way would be.

Jan


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Directory completion acts as if CHASE_LINKS is set
  2013-09-06  1:42   ` Jan Larres
@ 2013-09-06  6:13     ` Bart Schaefer
  2013-09-06  6:46       ` Jan Larres
  0 siblings, 1 reply; 13+ messages in thread
From: Bart Schaefer @ 2013-09-06  6:13 UTC (permalink / raw)
  To: zsh-workers

On Sep 6,  1:42pm, Jan Larres wrote:
} Subject: Re: Directory completion acts as if CHASE_LINKS is set
}
} On 06/09/13 03:31, Bart Schaefer wrote:
} > In any case, this is a problem inherent in the way globbing interprets
} > "../" -- filename generation does not obey the same rules as "cd" path
} > resolution.
} 
} Thanks, that patch does solve the issue with cd to a certain degree. But 
} as you said yourself it is not specific to cd - for example, 'ls ../[TAB]'
} has the same problem.

No, you misunderstand.  It actually *is* specific to cd -- ls is an
external command and will physically follow ../, so it is correct for
completion for ls to do so as well.

Only in shell builtins can ../ refer to $PWD:h/, and the only builtins
that have this behavior are cd and pushd.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Directory completion acts as if CHASE_LINKS is set
  2013-09-06  6:13     ` Bart Schaefer
@ 2013-09-06  6:46       ` Jan Larres
  0 siblings, 0 replies; 13+ messages in thread
From: Jan Larres @ 2013-09-06  6:46 UTC (permalink / raw)
  To: zsh-workers

On 06/09/13 18:13, Bart Schaefer wrote:
> On Sep 6,  1:42pm, Jan Larres wrote:
> } Subject: Re: Directory completion acts as if CHASE_LINKS is set
> }
> } On 06/09/13 03:31, Bart Schaefer wrote:
> } > In any case, this is a problem inherent in the way globbing interprets
> } > "../" -- filename generation does not obey the same rules as "cd" path
> } > resolution.
> }
> } Thanks, that patch does solve the issue with cd to a certain degree. But
> } as you said yourself it is not specific to cd - for example, 'ls ../[TAB]'
> } has the same problem.
>
> No, you misunderstand.  It actually *is* specific to cd -- ls is an
> external command and will physically follow ../, so it is correct for
> completion for ls to do so as well.

Huh, you're right. I never noticed that. That's rather counterintuitive. 
Then I guess cd completion really is the only thing that can be changed. 
Thanks for clarifying!


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Directory completion acts as if CHASE_LINKS is set
  2013-09-05 15:31 ` Bart Schaefer
  2013-09-06  1:42   ` Jan Larres
@ 2013-09-06 20:09   ` Peter Stephenson
  2013-09-07  5:03     ` Bart Schaefer
  1 sibling, 1 reply; 13+ messages in thread
From: Peter Stephenson @ 2013-09-06 20:09 UTC (permalink / raw)
  To: zsh-workers

On Thu, 05 Sep 2013 08:31:39 -0700
Bart Schaefer <schaefer@brasslantern.com> wrote:
> diff --git a/Completion/Zsh/Command/_cd b/Completion/Zsh/Command/_cd
> index 476947f..9c82a2f 100644
> --- a/Completion/Zsh/Command/_cd
> +++ b/Completion/Zsh/Command/_cd
> @@ -51,6 +51,14 @@ else
>      _directory_stack && ret=0
>    fi
>  
> +  if [[ $PREFIX = (|*/)..(|/*) ]]; then
> +    local tmpprefix
> +    # Use cd in a subshell to properly [not] resolve symlinks
> +    tmpprefix=$(cd $PREFIX >&/dev/null && print $PWD) ||
> +      tmpprefix=$(cd $PREFIX:h >&/dev/null && print $PWD/$PREFIX:t)
> +    [[ -n $tmpprefix ]] && PREFIX=$tmpprefix
> +  fi
> +
>    if [[ $PREFIX != (\~|/|./|../)* ]]; then
>      local tmpcdpath alt

You're probably going to be better off using ${PREFIX:a} rather than
cd.  I also wonder if it would be better only to look at previous
directory components, i.e. always take the PREFIX up to the last "/"
(and require that there be one) rather than have two cases.

I doubt there's much you can do better if you're completing in the
middle of the word.   If COMPLETEINWORD is not set, so you're sensitive
to $SUFFIX, you might use $PREFIX$SUFFIX, but apart from that $PREFIX
looks like the only interesting bit for path resolution.  This is rather
specialised.

-- 
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Directory completion acts as if CHASE_LINKS is set
  2013-09-06 20:09   ` Peter Stephenson
@ 2013-09-07  5:03     ` Bart Schaefer
  2013-09-08 17:51       ` Peter Stephenson
  0 siblings, 1 reply; 13+ messages in thread
From: Bart Schaefer @ 2013-09-07  5:03 UTC (permalink / raw)
  To: zsh-workers

On Sep 6,  9:09pm, Peter Stephenson wrote:
} Subject: Re: Directory completion acts as if CHASE_LINKS is set
}
} On Thu, 05 Sep 2013 08:31:39 -0700
} Bart Schaefer <schaefer@brasslantern.com> wrote:
} > +    # Use cd in a subshell to properly [not] resolve symlinks
} > +    tmpprefix=$(cd $PREFIX >&/dev/null && print $PWD) ||
} > +      tmpprefix=$(cd $PREFIX:h >&/dev/null && print $PWD/$PREFIX:t)
} 
} You're probably going to be better off using ${PREFIX:a} rather than
} cd.

No, sorry, that doesn't work; :a behaves like globbing and CHASE_DOTS:

torch% print $PWD
/tmp/cdtest/foo/bar
torch% x=..        
torch% print $x:a
/tmp/cdtest

As far as I can tell the only way to get symlinks resolved the way that
"cd" does with respect to whatever CHASE options are currently set, is
to actually perform the "cd".

} I also wonder if it would be better only to look at previous
} directory components, i.e. always take the PREFIX up to the last "/"
} (and require that there be one) rather than have two cases.

You'll have to actually write out what you mean here, because I can't
get it to work for e.g. "cd ../" without having the first case there.

} I doubt there's much you can do better if you're completing in the
} middle of the word.

Indeed.  Also things may be a bit strange when a cdablevar is at the
front of the path, with a /../ somewhere beyond it.

Any suggestions for how to avoid having "../" expand into $PWD:h/ on
the command line?  I tried fiddling with IPREFIX the way the cdablevars
branch does, but without success.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Directory completion acts as if CHASE_LINKS is set
  2013-09-07  5:03     ` Bart Schaefer
@ 2013-09-08 17:51       ` Peter Stephenson
  2013-09-08 21:26         ` Bart Schaefer
  0 siblings, 1 reply; 13+ messages in thread
From: Peter Stephenson @ 2013-09-08 17:51 UTC (permalink / raw)
  To: zsh-workers

On Fri, 06 Sep 2013 22:03:00 -0700
Bart Schaefer <schaefer@brasslantern.com> wrote:
> On Sep 6,  9:09pm, Peter Stephenson wrote:
> } Subject: Re: Directory completion acts as if CHASE_LINKS is set
> }
> } On Thu, 05 Sep 2013 08:31:39 -0700
> } Bart Schaefer <schaefer@brasslantern.com> wrote:
> } > +    # Use cd in a subshell to properly [not] resolve symlinks
> } > +    tmpprefix=$(cd $PREFIX >&/dev/null && print $PWD) ||
> } > +      tmpprefix=$(cd $PREFIX:h >&/dev/null && print $PWD/$PREFIX:t)
> 
> } I also wonder if it would be better only to look at previous
> } directory components, i.e. always take the PREFIX up to the last "/"
> } (and require that there be one) rather than have two cases.
> 
> You'll have to actually write out what you mean here, because I can't
> get it to work for e.g. "cd ../" without having the first case there.

I'm thinking of something like ${PREFIX%/*}.

pws


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Directory completion acts as if CHASE_LINKS is set
  2013-09-08 17:51       ` Peter Stephenson
@ 2013-09-08 21:26         ` Bart Schaefer
  2013-09-09  9:59           ` Peter Stephenson
  2013-09-10 14:26           ` Bart Schaefer
  0 siblings, 2 replies; 13+ messages in thread
From: Bart Schaefer @ 2013-09-08 21:26 UTC (permalink / raw)
  To: zsh-workers

On Sep 6, 10:03pm, Bart Schaefer wrote:
>
> On Sep 6,  9:09pm, Peter Stephenson wrote:
> }
> } You're probably going to be better off using ${PREFIX:a} rather than
> } cd.
>
> No, sorry, that doesn't work; :a behaves like globbing and CHASE_DOTS:
>
> torch% print $PWD
> /tmp/cdtest/foo/bar
> torch% x=..
> torch% print $x:a
> /tmp/cdtest

Hmm, I just noticed that :a does work like "cd" IF there is a path
prefix, that is, if "../" is not at the beginning of the value:

torch% x=$PWD/..     
torch% print $x $x:a
/tmp/cdtest/foo/bar/.. /tmp/cdtest/foo

So it might be possible to use :a, but it'd need a condition on the
form of $PREFIX.  However, the other bit that is simplified by doing
a real "cd" in a subshell is that cdablevars et al. are taken care of.

I suppose you could argue "that's cheating, it's important to avoid
the fork" ... but I've spent enough time on this as it is, someone
else can take over from here.


On Sep 8,  6:51pm, Peter Stephenson wrote:
} Subject: Re: Directory completion acts as if CHASE_LINKS is set
}
} > } I also wonder if it would be better only to look at previous
} > } directory components, i.e. always take the PREFIX up to the last "/"
} 
} I'm thinking of something like ${PREFIX%/*}.

Ah, I see.  Yes, that does work, and furthermore gave me the clue that I
needed to get the commmand line handling right.

Remaining question is whether to use ${IPREFIX}${PREFIX%/*}.  I did in
the assignment but not in the $(cd ...) as I can't think of a case for
cd where IPREFIX would have a useful value.


diff --git a/Completion/Zsh/Command/_cd b/Completion/Zsh/Command/_cd
index 476947f..5b581e7 100644
--- a/Completion/Zsh/Command/_cd
+++ b/Completion/Zsh/Command/_cd
@@ -51,6 +51,18 @@ else
     _directory_stack && ret=0
   fi
 
+  local -a tmpWpath
+  if [[ $PREFIX = (|*/)../* ]]; then
+    local tmpprefix
+    # Use cd in a subshell to properly [not] resolve symlinks
+    tmpprefix=$(cd ${PREFIX%/*} >&/dev/null && print $PWD)
+    if [[ -n $tmpprefix ]]; then
+      tmpWpath=(-W $tmpprefix)
+      IPREFIX=${IPREFIX}${PREFIX%/*}/
+      PREFIX=${PREFIX##*/}
+    fi
+  fi
+
   if [[ $PREFIX != (\~|/|./|../)* ]]; then
     local tmpcdpath alt
 
@@ -100,7 +112,7 @@ else
     return ret
   fi
   [[ CURRENT -ne 1 ]] && _wanted directories expl directory \
-      _path_files -/ && ret=0
+      _path_files $tmpWpath -/ && ret=0
 
   return ret
 fi


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Directory completion acts as if CHASE_LINKS is set
  2013-09-08 21:26         ` Bart Schaefer
@ 2013-09-09  9:59           ` Peter Stephenson
  2013-09-10 14:26           ` Bart Schaefer
  1 sibling, 0 replies; 13+ messages in thread
From: Peter Stephenson @ 2013-09-09  9:59 UTC (permalink / raw)
  To: zsh-workers

On Sun, 08 Sep 2013 14:26:28 -0700
Bart Schaefer <schaefer@brasslantern.com> wrote:
> Remaining question is whether to use ${IPREFIX}${PREFIX%/*}.  I did in
> the assignment but not in the $(cd ...) as I can't think of a case for
> cd where IPREFIX would have a useful value.

Doesn't seem to make a material difference that I can think of right
now.

pws


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Directory completion acts as if CHASE_LINKS is set
  2013-09-08 21:26         ` Bart Schaefer
  2013-09-09  9:59           ` Peter Stephenson
@ 2013-09-10 14:26           ` Bart Schaefer
  2013-09-10 22:34             ` Jan Larres
  1 sibling, 1 reply; 13+ messages in thread
From: Bart Schaefer @ 2013-09-10 14:26 UTC (permalink / raw)
  To: zsh-workers

On Sep 8,  2:26pm, Bart Schaefer wrote:
}
} Ah, I see.  Yes, that does work, and furthermore gave me the clue that I
} needed to get the commmand line handling right.

Discovered I needed a reference to $tmpWpath in one more place.  Here is
the final diff ... unless we find out I messed up about IPREFIX.


diff --git a/Completion/Zsh/Command/_cd b/Completion/Zsh/Command/_cd
index 476947f..a5d328f 100644
--- a/Completion/Zsh/Command/_cd
+++ b/Completion/Zsh/Command/_cd
@@ -51,6 +51,18 @@ else
     _directory_stack && ret=0
   fi
 
+  local -a tmpWpath
+  if [[ $PREFIX = (|*/)../* ]]; then
+    local tmpprefix
+    # Use cd in a subshell to properly [not] resolve symlinks
+    tmpprefix=$(cd ${PREFIX%/*} >&/dev/null && print $PWD)
+    if [[ -n $tmpprefix ]]; then
+      tmpWpath=(-W $tmpprefix)
+      IPREFIX=${IPREFIX}${PREFIX%/*}/
+      PREFIX=${PREFIX##*/}
+    fi
+  fi
+
   if [[ $PREFIX != (\~|/|./|../)* ]]; then
     local tmpcdpath alt
 
@@ -88,7 +100,7 @@ else
     # already handled by _command_names (see _autocd)
 
     [[ CURRENT -ne 1 || ( -z "$path[(r).]" && $PREFIX != */* ) ]] &&
-        alt=( "${cdpath+local-}directories:${cdpath+local }directory:_path_files -/" "$alt[@]" )
+        alt=( "${cdpath+local-}directories:${cdpath+local }directory:_path_files $tmpWpath -/" "$alt[@]" )
 
     if [[ CURRENT -eq argstart && noopts -eq 0 && $PREFIX = -* ]] &&
       zstyle -t ":completion:${curcontext}:options" complete-options; then
@@ -100,7 +112,7 @@ else
     return ret
   fi
   [[ CURRENT -ne 1 ]] && _wanted directories expl directory \
-      _path_files -/ && ret=0
+      _path_files $tmpWpath -/ && ret=0
 
   return ret
 fi


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Directory completion acts as if CHASE_LINKS is set
  2013-09-10 14:26           ` Bart Schaefer
@ 2013-09-10 22:34             ` Jan Larres
  0 siblings, 0 replies; 13+ messages in thread
From: Jan Larres @ 2013-09-10 22:34 UTC (permalink / raw)
  To: zsh-workers

On 11/09/13 02:26, Bart Schaefer wrote:
> Discovered I needed a reference to $tmpWpath in one more place.  Here is
> the final diff ... unless we find out I messed up about IPREFIX.

The patch seems to work fine for me, thanks!

Jan


^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2013-09-10 22:34 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-09-05  1:23 Directory completion acts as if CHASE_LINKS is set Jan Larres
2013-09-05  2:15 ` Jan Larres
2013-09-05 15:31 ` Bart Schaefer
2013-09-06  1:42   ` Jan Larres
2013-09-06  6:13     ` Bart Schaefer
2013-09-06  6:46       ` Jan Larres
2013-09-06 20:09   ` Peter Stephenson
2013-09-07  5:03     ` Bart Schaefer
2013-09-08 17:51       ` Peter Stephenson
2013-09-08 21:26         ` Bart Schaefer
2013-09-09  9:59           ` Peter Stephenson
2013-09-10 14:26           ` Bart Schaefer
2013-09-10 22:34             ` Jan Larres

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).