Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: Adding tests for zle? The missing X series tests
- X-seq: zsh-workers 30084
- From: Peter Stephenson <p.w.stephenson@xxxxxxxxxxxx>
- To: <zsh-workers@xxxxxxx>
- Subject: Re: Adding tests for zle? The missing X series tests
- Date: Wed, 4 Jan 2012 17:38:44 +0000
- In-reply-to: <20111221113947.75942dd8@pwslap01u.europe.root.pri>
- List-help: <mailto:zsh-workers-help@zsh.org>
- List-id: Zsh Workers List <zsh-workers.zsh.org>
- List-post: <mailto:zsh-workers@zsh.org>
- Mailing-list: contact zsh-workers-help@xxxxxxx; run by ezmlm
- References: <CANGpWcegC1R2ayUs34PKK3o3PFFPEKh5wsTVh8mEX5ERi-Sz0Q@mail.gmail.com> <20111221113947.75942dd8@pwslap01u.europe.root.pri>
On Wed, 21 Dec 2011 11:39:47 +0000
Peter Stephenson <Peter.Stephenson@xxxxxxx> wrote:
> Probably easier is to intercept the terminal output at a low-level
> inside the shell by having an option that directly outputs values from
> an associative array with termcap codes as keys (this doesn't need to be
> particularly user-friendly, and as zsh internally still uses termcap
> codes this looks like the easiest way to test it) instead of using the
> termcap output functions. That shouldn't be too much work --- termcap
> is vastly simpler than e.g. curses --- and makes the job no harder (!)
> than testing completion. There are also potential uses for this in
> debugging --- it should provide a simpler method of finding out what has
> caused the cursor to end up where it did.
A function both makes this flexible and allows you to handle all termcap
entries uniformly.
I've done this by adding a generic command for zle transformations, but
I don't know that we'll ever use this for anything else.
Try
tcfunc() {
if [[ -n $2 ]]; then
REPLY="<tc=$1,arg=$2>"
else
REPLY="<tc=$1>"
fi
}
zle -T tc tcfunc
and
zle -Tr tc
to turn it off (your typing had better be accurate).
There's a completely irrelevant zsfree(argzero) snuck in because I was
too lazy to separate it. This stops a valgrind warning in some cases
(it's a very minor leak since it only happens once at the start).
Index: Doc/Zsh/zle.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/zle.yo,v
retrieving revision 1.95
diff -p -u -r1.95 zle.yo
--- Doc/Zsh/zle.yo 4 Nov 2011 14:14:27 -0000 1.95
+++ Doc/Zsh/zle.yo 4 Jan 2012 17:32:13 -0000
@@ -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
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.
Index: Src/init.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/init.c,v
retrieving revision 1.120
diff -p -u -r1.120 init.c
--- Src/init.c 9 May 2011 09:49:09 -0000 1.120
+++ Src/init.c 4 Jan 2012 17:32:14 -0000
@@ -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 */
/**/
@@ -978,6 +991,7 @@ setupshin(char *runscript)
exit(127);
}
scriptfilename = sfname;
+ zsfree(argzero); /* ztrdup'd in parseargs */
argzero = runscript;
}
/*
Index: Src/Zle/zle_main.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_main.c,v
retrieving revision 1.131
diff -p -u -r1.131 zle_main.c
--- Src/Zle/zle_main.c 2 Jan 2012 19:31:16 -0000 1.131
+++ Src/Zle/zle_main.c 4 Jan 2012 17:32:14 -0000
@@ -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
Index: Src/Zle/zle_refresh.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_refresh.c,v
retrieving revision 1.88
diff -p -u -r1.88 zle_refresh.c
--- Src/Zle/zle_refresh.c 17 Aug 2011 10:15:50 -0000 1.88
+++ Src/Zle/zle_refresh.c 4 Jan 2012 17:32:14 -0000
@@ -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));
}
Index: Src/Zle/zle_thingy.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_thingy.c,v
retrieving revision 1.35
diff -p -u -r1.35 zle_thingy.c
--- Src/Zle/zle_thingy.c 4 Nov 2011 14:14:27 -0000 1.35
+++ Src/Zle/zle_thingy.c 4 Jan 2012 17:32:14 -0000
@@ -353,6 +353,7 @@ bin_zle(char *name, char **args, Options
{ '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, Opti
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 */
/*******************/
Messages sorted by:
Reverse Date,
Date,
Thread,
Author