diff options
Diffstat (limited to 'Src/Zle')
-rw-r--r-- | Src/Zle/zle_main.c | 2 | ||||
-rw-r--r-- | Src/Zle/zle_refresh.c | 81 | ||||
-rw-r--r-- | Src/Zle/zle_thingy.c | 64 |
3 files changed, 144 insertions, 3 deletions
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 */ /*******************/ |