zsh-workers
 help / color / mirror / code / Atom feed
* annoying correction of directory name to non-directory name for cd
@ 2015-09-16 23:21 Vincent Lefevre
  2015-09-17  1:07 ` Bart Schaefer
  0 siblings, 1 reply; 7+ messages in thread
From: Vincent Lefevre @ 2015-09-16 23:21 UTC (permalink / raw)
  To: zsh-workers

zsh often proposes to correct a directory name to a non-directory
name. This is annoying. For instance:

% setopt CORRECT_ALL
% touch shar
% cd share/zsh
zsh: correct 'share/zsh' to 'shar/zsh' [nyae]?

where "share/zsh" is not in the current directory (but still valid
via $cdpath).

Or perhaps the correction system should take $cdpath into account.

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)


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

* Re: annoying correction of directory name to non-directory name for cd
  2015-09-16 23:21 annoying correction of directory name to non-directory name for cd Vincent Lefevre
@ 2015-09-17  1:07 ` Bart Schaefer
  2015-10-04 12:17   ` Vincent Lefevre
  0 siblings, 1 reply; 7+ messages in thread
From: Bart Schaefer @ 2015-09-17  1:07 UTC (permalink / raw)
  To: zsh-workers

On Sep 17,  1:21am, Vincent Lefevre wrote:
}
} zsh often proposes to correct a directory name to a non-directory
} name. This is annoying.
} 
} Or perhaps the correction system should take $cdpath into account.

CORRECT_ALL isn't intended to be that smart.  It doesn't know or care
what the command word is, and doesn't have access to all of the syntax
analysis done by the completion system to understand what each word
position means.  It doesn't know your word is a directory, EXCEPT that,
when AUTO_CD and the word is in command position, then it compares it
against cdpath if nothing else looks better.

alias cd="nocorrect cd" is always an option.

We've bandied for years about the possiblity of somehow translating the
completion system's syntax knowledge into performing correction, but
that all boils down to walking over every word in the command to call
the _correct completer on it, which isn't something that belongs in
the core shell where CORRECT_ALL sits.


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

* Re: annoying correction of directory name to non-directory name for cd
  2015-09-17  1:07 ` Bart Schaefer
@ 2015-10-04 12:17   ` Vincent Lefevre
  2015-10-04 17:06     ` Bart Schaefer
  0 siblings, 1 reply; 7+ messages in thread
From: Vincent Lefevre @ 2015-10-04 12:17 UTC (permalink / raw)
  To: zsh-workers

On 2015-09-16 18:07:14 -0700, Bart Schaefer wrote:
> On Sep 17,  1:21am, Vincent Lefevre wrote:
> } zsh often proposes to correct a directory name to a non-directory
> } name. This is annoying.
> } 
> } Or perhaps the correction system should take $cdpath into account.
> 
> CORRECT_ALL isn't intended to be that smart.  It doesn't know or care
> what the command word is, and doesn't have access to all of the syntax
> analysis done by the completion system to understand what each word
> position means.

For the simplest cases, it doesn't need to know the meaning: when the
word is followed by a slash, the filename must be a directory name.
So, before proposing anything, the correction system should do such
an additional check. At least it would avoid some false positives.

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)


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

