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

PATCH: more $'...' completion



This fixes completion of filenames in cases like:

  sh -c $'ls "quoted filename" "and another"

which was still thoroughly broken after my previous patch.  This is
still nowhere near the end of the $'-completion saga, but once again I
think it's better than it was before.

Index: Src/lex.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/lex.c,v
retrieving revision 1.35
diff -u -r1.35 lex.c
--- Src/lex.c	13 Dec 2006 18:49:07 -0000	1.35
+++ Src/lex.c	8 Jan 2007 20:48:32 -0000
@@ -96,18 +96,18 @@
 mod_export int wb, we;
 
 /* 1 if aliases should not be expanded */
- 
+
 /**/
 mod_export int noaliases;
 
 /* we are parsing a line sent to use by the editor */
- 
+
 /**/
 mod_export int zleparse;
- 
+
 /**/
 mod_export int wordbeg;
- 
+
 /**/
 mod_export int parbegin;
 
@@ -115,7 +115,7 @@
 mod_export int parend;
 
 /* don't recognize comments */
- 
+
 /**/
 mod_export int nocomments;
 
@@ -1181,10 +1181,20 @@
 		STOPHIST
 		while ((c = hgetc()) != '\'' && !lexstop) {
 		    if (strquote && c == '\\') {
-			add(c);
 			c = hgetc();
 			if (lexstop)
 			    break;
+			/*
+			 * Mostly we don't need to do anything special
+			 * with escape backslashes or closing quotes
+			 * inside $'...'; however in completion we
+			 * need to be able to strip multiple backslashes
+			 * neatly.
+			 */
+			if (c == '\\' || c == '\'')
+			    add(Bnull);
+			else
+			    add('\\');
 		    } else if (!sub && isset(CSHJUNKIEQUOTES) && c == '\n') {
 			if (bptr[-1] == '\\')
 			    bptr--, len--;
Index: Src/utils.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/utils.c,v
retrieving revision 1.148
diff -u -r1.148 utils.c
--- Src/utils.c	19 Dec 2006 13:01:43 -0000	1.148
+++ Src/utils.c	8 Jan 2007 20:48:33 -0000
@@ -4577,10 +4577,27 @@
 /*
  * Decode a key string, turning it into the literal characters.
  * The value returned is a newly allocated string from the heap.
- * The length is (usually) returned in *len.
+ *
+ * The length is returned in *len.  This is usually the length of
+ * the final unmetafied string.  The exception is the case of
+ * a complete GETKEY_DOLLAR_QUOTE conversion where *len is the
+ * length of the input string which has been used (up to and including
+ * the terminating single quote); as the final string is metafied and
+ * NULL-terminated its length is not required.  If both GETKEY_DOLLAR_QUOTE
+ * and GETKEY_UPDATE_OFFSET are present in "how", the string is not
+ * expected to be terminated (this is used in completion to parse
+ * a partial $'...'-quoted string) and the length passed back is
+ * that of the converted string.  Note in both cases that this is a length
+ * in bytes (i.e. the same as given by a raw pointer difference), not
+ * characters, which may occupy multiple bytes.
+ *
  * how is a set of bits from the GETKEY_ values defined in zsh.h;
  * not all combinations of bits are useful.  Callers will typically
  * use one of the GETKEYS_ values which define sets of bits.
+ * Note, for example that:
+ * - GETKEY_SINGLE_CHAR must not be combined with GETKEY_DOLLAR_QUOTE.
+ * - GETKEY_UPDATE_OFFSET is only allowed if GETKEY_DOLLAR_QUOTE is
+ *   also present.
  *
  * The return value is unmetafied unless GETKEY_DOLLAR_QUOTE is
  * in use.
@@ -4946,9 +4963,9 @@
     if (how & GETKEY_DOLLAR_QUOTE)
 	*tdest = '\0';
     if (how & GETKEY_SINGLE_CHAR)
-      *misc = 0;
+	*misc = 0;
     else
-      *len = t - buf;
+	*len = ((how & GETKEY_DOLLAR_QUOTE) ? tdest : t) - buf;
     return buf;
 }
 
Index: Src/zsh.h
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/zsh.h,v
retrieving revision 1.105
diff -u -r1.105 zsh.h
--- Src/zsh.h	4 Jan 2007 17:24:03 -0000	1.105
+++ Src/zsh.h	8 Jan 2007 20:48:35 -0000
@@ -1914,8 +1914,12 @@
 #define STRINGIFY(x)		STRINGIFY_LITERAL(x)
 #define ERRMSG(x)		(__FILE__ ":" STRINGIFY(__LINE__) ": " x)
 # define DPUTS(X,Y) if (!(X)) {;} else dputs(ERRMSG(Y))
+# define DPUTS1(X,Y,Z1) if (!(X)) {;} else dputs(ERRMSG(Y), Z1)
+# define DPUTS2(X,Y,Z1,Z2) if (!(X)) {;} else dputs(ERRMSG(Y), Z1, Z2)
 #else
 # define DPUTS(X,Y)
+# define DPUTS1(X,Y,Z1)
+# define DPUTS2(X,Y,Z1,Z2)
 #endif
 
 /**************************/
Index: Src/Zle/compcore.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/compcore.c,v
retrieving revision 1.88
diff -u -r1.88 compcore.c
--- Src/Zle/compcore.c	8 Dec 2006 18:52:05 -0000	1.88
+++ Src/Zle/compcore.c	8 Jan 2007 20:48:35 -0000
@@ -1432,10 +1432,8 @@
      *     set, which isn't necessarily correct if the quotes were typed by
      *     the user).
      * osq: c.f. odq, taking account of Snull's and embeded "'"'s.
-     * issq: flag that current quoting is single quotes; I assume that
-     *       civilization would end if we used a consistent way of
-     *       flagging the different types of quotes, or something.
-     * lsq: when quoting is single quotes (issq), counts the offset
+     * qttype: type of quotes using standard QT_* definitions.
+     * lsq: when quoting is single quotes (QT_SINGLE), counts the offset
      *      adjustment needed in the word being examined in the lexer loop.
      * sqq: the value of lsq for the current completion word.
      * qa:  not, unfortunately, a question and answer session with the
@@ -1443,7 +1441,7 @@
      *      when stripping single quotes: 1 for RCQUOTES, 3 otherwise
      *      (because we leave a "'" in the final string).
      */
-    int dq = 0, odq, sq = 0, osq, issq = 0, sqq = 0, lsq = 0, qa = 0;
+    int dq = 0, odq, sq = 0, osq, qttype, sqq = 0, lsq = 0, qa = 0;
     /* dolq: like sq and dq but for dollars quoting. */
     int dolq = 0;
     /* remember some global variable values (except lp is local) */
@@ -1479,26 +1477,25 @@
     addedx = 1;
     noerrs = 1;
     lexsave();
-    tmp = (char *) zhalloc(tl = 3 + strlen(s));
+    /*
+     * tl is the length of the temporary string including
+     * the space at the start and the x at the cursor position,
+     * but not the NULL byte.
+     */
+    tl = strlen(s) + 2;
+    tmp = (char *) zhalloc(tl + 1);
     tmp[0] = ' ';
     memcpy(tmp + 1, s, noffs);
     tmp[(scs = zlemetacs = 1 + noffs)] = 'x';
     strcpy(tmp + 2 + noffs, s + noffs);
 
-    switch (*compqstack) {
-    case QT_NONE:
-#ifdef DEBUG
-	dputs("BUG: head of compqstack is NULL");
-#endif
-	break;
-
+    switch ((qttype = *compqstack)) {
     case QT_BACKSLASH:
         remq = 1;
 	tmp = rembslash(tmp);
         break;
 
     case QT_SINGLE:
-        issq = 1;
         if (isset(RCQUOTES))
             qa = 1;
         else
@@ -1531,22 +1528,32 @@
 	break;
 
     case QT_DOLLARS:
-	sl = strlen(tmp);
 	j = zlemetacs;
-	tmp = getkeystring(tmp, &tl,
+	tmp = getkeystring(tmp, &sl,
 			   GETKEY_DOLLAR_QUOTE|GETKEY_UPDATE_OFFSET,
 			   &zlemetacs);
-	/* The number of characters we removed because of $' quoting */
-	dolq = sl - tl;
+	/* The number of bytes we removed because of $' quoting */
+	dolq = tl - sl;
 	/* Offset into the word is modified, too... */
 	css += zlemetacs - j;
 	break;
+
+    case QT_NONE:
+    default: /* to silence compiler warnings */
+#ifdef DEBUG
+	dputs("BUG: head of compqstack is NULL");
+#endif
+	break;
+
     }
     odq = dq;
     osq = sq;
     inpush(dupstrspace(tmp), 0, NULL);
     zlemetaline = tmp;
-    zlemetall = tl - 1;
+    /*
+     * Length of temporary string, calculated above.
+     */
+    zlemetall = tl;
     strinbeg(0);
     noaliases = 1;
     do {
@@ -1582,7 +1589,7 @@
                         dq--;
                 }
             }
-            if (issq) {
+            if (qttype == QT_SINGLE) {
                 for (p = tokstr, lsq = 0; *p; p++) {
                     if (sq && *p == Snull)
                         sq -= qa;
@@ -1606,6 +1613,8 @@
 	    swe = we - 1 - dq - sq - dolq;
             sqq = lsq;
 	    soffs = zlemetacs - swb - css;
+	    DPUTS2(p[soffs] != 'x', "expecting 'x' at offset %d of \"%s\"",
+		   soffs, p);
 	    chuck(p + soffs);
 	    ns = dupstring(p);
 	}
@@ -1736,7 +1745,7 @@
      */
     sav = s[(i = swb - 1 - sqq + dq)];
     s[i] = '\0';
-    qp = (issq ? dupstring(s) : rembslash(s));
+    qp = (qttype == QT_SINGLE) ? dupstring(s) : rembslash(s);
     s[i] = sav;
     if (swe < swb)
 	swe = swb;
@@ -1747,11 +1756,11 @@
 	if ((int)strlen(ns) > swe - swb + 1)
 	    ns[swe - swb + 1] = '\0';
     }
-    qs = (issq ? dupstring(s + swe) : rembslash(s + swe));
+    qs = (qttype == QT_SINGLE) ? dupstring(s + swe) : rembslash(s + swe);
     sl = strlen(ns);
     if (soffs > sl)
 	soffs = sl;
-    if (issq) {
+    if (qttype == QT_SINGLE) {
         remsquote(qp);
         remsquote(qs);
     }

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



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