about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog10
-rw-r--r--Doc/Zsh/compwid.yo5
-rw-r--r--Doc/Zsh/params.yo43
-rw-r--r--NEWS4
-rw-r--r--Src/Zle/compresult.c8
-rw-r--r--Src/Zle/zle.h4
-rw-r--r--Src/Zle/zle_misc.c65
7 files changed, 120 insertions, 19 deletions
diff --git a/ChangeLog b/ChangeLog
index b2ca7ab76..39bbffbb1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2009-04-24  Peter Stephenson  <pws@csr.com>
+
+	* 26876 (documentation slightly modified): NEWS, Doc/Zsh/compwid.yo,
+	Doc/Zsh/params.yo, Src/Zle/compresult.c, Src/Zle/zle.h,
+	Src/Zle/zle_misc.c: add ZLE_REMOVE_SUFFIX_CHARS and
+	ZLE_SPACE_SUFFIX_CHARS to make actions for suffix removals when
+	not controlled by completion system more configurable.
+
 2009-04-23  Clint Adams  <clint@zsh.org>
 
 	* 26877, 26879: Completion/Debian/Command/_apt: handle apt-get
@@ -11608,5 +11616,5 @@
 
 *****************************************************
 * This is used by the shell to define $ZSH_PATCHLEVEL
-* $Revision: 1.4665 $
+* $Revision: 1.4666 $
 *****************************************************
diff --git a/Doc/Zsh/compwid.yo b/Doc/Zsh/compwid.yo
index 80427330d..b8786dd26 100644
--- a/Doc/Zsh/compwid.yo
+++ b/Doc/Zsh/compwid.yo
@@ -58,6 +58,11 @@ endmenu()
 texinode(Completion Special Parameters)(Completion Builtin Commands)()(Completion Widgets)
 sect(Completion Special Parameters)
 
+The parameters tt(ZLE_REMOVE_SUFFIX_CHARS) and tt(ZLE_SPACE_SUFFIX_CHARS)
+are used by the completion mechanism, but are not special.
+ifzman(See em(Parameters Used By The Shell) in zmanref(zshparam))\
+ifnzman(noderef(Parameters Used By The Shell)).
+
 Inside completion widgets, and any functions called from them, some
 parameters have special meaning; outside these functions they are not
 special to the shell in any way.  These parameters are used to pass
diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo
index 7a8efdd94..e36becf53 100644
--- a/Doc/Zsh/params.yo
+++ b/Doc/Zsh/params.yo
@@ -1330,4 +1330,47 @@ item(tt(ZDOTDIR))(
 The directory to search for shell startup files (.zshrc, etc),
 if not tt($HOME).
 )
+vindex(ZLE_REMOVE_SUFFIX_CHARS)
+vindex(ZLE_SPACE_SUFFIX_CHARS)
+xitem(tt(ZLE_REMOVE_SUFFIX_CHARS))
+item(tt(ZLE_SPACE_SUFFIX_CHARS))(
+These parameters are used by the line editor.  In certain circumstances
+suffixes (typically space or slash) added by the completion system
+will be removed automatically, either because the next editing command
+was not an insertable character, or because the character was marked
+as requiring the suffix to be removed.
+
+These variables can contain the sets of characters that will cause the
+suffix to be removed.  If tt(ZLE_REMOVE_SUFFIX_CHARS) is set, those
+characters will cause the suffix to be removed; if
+tt(ZLE_SPACE_SUFFIX_CHARS) is set, those characters will cause the
+suffix to be removed and replaced by a space.
+
+If tt(ZLE_REMOVE_SUFFIX_CHARS) is not set, the default behaviour is
+equivalent to:
+
+example(ZLE_REMOVE_SUFFIX_CHARS=$' \t\n;&|')
+
+If tt(ZLE_REMOVE_SUFFIX_CHARS) is set but is empty, no characters have this
+behaviour.  tt(ZLE_SPACE_SUFFIX_CHARS) takes precedence, so that the
+following:
+
+example(ZLE_SPACE_SUFFIX_CHARS=$'&|')
+
+causes the characters `tt(&)' and `tt(|)' to remove the suffix but to
+replace it with a space.
+
+To illustrate the difference, suppose that the option tt(AUTO_REMOVE_SLASH)
+is in effect and the directory tt(DIR) has just been completed, with an
+appended tt(/), following which the user types `tt(&)'.  The default result
+is `tt(DIR&)'.  With tt(ZLE_REMOVE_SUFFIX_CHARS) set but without including
+`tt(&)' the result is `tt(DIR/&)'.  With tt(ZLE_SPACE_SUFFIX_CHARS) set to
+include `tt(&)' the result is `tt(DIR &)'.
+
+Note that certain completions may provide their own suffix removal
+or replacement behaviour which overrides the values described here.
+See the completion system documentation in
+ifzman(zmanref(zshcompsys))\
+ifnzman(noderef(Completion System)).
+)
 enditem()
