zsh-workers
 help / color / mirror / code / Atom feed
* [PATCH] expand '..n' to equivalent number of '..' segments in fixdir
@ 2020-05-10  4:37 Dian M Fay
  2020-05-10  4:43 ` Roman Perepelitsa
  0 siblings, 1 reply; 9+ messages in thread
From: Dian M Fay @ 2020-05-10  4:37 UTC (permalink / raw)
  To: zsh-workers

dian@lamia ~/work/zsh cd ..2
dian@lamia ~ cd ..123
dian@lamia / cd ~/..2/home/dian/work/../work/zsh
dian@lamia ~/work/zsh cd ..2/work/zsh
dian@lamia ~/work/zsh

I added a minimal test case and so far it seems to do what I expect, but I don't know if there are any side effects to worry about.

diff --git a/Src/builtin.c b/Src/builtin.c
index d5a874a95..3a13f19ee 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -1353,8 +1353,12 @@ fixdir(char *src)
 	    *dest = '\0';
 	    return chasedots;
 	}
-	if (src[0] == '.' && src[1] == '.' &&
-	    (src[2] == '\0' || src[2] == '/')) {
+	if (src[0] == '.' && src[1] == '.') {
+	    int backtracks = src[2] == '\0' || src[2] == '/' ? 1 : atoi(src + 2);
+
+	    if (backtracks < 1)
+		backtracks = 1;
+
 	    if (isset(CHASEDOTS) || chasedots > 1) {
 		chasedots = 1;
 		/* and treat as normal path segment */
@@ -1375,11 +1379,16 @@ fixdir(char *src)
 			*ptrd = '\0';
 			return 1;
 		    }
-		    for (dest--; dest > d0 + 1 && dest[-1] != '/'; dest--);
-		    if (dest[-1] != '/')
-			dest--;
+		    for (int i = 0; i < backtracks; i++) {
+			for (dest--; dest > d0 + 1 && dest[-1] != '/'; dest--);
+			if (dest[-1] != '/')
+			    dest--;
+			if (dest - 1 == d0)
+			    break;
+		    }
 		}
-		src++;
+		/* jump forward one space plus the length of any trailing digits */
+		src += backtracks == 1 ? 1 : (int) trunc(log10(backtracks)) + 2;
 		while (*++src == '/');
 		continue;
 	    }
diff --git a/Test/B01cd.ztst b/Test/B01cd.ztst
index 21e751dcb..f7f82147f 100644
--- a/Test/B01cd.ztst
+++ b/Test/B01cd.ztst
@@ -123,6 +123,14 @@ F:something is broken.  But you already knew that.
  print $PWD
 0q:Changing directory up through symbolic links without following them
 >$mydir
+>$mydir
+
+ cd $mydir/cdtst.tmp/sub/fake
+ cd ..3 &&
+ pwd &&
+ print $PWD
+0q:Changing directory up without following symlinks, shorter form
+>$mydir
 >$mydir
 
  setopt chaselinks

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

* Re: [PATCH] expand '..n' to equivalent number of '..' segments in fixdir
  2020-05-10  4:37 [PATCH] expand '..n' to equivalent number of '..' segments in fixdir Dian M Fay
@ 2020-05-10  4:43 ` Roman Perepelitsa
  2020-05-10  5:58   ` Bart Schaefer
  0 siblings, 1 reply; 9+ messages in thread
From: Roman Perepelitsa @ 2020-05-10  4:43 UTC (permalink / raw)
  To: Dian M Fay; +Cc: Zsh hackers list

On Sun, May 10, 2020 at 6:36 AM Dian M Fay <dian.m.fay@gmail.com> wrote:
>
> dian@lamia ~/work/zsh cd ..2
> dian@lamia ~ cd ..123
> dian@lamia /

`..2` is a valid directory name. So it's a breaking change.

~% mkdir ..2
~% cd ..2
~/..2%

Roman.

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

* Re: [PATCH] expand '..n' to equivalent number of '..' segments in fixdir
  2020-05-10  4:43 ` Roman Perepelitsa
@ 2020-05-10  5:58   ` Bart Schaefer
  2020-05-10  6:28     ` Bart Schaefer
  0 siblings, 1 reply; 9+ messages in thread
