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

Re: Bug#519535: history expansion: modifier completion missing



On Tue, 17 Mar 2009 09:57:17 +0000
Peter Stephenson <pws@xxxxxxx> wrote:
> On Mon, 16 Mar 2009 19:44:34 -0700
> Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> wrote:
> > torch% echo foo
> > torch% !!:a
> > /usr/local/src/zsh/zsh-build/echo foo
> > zsh: no such file or directory: /usr/local/src/zsh/zsh-build/echo
> > 
> > That's almost certainly not the intended behavior ... is it?
> 
> It depends what you mean by "intended": Michael did say the operation
> didn't take account of whether the file existed (but I didn't document
> this), and there was never any special behaviour for command words.  You
> could make it work like "=", I suppose, but that's an extension.

I'm not sure if the change below is what you had in mind.  Maybe you were
pointing out that applying :a to the entire expression "echo foo", which is
what happened, didn't make sense, but that's the way modifiers have always
worked:

% /bin/echo hello
% !!:h<TAB>   ->   /bin
% !!:t<TAB>   ->   echo hello

so yes, it would be intended that a and A work the same.

Maybe it's not clear (or is actually confusing) in the change below that
the expansion depends not where the original has come from, but where the
expansion is being used on the command line.

I'm not even sure this change is useful.  Suppose you had:

% script arg

and that didn't work because script was in the current directory rather
than the path, so you ran

% !:0:a !:*

to ensure you ran the script from the current directory.  With the change
below, that wouldn't work any more.

I've a mind to leave a and A as they were, note that they don't care if the
file doesn't exist (which is also entirely consistent with h, t, etc.), and
add c to do the following.  You could then stack :c:A if you really wanted.

Index: Doc/Zsh/expn.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/expn.yo,v
retrieving revision 1.103
diff -u -r1.103 expn.yo
--- Doc/Zsh/expn.yo	15 Mar 2009 01:17:06 -0000	1.103
+++ Doc/Zsh/expn.yo	17 Mar 2009 10:44:41 -0000
@@ -219,6 +219,18 @@
 item(tt(a))(
 Turn a file name into an absolute path:  prepends the current directory,
 if necessary, and resolves any use of `tt(..)' and `tt(.)' in the path.
+If used in history substitution at the start of a command line and the name
+does not contain a tt(/), it is resolved as an external command by
+searching the command path given by the tt(PATH) parameter.  For example,
+assuming the current directory is tt(/home/pwd) and the external command
+tt(echo) exists in tt(/bin), then the following:
+example(echo file
+!:0:a !:1:a
+)
+becomes `tt(/bin/echo /home/pwd/file)', while
+example(./script file
+!:0:a !:1:a)
+becomes `tt(/home/pwd/script /home/pwd/file)'.
 )
 item(tt(A))(
 As `tt(a)', but also resolve use of symbolic links where possible.
Index: Src/hist.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/hist.c,v
retrieving revision 1.90
diff -u -r1.90 hist.c
--- Src/hist.c	15 Mar 2009 01:17:06 -0000	1.90
+++ Src/hist.c	17 Mar 2009 10:44:42 -0000
@@ -624,7 +624,9 @@
 		histdone = HISTFLAG_DONE | HISTFLAG_NOEXEC;
 		break;
 	    case 'a':
-		if (!chabspath(&sline)) {
+		if ((incmdpos && !strchr(sline, '/') &&
+		     !(sline = equalsubstr(sline, 0, 0))) ||
+		    !chabspath(&sline)) {
 		    herrflush();
 		    zerr("modifier failed: a");
 		    return -1;
@@ -632,7 +634,9 @@
 		break;
 
 	    case 'A':
-		if (!chrealpath(&sline)) {
+		if ((incmdpos && !strchr(sline, '/') &&
+		     !(sline = equalsubstr(sline, 0, 0))) ||
+		    !chrealpath(&sline)) {
 		    herrflush();
 		    zerr("modifier failed: A");
 		    return -1;
Index: Src/subst.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/subst.c,v
retrieving revision 1.96
diff -u -r1.96 subst.c
--- Src/subst.c	15 Mar 2009 01:17:06 -0000	1.96
+++ Src/subst.c	17 Mar 2009 10:44:42 -0000
@@ -539,12 +539,43 @@
     }
 }
 
+#define isend(c) ( !(c) || (c)=='/' || (c)==Inpar || (assign && (c)==':') )
+#define isend2(c) ( !(c) || (c)==Inpar || (assign && (c)==':') )
+
+/*
+ * do =foo substitution, or equivalent.
+ * on entry, str should point to the "foo".
+ * if assign, this is in an assignment
+ * if nomatch, report hard error on failure.
+ * if successful, returns the expansion, else NULL.
+ */
+
+/**/
+char *
+equalsubstr(char *str, int assign, int nomatch)
+{
+    char *pp, *cnam, *cmdstr, *ret;
+
+    for (pp = str; !isend2(*pp); pp++)
+	;
+    cmdstr = dupstrpfx(str, pp-str);
+    untokenize(cmdstr);
+    remnulargs(cmdstr);
+    if (!(cnam = findcmd(cmdstr, 1))) {
+	if (nomatch)
+	    zerr("%s not found", cmdstr);
+	return NULL;
+    }
+    ret = dupstring(cnam);
+    if (*pp)
+	ret = dyncat(ret, pp);
+    return ret;
+}
+
 /**/
 mod_export int
 filesubstr(char **namptr, int assign)
 {
-#define isend(c) ( !(c) || (c)=='/' || (c)==Inpar || (assign && (c)==':') )
-#define isend2(c) ( !(c) || (c)==Inpar || (assign && (c)==':') )
     char *str = *namptr;
 
     if (*str == Tilde && str[1] != '=' && str[1] != Equals) {
@@ -606,27 +637,17 @@
 	    return 1;
 	}
     } else if (*str == Equals && isset(EQUALS) && str[1]) {   /* =foo */
-	char *pp, *cnam, *cmdstr, *str1 = str+1;
-
-	for (pp = str1; !isend2(*pp); pp++)
-	    ;
-	cmdstr = dupstrpfx(str1, pp-str1);
-	untokenize(cmdstr);
-	remnulargs(cmdstr);
-	if (!(cnam = findcmd(cmdstr, 1))) {
-	    if (isset(NOMATCH))
-		zerr("%s not found", cmdstr);
-	    return 0;
+	char *expn = equalsubstr(str+1, assign, isset(NOMATCH));
+	if (expn) {
+	    *namptr = expn;
+	    return 1;
 	}
-	*namptr = dupstring(cnam);
-	if (*pp)
-	    *namptr = dyncat(*namptr, pp);
-	return 1;
     }
     return 0;
+}
+
 #undef isend
 #undef isend2
-}
 
 /**/
 static char *


-- 
Peter Stephenson <pws@xxxxxxx>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070



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