* Re: annoying correction of directory name to non-directory name for cd
  2015-10-04 12:17   ` Vincent Lefevre
@ 2015-10-04 17:06     ` Bart Schaefer
  2015-10-04 18:29       ` Bart Schaefer
  0 siblings, 1 reply; 7+ messages in thread
From: Bart Schaefer @ 2015-10-04 17:06 UTC (permalink / raw)
  To: zsh-workers

On Oct 4,  2:17pm, Vincent Lefevre wrote:
} Subject: Re: annoying correction of directory name to non-directory name f
}
} On 2015-09-16 18:07:14 -0700, Bart Schaefer wrote:
} > On Sep 17,  1:21am, Vincent Lefevre wrote:
} > } zsh often proposes to correct a directory name to a non-directory
} > } name. This is annoying.
} > 
} > CORRECT_ALL isn't intended to be that smart.
} 
} For the simplest cases, it doesn't need to know the meaning: when the
} word is followed by a slash, the filename must be a directory name.

Hmm.  Does this do what you want?

I've tried to minimize the stat()-ing to the names that are actually
candidate corrections.

diff --git a/Src/utils.c b/Src/utils.c
index ab3b0c2..530b51e 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -2812,7 +2812,7 @@ spckword(char **s, int hist, int cmd, int ask)
 		     * as used in spscan(), so that an autocd is chosen *
 		     * only when it is better than anything so far, and *
 		     * so we prefer directories earlier in the cdpath.  */
-		    if ((thisdist = mindist(*pp, *s, bestcd)) < d) {
+		    if ((thisdist = mindist(*pp, *s, bestcd, 1)) < d) {
 			best = dupstring(bestcd);
 			d = thisdist;
 		    }
@@ -4057,7 +4057,8 @@ spname(char *oldname)
 	    thresh = 3;
 	else if (thresh > 100)
 	    thresh = 100;
-	if ((thisdist = mindist(newname, spnameguess, spnamebest)) >= thresh) {
+	thisdist = mindist(newname, spnameguess, spnamebest, *old == '/');
+	if (thisdist >= thresh) {
 	    /* The next test is always true, except for the first path    *
 	     * component.  We could initialize bestdist to some large     *
 	     * constant instead, and then compare to that constant here,  *
@@ -4082,12 +4083,13 @@ spname(char *oldname)
 
 /**/
 static int
-mindist(char *dir, char *mindistguess, char *mindistbest)
+mindist(char *dir, char *mindistguess, char *mindistbest, int isdir)
 {
     int mindistd, nd;
     DIR *dd;
     char *fn;
     char *buf;
+    struct stat st;
 
     if (dir[0] == '\0')
 	dir = ".";
@@ -4096,7 +4098,7 @@ mindist(char *dir, char *mindistguess, char *mindistbest)
     buf = zalloc(strlen(dir) + strlen(mindistguess) + 2);
     sprintf(buf, "%s/%s", dir, mindistguess);
 
-    if (access(unmeta(buf), F_OK) == 0) {
+    if (stat(unmeta(buf), &st) == 0 && (!isdir || S_ISDIR(st.st_mode))) {
 	strcpy(mindistbest, mindistguess);
 	free(buf);
 	return 0;
@@ -4110,7 +4112,8 @@ mindist(char *dir, char *mindistguess, char *mindistbest)
 	    continue;
 	nd = spdist(fn, mindistguess,
 		    (int)strlen(mindistguess) / 4 + 1);
-	if (nd <= mindistd) {
+	if (nd <= mindistd &&
+	    (!isdir || (stat(unmeta(fn), &st) == 0 && S_ISDIR(st.st_mode)))) {
 	    strcpy(mindistbest, fn);
 	    mindistd = nd;
 	    if (mindistd == 0)


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

* Re: annoying correction of directory name to non-directory name for cd
  2015-10-04 17:06     ` Bart Schaefer
@ 2015-10-04 18:29       ` Bart Schaefer
  2015-10-04 20:14         ` Bart Schaefer
  0 siblings, 1 reply; 7+ messages in thread
From: Bart Schaefer @ 2015-10-04 18:29 UTC (permalink / raw)
  To: zsh-workers