From: Bart Schaefer @ 2020-05-10  5:58 UTC (permalink / raw)
  To: Roman Perepelitsa; +Cc: Dian M Fay, Zsh hackers list

On Sat, May 9, 2020 at 9:44 PM Roman Perepelitsa
<roman.perepelitsa@gmail.com> wrote:
>
> On Sun, May 10, 2020 at 6:36 AM Dian M Fay <dian.m.fay@gmail.com> wrote:
> >
> > dian@lamia ~/work/zsh cd ..2
> > dian@lamia ~ cd ..123
> > dian@lamia /
>
> `..2` is a valid directory name. So it's a breaking change.

It can also be implemented as a shell function wrapper around "cd", so
it's not necessary to modify the C code.

Here's the basics, minus necessary handling for other cd options.

cd() {
  emulate -L zsh -o extendedglob -o histsubstpattern
  while [[ $1 = (#b)((#s)(|*/)..(<->)(/*|)(#e)) ]] do
    local dots=${(j:/:)${:-{1..${match[3]}}}//<->/..}
    set -- ${1:s,${~match[1]},${match[2]}${dots}${match[4]}}
  done
  echo builtin cd $*
}

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

* Re: [PATCH] expand '..n' to equivalent number of '..' segments in fixdir
  2020-05-10  5:58   ` Bart Schaefer
@ 2020-05-10  6:28     ` Bart Schaefer
  2020-05-10 17:17       ` Dian M Fay
  0 siblings, 1 reply; 9+ messages in thread
From: Bart Schaefer @ 2020-05-10  6:28 UTC (permalink / raw)
  To: Roman Perepelitsa; +Cc: Dian M Fay, Zsh hackers list

On Sat, May 9, 2020 at 10:58 PM Bart Schaefer <schaefer@brasslantern.com> wrote:
>
>   echo builtin cd $*

Oops, forgot to remove the "echo" from my test case.  But it's not
really a finished function anyway.

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

* Re: [PATCH] expand '..n' to equivalent number of '..' segments in fixdir
  2020-05-10  6:28     ` Bart Schaefer
@ 2020-05-10 17:17       ` Dian M Fay
  0 siblings, 0 replies; 9+ messages in thread
From: Dian M Fay @ 2020-05-10 17:17 UTC (permalink / raw)
  To: Bart Schaefer, Roman Perepelitsa; +Cc: Dian M Fay, Zsh hackers list

Thanks all! I'll check out some of the alternatives.

On Sat May 9, 2020 at 11:28 PM, Bart Schaefer wrote:
> On Sat, May 9, 2020 at 10:58 PM Bart Schaefer
> <schaefer@brasslantern.com> wrote:
> >
> >   echo builtin cd $*
>
> 
> Oops, forgot to remove the "echo" from my test case. But it's not
> really a finished function anyway.

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

* Re: [PATCH] expand '..n' to equivalent number of '..' segments in fixdir
  2020-05-10  7:09     ` Eric Cook
@ 2020-05-10 14:21       ` Daniel Shahaf
  0 siblings, 0 replies; 9+ messages in thread
From: Daniel Shahaf @ 2020-05-10 14:21 UTC (permalink / raw)
  To: zsh-workers

Eric Cook wrote on Sun, 10 May 2020 03:09 -0400:
> On 5/10/20 3:06 AM, Eric Cook wrote:
> > I personally think a wrapper function is more appropriate.  
> 
> One not distributed with zsh itself that is.

Or a shell widget, like Mikael's rationalise-dot widget that lets one
type «cd ...» to get «cd ../..» and so on.  This also has the benefit
of not requiring completion functions to be taught about the new syntax.

I don't have his latest version handy, but I use a modified version:

_rationalise-dot2 ()
{
        if [[ $LBUFFER == *( ) ]]
        then
                zle .self-insert
		return
        fi
        local -a tokens; tokens=(${(z)LBUFFER}) 
        if [[ $tokens[-1] == (../|*/../) ]]
        then
                LBUFFER+=../ 
        elif [[ $tokens[-1] == '.' ]]
        then
                LBUFFER+=./ 
        else
                zle .self-insert
        fi
}
zle -N _rationalise-dot2
bindkey . _rationalise-dot2
bindkey -M isearch . self-insert

The zle calls inside the function don't pass argv through, but that
doesn't matter in practice.

Tweak to taste.

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

* Re: [PATCH] expand '..n' to equivalent number of '..' segments in fixdir
  2020-05-10  7:06   ` Eric Cook
@ 2020-05-10  7:09     ` Eric Cook
  2020-05-10 14:21       ` Daniel Shahaf
  0 siblings, 1 reply; 9+ messages in thread
From: Eric Cook @ 2020-05-10  7:09 UTC (permalink / raw)
  To: zsh-workers

On 5/10/20 3:06 AM, Eric Cook wrote:
> I personally think a wrapper function is more appropriate.

One not distributed with zsh itself that is.

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

* Re: [PATCH] expand '..n' to equivalent number of '..' segments in fixdir
  2020-05-10  5:28 ` Dian M Fay
@ 2020-05-10  7:06   ` Eric Cook
  2020-05-10  7:09     ` Eric Cook
  0 siblings, 1 reply; 9+ messages in thread
From: Eric Cook @ 2020-05-10  7:06 UTC (permalink / raw)
  To: zsh-workers

On 5/10/20 1:28 AM, Dian M Fay wrote:
> Of course. Actually encountering a directory named like that does seem
> unlikely, but unlikely probably doesn't cut it. It could stat beforehand
> but then the ..n behavior becomes less consistent.
>
> Would making this an option ('BACKTRACK_N' or something) be appropriate?
>
> On Sun May 10, 2020 at 6:43 AM, Roman Perepelitsa wrote:
>> On Sun, May 10, 2020 at 6:36 AM Dian M Fay <dian.m.fay@gmail.com> wrote:
>>>
>>> dian@lamia ~/work/zsh cd ..2
>>> dian@lamia ~ cd ..123
>>> dian@lamia /
>>
>>
>> `..2` is a valid directory name. So it's a breaking change.
>>
>>
>> ~% mkdir ..2
>> ~% cd ..2
>> ~/..2%
>>
>>
>> Roman.

I personally think a wrapper function is more appropriate.

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

* Re: [PATCH] expand '..n' to equivalent number of '..' segments in fixdir
       [not found] <CAN=4vMr_8j03P2oY0+9SLgBnMWMtGtrnUag7fte =18VnvUtRKg@mail.gmail.com>
@ 2020-05-10  5:28 ` Dian M Fay
  2020-05-10  7:06   ` Eric Cook
  0 siblings, 1 reply; 9+ messages in thread
From: Dian M Fay @ 2020-05-10  5:28 UTC (permalink / raw)
  To: Roman Perepelitsa; +Cc: Zsh hackers list

Of course. Actually encountering a directory named like that does seem
unlikely, but unlikely probably doesn't cut it. It could stat beforehand
but then the ..n behavior becomes less consistent.

Would making this an option ('BACKTRACK_N' or something) be appropriate?

On Sun May 10, 2020 at 6:43 AM, Roman Perepelitsa wrote:
> On Sun, May 10, 2020 at 6:36 AM Dian M Fay <dian.m.fay@gmail.com> wrote:
> >
> > dian@lamia ~/work/zsh cd ..2
> > dian@lamia ~ cd ..123
> > dian@lamia /
>
> 
> `..2` is a valid directory name. So it's a breaking change.
>
> 
> ~% mkdir ..2
> ~% cd ..2
> ~/..2%
>
> 
> Roman.

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

end of thread, other threads:[~2020-05-10 17:15 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-10  4:37 [PATCH] expand '..n' to equivalent number of '..' segments in fixdir Dian M Fay
2020-05-10  4:43 ` Roman Perepelitsa
2020-05-10  5:58   ` Bart Schaefer
2020-05-10  6:28     ` Bart Schaefer
2020-05-10 17:17       ` Dian M Fay
     [not found] <CAN=4vMr_8j03P2oY0+9SLgBnMWMtGtrnUag7fte =18VnvUtRKg@mail.gmail.com>
2020-05-10  5:28 ` Dian M Fay
2020-05-10  7:06   ` Eric Cook
2020-05-10  7:09     ` Eric Cook
2020-05-10 14:21       ` Daniel Shahaf

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).