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 11:00:03 +0000
Peter Stephenson <pws@xxxxxxx> wrote:
> 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.

I certainly like this better.  You can now do stuff like

% print ${${:-cat}:c:h}
/bin

although since

% print ${${:-=cat}:h}
/bin

also works it's possibly not much of a gain; however, here you don't need to
force an additional level of expansion on parameters; however however,

% foo=cat
% print ${${:-=$foo}:h}
/bin

also works, too.  One other quirk that makes it less useful (which
surprised me enough before I realised it was indeed the way globbing has
always worked that I've mentioned it specially) is that

% print cat(:c)

doesn't work, because the glob qualifiers turn on globbing, which finds
that the file "cat" doesn't exist and rejects it at that point.  Maybe we
need an alternative syntax for this case.

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 12:05:05 -0000
@@ -219,12 +219,21 @@
 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.
+Note that the transformation takes place even if the file or any
+intervening directories do not exist.
 )
 item(tt(A))(
 As `tt(a)', but also resolve use of symbolic links where possible.
 Note that resolution of `tt(..)' occurs em(before) resolution of symbolic
 links.
 )
+item(tt(c))(
+Resolve a command name into an absolute path by searching the command
+path given by the tt(PATH) variable.  This does not work for commands
+containing directory parts.  Note also that this does not usually work as
+a glob qualifier unless a file of the same name is found in the
+current directory.
+)
 item(tt(e))(
 Remove all but the extension.
 )
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 12:05:05 -0000
@@ -638,6 +638,13 @@
 		    return -1;
 		}
 		break;
+	    case 'c':
+		if (!(sline = equalsubstr(sline, 0, 0))) {
+		    herrflush();
+		    zerr("modifier failed: c");
+		    return -1;
+		}
+		break;
 	    case 'h':
 		if (!remtpath(&sline)) {
 		    herrflush();
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 12:05:05 -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 *
@@ -3201,6 +3222,7 @@
 	    switch (**ptr) {
             case 'a':
             case 'A':
+	    case 'c':
 	    case 'h':
 	    case 'r':
 	    case 'e':
@@ -3345,6 +3367,13 @@
 		    case 'A':
 			chrealpath(&copy);
 			break;
+		    case 'c':
+		    {
+			char *copy2 = equalsubstr(copy, 0, 0);
+			if (copy2)
+			    copy = copy2;
+			break;
+		    }
 		    case 'h':
 			remtpath(&copy);
 			break;
@@ -3410,6 +3439,13 @@
 		case 'A':
 		    chrealpath(str);
 		    break;
+		case 'c':
+		{
+		    char *copy2 = equalsubstr(*str, 0, 0);
+		    if (copy2)
+			*str = copy2;
+		    break;
+		}
 		case 'h':
 		    remtpath(str);
 		    break;

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