about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog12
-rw-r--r--Doc/Zsh/zle.yo28
-rw-r--r--Src/Zle/zle_main.c2
-rw-r--r--Src/Zle/zle_refresh.c81
-rw-r--r--Src/Zle/zle_thingy.c64
-rw-r--r--Src/init.c13
6 files changed, 196 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index a4e2c2931..22dcf483d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2012-01-05  Peter Stephenson  <p.w.stephenson@ntlworld.com>
+
+	* 30084: Doc/Zsh/zle.yo, Src/init.c, Src/Zle/zle_main.c,
+	Src/Zle/zle_refresh.c, Src/Zle/zle_thingy.c: `zle -T tc func'
+	defines function to be used insted of termcap output for
+	testing.
+
+	* 30081: Completion/Base/Core/_main_complete: remove necessity
+	to have IGNORE_CLOSE_BRACES unset when loaded.
+
 2012-01-04  Frank Terbeck  <ft@bewatermyfriend.org>
 
 	* 30079: Src/params.c: Restore `LC_ALL' when setting `LANG'.
@@ -15819,5 +15829,5 @@
 
 *****************************************************
 * This is used by the shell to define $ZSH_PATCHLEVEL
-* $Revision: 1.5554 $
+* $Revision: 1.5555 $
 *****************************************************
diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo
index 752247461..d3624b1ce 100644
--- a/Doc/Zsh/zle.yo
+++ b/Doc/Zsh/zle.yo
@@ -370,6 +370,7 @@ xitem(tt(zle) tt(-U) var(string))
 xitem(tt(zle) tt(-K) var(keymap))
 xitem(tt(zle) tt(-F) [ tt(-L) ] [ var(fd) [ var(handler) ] ])
 xitem(tt(zle) tt(-I))
+xitem(tt(zle) tt(-T) [ tt(tc) var(function) | tt(-r) tt(tc) | tt(-L) ] )
 item(tt(zle) var(widget) tt([ -n) var(num) tt(]) tt([ -Nw ] [ -K) var(keymap) tt(]) var(args) ...)(
 The tt(zle) builtin performs a number of different actions concerning
 ZLE.
@@ -572,6 +573,33 @@ this may have been by a previous call to `tt(zle -I)' or by a system
 notification.  To test if a zle widget may be called at this point, execute
 tt(zle) with no arguments and examine the return status.
 )
+item(tt(-T))(
+This is used to add, list or remove internal transformations on the
+processing performed by the line editor.  It is typically used only for
+debugging or testing and is therefore of little interest to the general
+user.
+
+`tt(zle -T) var(transformation) var(func)' specifies that the
+given var(transformation) (see below) is effected by shell function
+var(func).
+
+`tt(zle -Tr) var(transformation)' removes the given var(transformation)
+if it was present (it is not an error if none was).
+
+`tt(zle -TL)' can be used to list all transformations currently in
+operation.
+
+Currently the only transformation is tt(tc).  This is used instead
+of outputting termcap codes to the terminal.  When the transformation is
+in operation the shell function is passed the termcap code that would be
+output as its first argument; if the operation required a numeric
+argument, that is passed as a second argument.  The function should set
+the shell variable tt(REPLY) to the transformed termcap code.  Typically
+this is used to produce some simply formatted version of the code and
+optional argument for debugging or testing.  Note that this
+transformation is not applied to other non-printing characters such as
+carriage returns and newlines.
+)
 item(var(widget) tt([ -n) var(num) tt(]) tt([ -Nw ] [ -K) var(keymap) tt(]) var(args) ...)(
 Invoke the specified widget.  This can only be done when ZLE is
 active; normally this will be within a user-defined widget.
diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c
index e570d1d8c..e1a575bdb 100644
--- a/Src/Zle/zle_main.c
+++ b/Src/Zle/zle_main.c
@@ -1927,7 +1927,7 @@ zle_main_entry(int cmd, va_list ap)
 static struct builtin bintab[] = {
     BUILTIN("bindkey", 0, bin_bindkey, 0, -1, 0, "evaM:ldDANmrsLRp", NULL),
     BUILTIN("vared",   0, bin_vared,   1,  1, 0, "aAcehM:m:p:r:t:", NULL),
-    BUILTIN("zle",     0, bin_zle,     0, -1, 0, "aAcCDFgGIKlLmMNRU", NULL),
+    BUILTIN("zle",     0, bin_zle,     0, -1, 0, "aAcCDFgGIKlLmMNrRTU", NULL),
 };
 
 /* The order of the entries in this table has to match the *HOOK
diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c
index 260df8bf6..17b78ce59 100644
--- a/Src/Zle/zle_refresh.c
+++ b/Src/Zle/zle_refresh.c
@@ -233,6 +233,12 @@ int n_region_highlights;
 /**/
 int region_active;
 
+/*
+ * Name of function to use to output termcap values, if defined.
+ */
+/**/
+char *tcout_func_name;
+
 #ifdef HAVE_SELECT
 /* cost of last update */
 /**/
@@ -2271,11 +2277,78 @@ tc_downcurs(int ct)
     return ret;
 }
 