diff --git a/NEWS b/NEWS
index e103840ee..b26617a60 100644
--- a/NEWS
+++ b/NEWS
@@ -20,6 +20,10 @@ shells.
 The variable ZSH_PATCHLEVEL can be used to test for unreleased versions of
 the shell; it is present but less useful in released versions.
 
+The variables ZLE_REMOVE_SUFFIX_CHARS and ZLE_SPACE_SUFFIX_CHARS allow more
+control over the way automatically removed suffixes are treated in
+completion.
+
 Major changes between versions 4.3.6 and 4.3.9
 ----------------------------------------------
 
diff --git a/Src/Zle/compresult.c b/Src/Zle/compresult.c
index e595802dd..43733b0c6 100644
--- a/Src/Zle/compresult.c
+++ b/Src/Zle/compresult.c
@@ -1011,7 +1011,7 @@ do_single(Cmatch m)
 		    stringaszleline(m->suf, 0, &len, NULL, NULL);
 		makesuffixstr(m->remf, m->rems, len);
 		if (len == 1)
-		    addsuffix(SUFTYP_POSSTR, wsuf, 1, 1);
+		    addsuffix(SUFTYP_POSSTR, 0, wsuf, 1, 1);
 		free(wsuf);
 	    }
 	}
@@ -1104,7 +1104,7 @@ do_single(Cmatch m)
 			makesuffixstr(m->remf, m->rems, 1);
 		    else if (isset(AUTOREMOVESLASH)) {
 			makesuffix(1);
-			addsuffix(SUFTYP_POSSTR, ZWS("/"), 1, 1);
+			addsuffix(SUFTYP_POSSTR, 0, ZWS("/"), 1, 1);
 		    }
 		}
 	    }
@@ -1119,7 +1119,7 @@ do_single(Cmatch m)
 	    /* If a suffix was added, and is removable, let *
 	     * `,' and `}' remove it.                       */
 	    if (isset(AUTOPARAMKEYS))
-		addsuffix(SUFTYP_POSSTR, ZWS(",}"), 2, suffixnoinslen);
+		addsuffix(SUFTYP_POSSTR, 0, ZWS(",}"), 2, suffixnoinslen);
 	} else if (!menucmp) {
 	    /*{{*/
 	    /* Otherwise, add a `,' suffix, and let `}' remove it. */
@@ -1129,7 +1129,7 @@ do_single(Cmatch m)
 	    minfo.insc++;
 	    makesuffix(1);
 	    if ((!menucmp || minfo.we) && isset(AUTOPARAMKEYS))
-		addsuffix(SUFTYP_POSSTR, ZWS(",}"), 2, 1);
+		addsuffix(SUFTYP_POSSTR, 0, ZWS(",}"), 2, 1);
 	}
     } else if (!havesuff && (!(m->flags & CMF_FILE) || !sr)) {
 	/* If we didn't add a suffix, add a space, unless we are *
diff --git a/Src/Zle/zle.h b/Src/Zle/zle.h
index 1fd6d87a2..577a4442f 100644
--- a/Src/Zle/zle.h
+++ b/Src/Zle/zle.h
@@ -380,6 +380,10 @@ enum suffixtype {
     SUFTYP_NEGRNG		/* Range of characters not to match */
 };
 
+/* Additional flags to suffixes */
+enum suffixflags {
+    SUFFLAGS_SPACE = 0x0001	/* Add a space when removing suffix */
+};
 
 #ifdef MULTIBYTE_SUPPORT
 /*
diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c
index 961776f43..0beb43d6d 100644
--- a/Src/Zle/zle_misc.c
+++ b/Src/Zle/zle_misc.c
@@ -1232,6 +1232,7 @@ struct suffixset;
 struct suffixset {
     struct suffixset *next;	/* Next in the list */
     int tp;			/* The SUFTYP_* from enum suffixtype */
+    int flags;			/* Some of SUFFLAGS_* */
     ZLE_STRING_T chars;		/* Set of characters to match (or not) */
     int lenstr;			/* Length of chars */
     int lensuf;			/* Length of suffix */
@@ -1255,13 +1256,14 @@ suffixnoinslen;
 
 /**/
 mod_export void