On Oct 4, 10:06am, Bart Schaefer wrote:
}
} -	if (nd <= mindistd) {
} +	if (nd <= mindistd &&
} +	    (!isdir || (stat(unmeta(fn), &st) == 0 && S_ISDIR(st.st_mode)))) {

That doesn't quite do it -- the stat() needs to be on the catenation
of dir and fn.  There's a buffer for this but it might need resizing.
Updated patch later ...


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

* Re: annoying correction of directory name to non-directory name for cd
  2015-10-04 18:29       ` Bart Schaefer
@ 2015-10-04 20:14         ` Bart Schaefer
  2015-10-05 10:10           ` Vincent Lefevre
  0 siblings, 1 reply; 7+ messages in thread
From: Bart Schaefer @ 2015-10-04 20:14 UTC (permalink / raw)
  To: zsh-workers

On Oct 4, 11:29am, Bart Schaefer wrote:
} Subject: Re: annoying correction of directory name to non-directory name f
}
} Updated patch later ...

Mostly re-indentation but it seemed prudent to throw in a check for
successful allocation while here.


diff --git a/Src/utils.c b/Src/utils.c
index ab3b0c2..61cbe84 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -2812,7 +2812,7 @@ spckword(char **s, int hist, int cmd, int ask)
 		     * as used in spscan(), so that an autocd is chosen *
 		     * only when it is better than anything so far, and *
 		     * so we prefer directories earlier in the cdpath.  */
-		    if ((thisdist = mindist(*pp, *s, bestcd)) < d) {
+		    if ((thisdist = mindist(*pp, *s, bestcd, 1)) < d) {
 			best = dupstring(bestcd);
 			d = thisdist;
 		    }
@@ -4057,7 +4057,8 @@ spname(char *oldname)
 	    thresh = 3;
 	else if (thresh > 100)
 	    thresh = 100;
-	if ((thisdist = mindist(newname, spnameguess, spnamebest)) >= thresh) {
+	thisdist = mindist(newname, spnameguess, spnamebest, *old == '/');
+	if (thisdist >= thresh) {
 	    /* The next test is always true, except for the first path    *
 	     * component.  We could initialize bestdist to some large     *
 	     * constant instead, and then compare to that constant here,  *
@@ -4082,42 +4083,52 @@ spname(char *oldname)
 
 /**/
 static int
-mindist(char *dir, char *mindistguess, char *mindistbest)
+mindist(char *dir, char *mindistguess, char *mindistbest, int wantdir)
 {
     int mindistd, nd;
     DIR *dd;
     char *fn;
     char *buf;
+    struct stat st;
+    size_t dirlen;
 
     if (dir[0] == '\0')
 	dir = ".";
     mindistd = 100;
 
-    buf = zalloc(strlen(dir) + strlen(mindistguess) + 2);
+    if (!(buf = zalloc((dirlen = strlen(dir)) + strlen(mindistguess) + 2)))
+	return 0;
     sprintf(buf, "%s/%s", dir, mindistguess);
 
-    if (access(unmeta(buf), F_OK) == 0) {
+    if (stat(unmeta(buf), &st) == 0 && (!wantdir || S_ISDIR(st.st_mode))) {
 	strcpy(mindistbest, mindistguess);
 	free(buf);
 	return 0;
     }
-    free(buf);
 
-    if (!(dd = opendir(unmeta(dir))))
-	return mindistd;
-    while ((fn = zreaddir(dd, 0))) {
-	if (spnamepat && pattry(spnamepat, fn))
-	    continue;
-	nd = spdist(fn, mindistguess,
-		    (int)strlen(mindistguess) / 4 + 1);
-	if (nd <= mindistd) {
-	    strcpy(mindistbest, fn);
-	    mindistd = nd;
-	    if (mindistd == 0)
-		break;
+    if ((dd = opendir(unmeta(dir)))) {
+	while ((fn = zreaddir(dd, 0))) {
+	    if (spnamepat && pattry(spnamepat, fn))
+		continue;
+	    nd = spdist(fn, mindistguess,
+			(int)strlen(mindistguess) / 4 + 1);
+	    if (nd <= mindistd) {
+		if (wantdir) {
+		    if (!(buf = zrealloc(buf, dirlen + strlen(fn) + 2)))
+			continue;
+		    sprintf(buf, "%s/%s", dir, fn);
+		    if (stat(unmeta(buf), &st) != 0 || !S_ISDIR(st.st_mode))
+			continue;
+		}
+		strcpy(mindistbest, fn);
+		mindistd = nd;
+		if (mindistd == 0)
+		    break;
+	    }
 	}
+	closedir(dd);
     }
-    closedir(dd);
+    free(buf);
     return mindistd;
 }
 

-- 
Barton E. Schaefer


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

* Re: annoying correction of directory name to non-directory name for cd
  2015-10-04 20:14         ` Bart Schaefer
@ 2015-10-05 10:10           ` Vincent Lefevre
  0 siblings, 0 replies; 7+ messages in thread
From: Vincent Lefevre @ 2015-10-05 10:10 UTC (permalink / raw)
  To: zsh-workers

On 2015-10-04 13:14:34 -0700, Bart Schaefer wrote:
> On Oct 4, 11:29am, Bart Schaefer wrote:
> } Subject: Re: annoying correction of directory name to non-directory name f
> }
> } Updated patch later ...
> 
> Mostly re-indentation but it seemed prudent to throw in a check for
> successful allocation while here.
[...]

Thanks. It works as expected here.

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)


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

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

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-09-16 23:21 annoying correction of directory name to non-directory name for cd Vincent Lefevre
2015-09-17  1:07 ` Bart Schaefer
2015-10-04 12:17   ` Vincent Lefevre
2015-10-04 17:06     ` Bart Schaefer
2015-10-04 18:29       ` Bart Schaefer
2015-10-04 20:14         ` Bart Schaefer
2015-10-05 10:10           ` Vincent Lefevre

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