+/*
+ * Output a termcap value using a function defined by "zle -T tc".
+ * Loosely inspired by subst_string_by_func().
+ *
+ * cap is the internal index for the capability; it will be looked up
+ * in the table and the string passed to the function.
+ *
+ * arg is eithr an argument to the capability or -1 if there is none;
+ * if it is not -1 it will be passed as an additional argument to the
+ * function.
+ *
+ * outc is the output function; currently this is always putshout
+ * but in principle it may be used to output to a string.
+ */
+
+/**/
+static void
+tcout_via_func(int cap, int arg, int (*outc)(int))
+{
+    Shfunc tcout_func;
+    int osc, osm, old_incompfunc;
+
+    osc = sfcontext;
+    osm = stopmsg;
+    old_incompfunc = incompfunc;
+
+    sfcontext = SFC_SUBST;
+    incompfunc = 0;
+
+    if ((tcout_func = getshfunc(tcout_func_name))) {
+	LinkList l = newlinklist();
+	char buf[DIGBUFSIZE], *str;
+
+	addlinknode(l, tcout_func_name);
+	addlinknode(l, tccap_get_name(cap));
+
+	if (arg != -1) {
+	    sprintf(buf, "%d", arg);
+	    addlinknode(l, buf);
+	}
+
+	(void)doshfunc(tcout_func, l, 1);
+
+	str = getsparam("REPLY");
+	if (str) {
+	    while (*str) {
+		int chr;
+		if (*str == Meta) {
+		    chr = str[1] ^ 32;
+		    str += 2;
+		} else {
+		    chr = *str++;
+		}
+		(void)outc(chr);
+	    }
+	}
+    }
+
+    sfcontext = osc;
+    stopmsg = osm;
+    incompfunc = old_incompfunc;
+}
+
 /**/
 mod_export void
 tcout(int cap)
 {
-    tputs(tcstr[cap], 1, putshout);
+    if (tcout_func_name) {
+	tcout_via_func(cap, -1, putshout);
+    } else {
+	tputs(tcstr[cap], 1, putshout);
+    }
     SELECT_ADD_COST(tclen[cap]);
 }
 
@@ -2286,7 +2359,11 @@ tcoutarg(int cap, int arg)
     char *result;
 
     result = tgoto(tcstr[cap], arg, arg);
-    tputs(result, 1, putshout);
+    if (tcout_func_name) {
+	tcout_via_func(cap, arg, putshout);
+    } else {
+	tputs(result, 1, putshout);
+    }
     SELECT_ADD_COST(strlen(result));
 }
 
diff --git a/Src/Zle/zle_thingy.c b/Src/Zle/zle_thingy.c
index 03e73b4ca..49d715e06 100644
--- a/Src/Zle/zle_thingy.c
+++ b/Src/Zle/zle_thingy.c
@@ -353,6 +353,7 @@ bin_zle(char *name, char **args, Options ops, UNUSED(int func))
 	{ 'K', bin_zle_keymap, 1, 1 },
 	{ 'I', bin_zle_invalidate, 0, 0 },
 	{ 'F', bin_zle_fd, 0, 2 },
+	{ 'T', bin_zle_transform, 0, 2},
 	{ 0,   bin_zle_call, 0, -1 },
     };
     struct opn const *op, *opp;
@@ -856,6 +857,69 @@ bin_zle_fd(char *name, char **args, Options ops, UNUSED(char func))
     return 0;
 }
 
+/**/
+static int
+bin_zle_transform(char *name, char **args, Options ops, UNUSED(char func))
+{
+    /*
+     * -1: too few arguments
+     * 0: just right
+     * 1: too many arguments
+     * 2: first argument not recognised
+     */
+    int badargs = 0;
+
+    if (OPT_ISSET(ops,'L')) {
+	if (args[0]) {
+	    if (args[1]) {
+		badargs = 1;
+	    } else if (strcmp(args[0], "tc")) {
+		badargs = 2;
+	    }
+	}
+	if (!badargs && tcout_func_name) {
+	    fputs("zle -T tc ", stdout);
+	    quotedzputs(tcout_func_name, stdout);
+	    putchar('\n');
+	}
+    } else if (OPT_ISSET(ops,'r')) {
+	if (!args[0]) {
+	    badargs = -1;
+	} else if (args[1]) {
+	    badargs = 1;
+	} else if (tcout_func_name) {
+	    zsfree(tcout_func_name);
+	    tcout_func_name = NULL;
+	}
+    } else {
+	if (!args[0] || !args[1]) {
+	    badargs = -1;
+	    /* we've already checked args <= 2 */
+	} else {
+	    if (!strcmp(args[0], "tc")) {
+		if (tcout_func_name) {
+		    zsfree(tcout_func_name);
+		}
+		tcout_func_name = ztrdup(args[1]);
+	    } else {
+		badargs = 2;
+	    }
+	}
+    }
+
+    if (badargs) {
+	if (badargs == 2) {
+	    zwarnnam(name, "-T: no such transformation '%s'", args[0]);
+	} else {
+	    char *way = (badargs > 0) ? "many" : "few";
+	    zwarnnam(name, "too %s arguments for option -T", way);
+	}
+	return 1;
+    }
+
+    return 0;
+}
+
 /*******************/
 /* initialiasation */
 /*******************/
diff --git a/Src/init.c b/Src/init.c
index 29191410e..9820070fb 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -558,6 +558,19 @@ static char *tccapnams[TC_COUNT] = {
     "ku", "kd", "kl", "kr", "sc", "rc", "bc", "AF", "AB"
 };
 
+/**/
+mod_export char *
+tccap_get_name(int cap)
+{
+    if (cap >= TC_COUNT) {
+#ifdef DEBUG
+	dputs("name of invalid capability %d requested", cap);
+#endif
+	return "";
+    }
+    return tccapnams[cap];
+}
+
 /* Initialise termcap */
 
 /**/