-addsuffix(int tp, ZLE_STRING_T chars, int lenstr, int lensuf)
+addsuffix(int tp, int flags, ZLE_STRING_T chars, int lenstr, int lensuf)
 {
     struct suffixset *newsuf = zalloc(sizeof(struct suffixset));
     newsuf->next = suffixlist;
     suffixlist = newsuf;
 
     newsuf->tp = tp;
+    newsuf->flags = flags;
     if (lenstr) {
 	newsuf->chars = zalloc(lenstr*sizeof(ZLE_CHAR_T));
 	ZS_memcpy(newsuf->chars, chars, lenstr);
@@ -1271,6 +1273,24 @@ addsuffix(int tp, ZLE_STRING_T chars, int lenstr, int lensuf)
     newsuf->lensuf = lensuf;
 }
 
+
+/* Same as addsuffix, but from metafied string */
+
+/**/
+mod_export void
+addsuffixstring(int tp, int flags, char *chars, int lensuf)
+{
+    int slen, alloclen;
+    ZLE_STRING_T suffixstr;
+
+    /* string needs to be writable... I've been regretting this for years.. */
+    chars = ztrdup(chars);
+    suffixstr = stringaszleline(chars, 0, &slen, &alloclen, NULL);
+    addsuffix(tp, flags, suffixstr, slen, lensuf);
+    zfree(suffixstr, alloclen);
+    zsfree(chars);
+}
+
 /* Set up suffix: the last n characters are a suffix that should be *
  * removed in the usual word end conditions.                        */
 
@@ -1278,7 +1298,17 @@ addsuffix(int tp, ZLE_STRING_T chars, int lenstr, int lensuf)
 mod_export void
 makesuffix(int n)
 {
-    addsuffix(SUFTYP_POSSTR, ZWS(" \t\n;&|"), 6, n);
+    char *suffixchars;
+
+    if (!(suffixchars = getsparam("ZLE_REMOVE_SUFFIX_CHARS")))
+	suffixchars = " \t\n;&|";
+
+    addsuffixstring(SUFTYP_POSSTR, 0, suffixchars, n);
+
+    /* Do this second so it takes precedence */
+    if ((suffixchars = getsparam("ZLE_SPACE_SUFFIX_CHARS")) && *suffixchars)
+	addsuffixstring(SUFTYP_POSSTR, SUFFLAGS_SPACE, suffixchars, n);
+
     suffixnoinslen = n;
 }
 
@@ -1301,7 +1331,7 @@ makeparamsuffix(int br, int n)
 	    lenstr += 6;
     }
     if (lenstr)
-	addsuffix(SUFTYP_POSSTR, charstr, lenstr, n);
+	addsuffix(SUFTYP_POSSTR, 0, charstr, lenstr, n);
 }
 
 /* Set up suffix given a string containing the characters on which to   *
@@ -1344,11 +1374,11 @@ makesuffixstr(char *f, char *s, int n)
 		ZLE_CHAR_T str[2];
 
 		if (wptr > lasts)
-		    addsuffix(inv ? SUFTYP_NEGSTR : SUFTYP_POSSTR,
+		    addsuffix(inv ? SUFTYP_NEGSTR : SUFTYP_POSSTR, 0,
 			      lasts, wptr - lasts, n);
 		str[0] = *wptr;
 		str[1] = wptr[2];
-		addsuffix(inv ? SUFTYP_NEGRNG : SUFTYP_POSRNG,
+		addsuffix(inv ? SUFTYP_NEGRNG : SUFTYP_POSRNG, 0,
 			  str, 2, n);
 
 		wptr += 3;
@@ -1360,7 +1390,7 @@ makesuffixstr(char *f, char *s, int n)
 	    }
 	}
 	if (wptr > lasts)
-	    addsuffix(inv ? SUFTYP_NEGSTR : SUFTYP_POSSTR,
+	    addsuffix(inv ? SUFTYP_NEGSTR : SUFTYP_POSSTR, 0,
 		      lasts, wptr - lasts, n);
 	free(ws);
     } else
@@ -1410,7 +1440,7 @@ iremovesuffix(ZLE_INT_T c, int keep)
 	zsfree(suffixfunc);
 	suffixfunc = NULL;
     } else {
-	int sl = 0;
+	int sl = 0, flags = 0;
 	struct suffixset *ss;
 
 	if (c == NO_INSERT_CHAR) {
@@ -1463,8 +1493,10 @@ iremovesuffix(ZLE_INT_T c, int keep)
 		    }
 		    break;
 		}
-		if (found)
+		if (found) {
+		    flags = ss->flags;
 		    break;
+		}
 	    }
 
 	    if (!found)
@@ -1472,12 +1504,17 @@ iremovesuffix(ZLE_INT_T c, int keep)
 	}
 	if (sl) {
 	    /* must be shifting wide character lengths */
-	    if (zlemetaline != NULL) {
-		unmetafy_line();
-		backdel(sl, CUT_RAW);
-		metafy_line();
-	    } else
-		backdel(sl, CUT_RAW);
+	    backdel(sl, CUT_RAW);
+	    if (flags & SUFFLAGS_SPACE)
+	    {
+		/* Add a space and advance over it */
+		spaceinline(1);
+		if (zlemetaline) {
+		    zlemetaline[zlemetacs++] = ' ';
+		} else {
+		    zleline[zlecs++] = ZWC(' ');
+		}
+	    }
 	    if (!keep)
 		invalidatelist();
 	}