diff options
author | Tanaka Akira <akr@users.sourceforge.net> | 1999-06-27 05:33:04 +0000 |
---|---|---|
committer | Tanaka Akira <akr@users.sourceforge.net> | 1999-06-27 05:33:04 +0000 |
commit | 346825df86466cf151be61b9429ef2c1734e66ea (patch) | |
tree | bd3e1ccd947b47f974c62b4113c5276416de2c9f /Src | |
parent | a2159285e80508bb682d90a71270fbddada8bd05 (diff) | |
download | zsh-346825df86466cf151be61b9429ef2c1734e66ea.tar.gz zsh-346825df86466cf151be61b9429ef2c1734e66ea.tar.xz zsh-346825df86466cf151be61b9429ef2c1734e66ea.zip |
zsh-3.1.5-pws-24 zsh-3.1.5-pws-24
Diffstat (limited to 'Src')
42 files changed, 3194 insertions, 1254 deletions
diff --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c index 4cb7b0aba..908a05ce9 100644 --- a/Src/Modules/parameter.c +++ b/Src/Modules/parameter.c @@ -326,7 +326,7 @@ setfunction(char *name, char *val) val = metafy(val, strlen(val), META_REALLOC); HEAPALLOC { - list = parse_string(val); + list = parse_string(val, 1); } LASTALLOC; if (!list || list == &dummy_list) { diff --git a/Src/Zle/.distfiles b/Src/Zle/.distfiles index 9dbf27758..add8f8466 100644 --- a/Src/Zle/.distfiles +++ b/Src/Zle/.distfiles @@ -2,6 +2,7 @@ DISTFILES_SRC=' .cvsignore .distfiles .exrc comp1.mdd comp.h comp1.c comp1.export compctl.mdd compctl.c + complist.mdd complist.c deltochar.mdd deltochar.c zle.mdd iwidgets.list zle.h zle_bindings.c zle_hist.c zle_keymap.c zle_main.c zle_misc.c zle_move.c zle_params.c diff --git a/Src/Zle/comp.h b/Src/Zle/comp.h index bf3ea816f..8264890df 100644 --- a/Src/Zle/comp.h +++ b/Src/Zle/comp.h @@ -36,6 +36,7 @@ typedef struct patcomp *Patcomp; typedef struct cmatcher *Cmatcher; typedef struct cmlist *Cmlist; typedef struct cpattern *Cpattern; +typedef struct menuinfo *Menuinfo; /* node for compctl hash table (compctltab) */ @@ -266,6 +267,19 @@ struct cpattern { #define CFN_FIRST 1 #define CFN_DEFAULT 2 +/* Information about menucompletion stuff. */ + +struct menuinfo { + Cmgroup group; /* position in the group list */ + Cmatch *cur; /* match currently inserted */ + int pos; /* begin on line */ + int len; /* length of inserted string */ + int end; /* end on the line */ + int we; /* non-zero if the cursor was at the end */ + int insc; /* length of suffix inserted */ + int asked; /* we asked if the list should be shown */ +}; + /* Flags for compadd and addmatches(). */ #define CAF_QUOTE 1 @@ -286,6 +300,7 @@ struct cadata { char *pre; /* prefix to insert (-P) */ char *suf; /* suffix to insert (-S) */ char *group; /* name of the group (-[JV]) */ + char *ylist; /* display list (-y) */ char *rems; /* remove suffix on chars... (-r) */ char *remf; /* function to remove suffix (-R) */ char *ign; /* ignored suffixes (-F) */ @@ -298,6 +313,16 @@ struct cadata { char *dpar; /* array to delete non-matches in (-D) */ }; +/* Data given to hooks. */ + +typedef struct chdata *Chdata; + +struct chdata { + Cmgroup matches; /* the matches generated */ + int num; /* the number of matches */ + Cmatch cur; /* current match or NULL */ +}; + /* Flags for special parameters. */ #define CPN_WORDS 0 diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c index c5b24714e..2b426492e 100644 --- a/Src/Zle/compctl.c +++ b/Src/Zle/compctl.c @@ -1727,7 +1727,7 @@ bin_compadd(char *name, char **argv, char *ops, int func) } dat.ipre = dat.isuf = dat.ppre = dat.psuf = dat.prpre = dat.pre = dat.suf = dat.group = dat.rems = dat.remf = - dat.ign = dat.exp = dat.apar = dat.opar = dat.dpar = NULL; + dat.ign = dat.exp = dat.apar = dat.opar = dat.dpar = dat.ylist = NULL; dat.match = NULL; dat.flags = 0; dat.aflags = CAF_MATCH; @@ -1779,6 +1779,10 @@ bin_compadd(char *name, char **argv, char *ops, int func) sp = &(dat.group); e = "group name expected after -%c"; break; + case 'y': + sp = &(dat.ylist); + e = "string expected after -%c"; + break; case 'i': sp = &(dat.ipre); e = "string expected after -%c"; @@ -2217,13 +2221,14 @@ static void addcompparams(struct compparam *cp, Param *pp) { for (; cp->name; cp++, pp++) { - Param pm = createparam(cp->name, cp->type | PM_SPECIAL | PM_REMOVABLE); + Param pm = createparam(cp->name, + cp->type |PM_SPECIAL|PM_REMOVABLE|PM_LOCAL); if (!pm) pm = (Param) paramtab->getnode(paramtab, cp->name); DPUTS(!pm, "param not set in addcompparams"); *pp = pm; - pm->level = locallevel; + pm->level = locallevel + 1; if ((pm->u.data = cp->var)) { switch(PM_TYPE(cp->type)) { case PM_SCALAR: @@ -2257,7 +2262,8 @@ makecompparams(void) addcompparams(comprparams, comprpms); - if (!(cpm = createparam(COMPSTATENAME, PM_SPECIAL|PM_REMOVABLE|PM_HASHED))) + if (!(cpm = createparam(COMPSTATENAME, + PM_SPECIAL|PM_REMOVABLE|PM_LOCAL|PM_HASHED))) cpm = (Param) paramtab->getnode(paramtab, COMPSTATENAME); DPUTS(!cpm, "param not set in makecompparams"); diff --git a/Src/Zle/complist.c b/Src/Zle/complist.c new file mode 100644 index 000000000..63bc4c6e3 --- /dev/null +++ b/Src/Zle/complist.c @@ -0,0 +1,918 @@ +/* + * complist.c - completion listing enhancements + * + * This file is part of zsh, the Z shell. + * + * Copyright (c) 1999 Sven Wischnowsky + * All rights reserved. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and to distribute modified versions of this software for any + * purpose, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * In no event shall Sven Wischnowsky or the Zsh Development Group be liable + * to any party for direct, indirect, special, incidental, or consequential + * damages arising out of the use of this software and its documentation, + * even if Sven Wischnowsky and the Zsh Development Group have been advised of + * the possibility of such damage. + * + * Sven Wischnowsky and the Zsh Development Group specifically disclaim any + * warranties, including, but not limited to, the implied warranties of + * merchantability and fitness for a particular purpose. The software + * provided hereunder is on an "as is" basis, and Sven Wischnowsky and the + * Zsh Development Group have no obligation to provide maintenance, + * support, updates, enhancements, or modifications. + * + */ + +#include "complist.mdh" +#include "complist.pro" + + +/* We use the parameters ZLS_COLORS and ZLS_COLOURS in the same way as + * the color ls does. It's just that we don't support the `or' file + * type. */ + + +static Widget w_menuselect; +static Keymap mskeymap; + +/* Indixes into the terminal string arrays. */ + +#define COL_NO 0 +#define COL_FI 1 +#define COL_DI 2 +#define COL_LN 3 +#define COL_PI 4 +#define COL_SO 5 +#define COL_BD 6 +#define COL_CD 7 +#define COL_EX 8 +#define COL_MI 9 +#define COL_LC 10 +#define COL_RC 11 +#define COL_EC 12 +#define COL_MA 13 + +#define NUM_COLS 14 + +/* Names of the terminal strings. */ + +static char *colnames[] = { + "no", "fi", "di", "ln", "pi", "so", "bd", "cd", "ex", "mi", + "lc", "rc", "ec", "ma", NULL +}; + +/* Default values. */ + +static char *defcols[] = { + "0", "0", "1;34", "1;36", "33", "1;35", "1;33", "1;33", "1;32", NULL, + "\033[", "m", NULL, "7" +}; + +/* This describes a terminal string for a filename extension. */ + +typedef struct extcol *Extcol; + +struct extcol { + char *ext; /* the extension */ + char *col; /* the terminal color string */ + Extcol next; /* the next one in the list */ +}; + +/* This holds all terminal strings. */ + +typedef struct listcols *Listcols; + +struct listcols { + char *cols[NUM_COLS]; /* strings for file types */ + Extcol exts; /* strings for extensions */ +}; + +/* This parses the value of a definition (the part after the `='). + * The return value is a pointer to the character after it. */ + +static char * +getcolval(char *s) +{ + char *p; + + for (p = s; *s && *s != ':'; p++, s++) { + if (*s == '\\' && s[1]) { + switch (*++s) { + case 'a': *p = '\007'; break; + case 'n': *p = '\n'; break; + case 'b': *p = '\b'; break; + case 't': *p = '\t'; break; + case 'v': *p = '\v'; break; + case 'f': *p = '\f'; break; + case 'r': *p = '\r'; break; + case 'e': *p = '\033'; break; + case '_': *p = ' '; break; + case '?': *p = '\177'; break; + default: + if (*s >= '0' && *s <= '7') { + int i = STOUC(*s); + + if (*++s >= '0' && *s <= '7') { + i = (i * 8) + STOUC(*s); + if (*++s >= '0' && *s <= '7') + i = (i * 8) + STOUC(*s); + } + *p = (char) i; + } else + *p = *s; + } + } else if (*s == '^') { + if ((s[1] >= '@' && s[1] <= '_') || + (s[1] >= 'a' && s[1] <= 'z')) + *p = (char) (STOUC(*s) & ~0x60); + else if (s[1] == '?') + *p = '\177'; + else { + *p++ = *s; + *p = s[1]; + } + s++; + } else + *p = *s; + } + if (p != s) + *p = '\0'; + return s; +} + +/* This parses one definition. Return value is a pointer to the + * character after it. */ + +static char * +getcoldef(Listcols c, char *s) +{ + if (*s == '*') { + Extcol ec; + char *n, *p; + + /* This is for an extension. */ + + n = ++s; + while (*s && *s != '=') + s++; + if (!*s ) + return s; + *s++ = '\0'; + p = getcolval(s); + if (*n) { + ec = (Extcol) zhalloc(sizeof(*ec)); + ec->ext = n; + ec->col = s; + ec->next = c->exts; + c->exts = ec; + } + if (*p) + *p++ = '\0'; + return p; + } else { + char *n = s, *p, **nn; + int i; + + /* This is for a file type. */ + + while (*s && *s != '=') + s++; + if (!*s) + return s; + *s++ = '\0'; + for (i = 0, nn = colnames; *nn; i++, nn++) + if (!strcmp(n ,*nn)) + break; + p = getcolval(s); + if (*nn) + c->cols[i] = s; + if (*p) + *p++ = '\0'; + return p; + } +} + +/* This initializes the given terminal color structure. */ + +static int +getcols(Listcols c) +{ + char *s; + int i; + + if (!(s = getsparam("ZLS_COLORS")) && + !(s = getsparam("ZLS_COLOURS"))) { + if (!c) + return 1; + for (i = 0; i < NUM_COLS; i++) + c->cols[i] = ""; + + c->exts = NULL; + return 1; + } + if (!c) + return 0; + /* We have one of the parameters, use it. */ + memset(c, 0, sizeof(*c)); + s = dupstring(s); + while (*s) + s = getcoldef(c, s); + + /* Use default values for those that aren't set explicitly. */ + for (i = 0; i < NUM_COLS; i++) + if (!c->cols[i]) + c->cols[i] = defcols[i]; + /* Default for missing files. */ + if (!c->cols[COL_MI]) + c->cols[COL_MI] = c->cols[COL_FI]; + + if (!c->cols[COL_EC]) { + char *e = (char *) zhalloc(strlen(c->cols[COL_LC]) + + strlen(c->cols[COL_NO]) + + strlen(c->cols[COL_RC]) + 1); + + /* If no `ec' was given, we is `<lc><no><rc>' as the default. */ + strcpy(e, c->cols[COL_LC]); + strcat(e, c->cols[COL_NO]); + strcat(e, c->cols[COL_RC]); + c->cols[COL_EC] = e; + } + return 0; +} + +/* Get the terminal color string for the file with the given name and + * file modes. */ + +static char * +getcolstr(Listcols c, char *n, mode_t m) +{ + Extcol e; + + for (e = c->exts; e; e = e->next) + if (strsfx(e->ext, n)) + return e->col; + + if (S_ISDIR(m)) + return c->cols[COL_DI]; + else if (S_ISLNK(m)) + return c->cols[COL_LN]; + else if (S_ISFIFO(m)) + return c->cols[COL_PI]; + else if (S_ISSOCK(m)) + return c->cols[COL_SO]; + else if (S_ISBLK(m)) + return c->cols[COL_BD]; + else if (S_ISCHR(m)) + return c->cols[COL_CD]; + else if (S_ISREG(m) && (m & S_IXUGO)) + return c->cols[COL_EX]; + + return c->cols[COL_FI]; +} + +/* Information about the list shown. */ + +static int noselect, mselect, inselect, mcol, mline, mcols, mlines; +static Cmatch *mmatch, **mtab; +static Cmgroup mgroup, *mgtab; + +/* List the matches. Most of this is just taken from ilistmatches(), + * of course. */ + +static int +complistmatches(Hookdef dummy, Chdata dat) +{ + Cmgroup amatches = dat->matches, g; + Cmatch *p, m; + Cexpl *e; + int nlines = 0, ncols, nlist = 0, longest = 1, pnl = 0, opl = 0; + int of = isset(LISTTYPES); + int mc, ml = 0, cc, hasm = 0; + struct listcols col; + + if (minfo.asked == 2) { + showinglist = 0; + return (noselect = 1); + } + getcols(&col); + + /* Set the cursor below the prompt. */ + if (inselect) + clearflag = 0; + trashzle(); + showinglist = listshown = 0; + + clearflag = (isset(USEZLE) && !termflags && + complastprompt && *complastprompt); + + for (g = amatches; g; g = g->next) { + char **pp = g->ylist; + int nl = 0, l; + + if (pp) { + /* We have an ylist, lets see, if it contains newlines. */ + while (!nl && *pp) + nl = !!strchr(*pp++, '\n'); + + pp = g->ylist; + if (nl) { + /* Yup, there are newlines, count lines. */ + char *nlptr, *sptr; + + g->flags |= CGF_LINES; + noselect = 1; + while ((sptr = *pp)) { + while (sptr && *sptr) { + nlines += (nlptr = strchr(sptr, '\n')) + ? 1 + (nlptr-sptr)/columns + : strlen(sptr)/columns; + sptr = nlptr ? nlptr+1 : NULL; + } + nlines++; + pp++; + } + nlines--; + } else { + while (*pp) { + if ((l = strlen(*pp)) > longest) + longest = l; + nlist++; + pp++; + } + } + } else { + for (p = g->matches; (m = *p); p++) { + if (!(m->flags & CMF_NOLIST)) { + if ((l = niceztrlen(m->str)) > longest) + longest = l; + nlist++; + } else + noselect = 1; + } + } + if ((e = g->expls)) { + while (*e) { + if ((*e)->count) + nlines += 1 + printfmt((*e)->str, (*e)->count, 0); + e++; + } + } + } + longest += 2 + of; + if ((ncols = (columns + 1) / longest)) { + for (g = amatches; g; g = g->next) + nlines += (g->lcount + ncols - 1) / ncols; + } else { + ncols = 1; + opl = 1; + for (g = amatches; g; g = g->next) { + char **pp = g->ylist; + + if (pp) { + if (!(g->flags & CGF_LINES)) { + while (*pp) { + nlines += 1 + (strlen(*pp) / columns); + pp++; + } + } + } else + for (p = g->matches; (m = *p); p++) + if (!(m->flags & CMF_NOLIST)) + nlines += 1 + ((1 + niceztrlen(m->str)) / columns); + } + } + + /* Maybe we have to ask if the user wants to see the list. */ + if ((!minfo.cur || !minfo.asked) && + ((complistmax && nlist > complistmax) || + (!complistmax && nlines >= lines))) { + int qup; + zsetterm(); + qup = printfmt("zsh: do you wish to see all %n possibilities? ", nlist, 1); + fflush(shout); + if (getzlequery() != 'y') { + if (clearflag) { + putc('\r', shout); + tcmultout(TCUP, TCMULTUP, qup); + if (tccan(TCCLEAREOD)) + tcout(TCCLEAREOD); + tcmultout(TCUP, TCMULTUP, nlnct); + } else + putc('\n', shout); + noselect = 1; + if (minfo.cur) + minfo.asked = 2; + return 1; + } + if (clearflag) { + putc('\r', shout); + tcmultout(TCUP, TCMULTUP, qup); + if (tccan(TCCLEAREOD)) + tcout(TCCLEAREOD); + } else + putc('\n', shout); + settyinfo(&shttyinfo); + if (minfo.cur) + minfo.asked = 1; + } + if (mselect >= 0) { + int i; + + i = ncols * nlines; + free(mtab); + mtab = (Cmatch **) zalloc(i * sizeof(Cmatch **)); + memset(mtab, 0, i * sizeof(Cmatch **)); + free(mgtab); + mgtab = (Cmgroup *) zalloc(i * sizeof(Cmgroup)); + memset(mgtab, 0, i * sizeof(Cmgroup)); + mcols = ncols; + mlines = nlines; + } + /* Now print the matches. */ + g = amatches; + while (g) { + char **pp = g->ylist; + + if ((e = g->expls)) { + while (*e) { + if ((*e)->count) { + if (pnl) { + putc('\n', shout); + pnl = 0; + ml++; + } + ml += printfmt((*e)->str, (*e)->count, 1); + pnl = 1; + } + e++; + } + } + if (pp && *pp) { + if (pnl) { + putc('\n', shout); + pnl = 0; + ml++; + } + if (g->flags & CGF_LINES) { + while (*pp) { + zputs(*pp, shout); + if (*++pp) + putc('\n', shout); + } + } else { + int n = g->lcount, nl = (n + ncols - 1) / ncols, nc = nl, i, a; + char **pq; + + while (n && nl--) { + i = ncols; + mc = 0; + pq = pp; + while (n && i--) { + if (pq - g->ylist >= g->lcount) + break; + zputs(*pq, shout); + if (i) { + a = longest - strlen(*pq); + while (a--) + putc(' ', shout); + } + pq += nc; + n--; + } + if (n) { + putc('\n', shout); + ml++; + } + pp++; + } + } + } else if (g->lcount) { + int n = g->lcount, nl = (n + ncols - 1) / ncols, nc = nl, i, j, a = 0; + int zt; + Cmatch *q; + + if (n && pnl) { + putc('\n', shout); + pnl = 0; + ml++; + } + for (p = skipnolist(g->matches); n && nl--;) { + i = ncols; + mc = 0; + q = p; + while (n && i--) { + fputs(col.cols[COL_LC], shout); + if (!(m = *q)) { + fputs(col.cols[COL_MI], shout); + fputs(col.cols[COL_RC], shout); + a = longest - 2; + while (a--) + putc(' ', shout); + fputs(col.cols[COL_EC], shout); + break; + } + hasm = 1; + if (mselect >= 0) { + mtab[mc + (ncols * ml)] = q; + mgtab[mc + (ncols * ml)] = g; + } + if (m->gnum == mselect) { + mcol = mc; + mline = ml; + mmatch = q; + mgroup = g; + cc = COL_MA; + } else + cc = -1; + if (m->flags & CMF_FILE) { + struct stat buf; + char *pb; + + pb = (char *) zhalloc((m->prpre ? strlen(m->prpre) : 0) + + 3 + strlen(m->str)); + sprintf(pb, "%s%s", (m->prpre ? m->prpre : "./"), + m->str); + + zt = ztat(pb, &buf, 1); + if (cc >= 0) + fputs(col.cols[cc], shout); + else if (zt) + fputs(col.cols[COL_NO], shout); + else + fputs(getcolstr(&col, pb, buf.st_mode), shout); + fputs(col.cols[COL_RC], shout); + nicezputs(m->str, shout); + if (zt) + putc(' ', shout); + else + putc(file_type(buf.st_mode), shout); + } else { + fputs(col.cols[cc >= 0 ? cc : COL_NO], shout); + fputs(col.cols[COL_RC], shout); + nicezputs(m->str, shout); + if (of) + putc(' ', shout); + } + a = longest - niceztrlen(m->str) - 2 - of; + while (a--) + putc(' ', shout); + fputs(col.cols[COL_EC], shout); + if (i) { + fputs(col.cols[COL_LC], shout); + fputs(col.cols[COL_NO], shout); + fputs(col.cols[COL_RC], shout); + fputs(" ", shout); + fputs(col.cols[COL_EC], shout); + } + if (--n) + for (j = nc; j && *q; j--) + q = skipnolist(q + 1); + mc++; + } + if (i > 0) { + fputs(col.cols[COL_LC], shout); + fputs(col.cols[COL_MI], shout); + fputs(col.cols[COL_RC], shout); + a = longest - 2; + while (a--) + putc(' ', shout); + fputs(col.cols[COL_EC], shout); + } + if (n) { + putc('\n', shout); + ml++; + if (n && nl) + p = skipnolist(p + 1); + } + } + } + if (g->lcount) + pnl = 1; + g = g->next; + } + + if (clearflag) { + /* Move the cursor up to the prompt, if always_last_prompt * + * is set and all that... */ + if ((nlines += nlnct - 1) < lines) { + tcmultout(TCUP, TCMULTUP, nlines); + showinglist = -1; + listshown = 1; + } else + clearflag = 0, putc('\n', shout); + } else + putc('\n', shout); + if (!hasm || nlines >= lines) + noselect = 1; + return noselect; +} + +typedef struct menustack *Menustack; + +struct menustack { + Menustack prev; + char *line; + int cs; + struct menuinfo info; +}; + +static int +domenuselect(Hookdef dummy, Chdata dat) +{ + Cmatch **p; + Cmgroup *pg; + Thingy cmd; + Menustack u = NULL; + int i = 0; + char *s; + + if (getcols(NULL) || (dummy && (!(s = getsparam("SELECTMIN")) || + (dat && dat->num < atoi(s))))) + return 1; + + selectlocalmap(mskeymap); + noselect = 0; + mselect = (*(minfo.cur))->gnum; + for (;;) { + showinglist = -2; + zrefresh(); + inselect = 1; + if (noselect) + break; + if (!i) { + i = mcols * mlines; + while (i--) + if (mtab[i]) + break; + if (!i) + break; + i = 1; + } + p = mtab + mcol + (mline * mcols); + pg = mgtab + mcol + (mline * mcols); + minfo.cur = *p; + minfo.group = *pg; + + getk: + + if (!(cmd = getkeycmd()) || cmd == Th(z_sendbreak) || + cmd == Th(z_acceptline)) + break; + else if (cmd == Th(z_acceptandhold) || + cmd == Th(z_acceptandmenucomplete)) { + Menustack s = (Menustack) zhalloc(sizeof(*s)); + + s->prev = u; + u = s; + s->line = dupstring((char *) line); + s->cs = cs; + memcpy(&(s->info), &minfo, sizeof(struct menuinfo)); + acceptlast(); + do_menucmp(0); + mselect = (*(minfo.cur))->gnum; + continue; + } else if (cmd == Th(z_undo)) { + int l; + + if (!u) + goto getk; + + cs = 0; + foredel(ll); + spaceinline(l = strlen(u->line)); + strncpy((char *) line, u->line, l); + cs = u->cs; + memcpy(&minfo, &(u->info), sizeof(struct menuinfo)); + p = &(minfo.cur); + u = u->prev; + } else if (cmd == Th(z_redisplay)) { + redisplay(zlenoargs); + continue; + } else if (cmd == Th(z_clearscreen)) { + clearscreen(zlenoargs); + continue; + } else if (cmd == Th(z_downhistory) || + cmd == Th(z_downlineorhistory) || + cmd == Th(z_downlineorsearch) || + cmd == Th(z_vidownlineorhistory)) { + do { + if (mline == mlines - 1) { + p -= mline * mcols; + mline = 0; + } else { + mline++; + p += mcols; + } + } while (!*p); + } else if (cmd == Th(z_uphistory) || + cmd == Th(z_uplineorhistory) || + cmd == Th(z_uplineorsearch) || + cmd == Th(z_viuplineorhistory)) { + do { + if (!mline) { + mline = mlines - 1; + p += mline * mcols; + } else { + mline--; + p -= mcols; + } + } while (!*p); + } else if (cmd == Th(z_forwardchar) || cmd == Th(z_viforwardchar)) { + do { + if (mcol == mcols - 1) { + p -= mcol; + mcol = 0; + } else { + mcol++; + p++; + } + } while (!*p); + } else if (cmd == Th(z_backwardchar) || cmd == Th(z_vibackwardchar)) { + do { + if (!mcol) { + mcol = mcols - 1; + p += mcol; + } else { + mcol--; + p--; + } + } while (!*p); + } else if (cmd == Th(z_beginningofbufferorhistory) || + cmd == Th(z_beginningofline) || + cmd == Th(z_beginningoflinehist) || + cmd == Th(z_vibeginningofline)) { + p -= mcol; + mcol = 0; + while (!*p) { + mcol++; + p++; + } + } else if (cmd == Th(z_endofbufferorhistory) || + cmd == Th(z_endofline) || + cmd == Th(z_endoflinehist) || + cmd == Th(z_viendofline)) { + p += mcols - mcol - 1; + mcol = mcols - 1; + while (!*p) { + mcol--; + p--; + } + } else if (cmd == Th(z_forwardword) || + cmd == Th(z_emacsforwardword) || + cmd == Th(z_viforwardword) || + cmd == Th(z_viforwardwordend)) { + Cmgroup g = *pg; + int ol = mline; + + do { + if (mline == mlines - 1) { + p -= mline * mcols; + pg -= mline * mcols; + mline = 0; + } else { + mline++; + p += mcols; + pg += mcols; + } + } while (ol != mline && (*pg == g || !*pg)); + } else if (cmd == Th(z_backwardword) || + cmd == Th(z_emacsbackwardword) || + cmd == Th(z_vibackwardword)) { + Cmgroup g = *pg; + int ol = mline; + + do { + if (!mline) { + mline = mlines - 1; + p += mline * mcols; + pg += mline * mcols; + } else { + mline--; + p -= mcols; + pg -= mcols; + } + } while (ol != mline && (*pg == g || !*pg)); + } else if (cmd == Th(z_completeword) || + cmd == Th(z_expandorcomplete) || + cmd == Th(z_expandorcompleteprefix) || + cmd == Th(z_menucomplete) || + cmd == Th(z_menuexpandorcomplete) || + !strcmp(cmd->nam, "menu-select") || + !strcmp(cmd->nam, "complete-word") || + !strcmp(cmd->nam, "expand-or-complete") || + !strcmp(cmd->nam, "expand-or-complete-prefix") || + !strcmp(cmd->nam, "menu-complete") || + !strcmp(cmd->nam, "menu-expand-or-complete")) { + do_menucmp(0); + mselect = (*(minfo.cur))->gnum; + continue; + } else if (cmd == Th(z_reversemenucomplete) || + !strcmp(cmd->nam, "reverse-menu-complete")) { + reversemenucomplete(zlenoargs); + mselect = (*(minfo.cur))->gnum; + continue; + } else { + ungetkeycmd(); + break; + } + do_single(**p); + mselect = (**p)->gnum; + } + selectlocalmap(NULL); + mselect = -1; + inselect = 0; + if (!noselect) { + showinglist = -2; + zrefresh(); + } + return noselect; +} + +/* The widget function. */ + +static int +menuselect(char **args) +{ + int d = 0; + + if (!minfo.cur) { + menucomplete(args); + if ((minfo.cur && minfo.asked == 2) || getsparam("ZLS_SELECT")) + return 0; + d = 1; + } + if (minfo.cur && (minfo.asked == 2 || domenuselect(NULL, NULL)) && !d) + menucomplete(args); + + return 0; +} + +/**/ +int +setup_complist(Module m) +{ + return 0; +} + +/**/ +int +boot_complist(Module m) +{ + mtab = NULL; + mgtab = NULL; + mselect = -1; + inselect = 0; + + w_menuselect = addzlefunction("menu-select", menuselect, + ZLE_MENUCMP|ZLE_KEEPSUFFIX|ZLE_ISCOMP); + if (!w_menuselect) { + zwarnnam(m->nam, "name clash when adding ZLE function `menu-select'", + NULL, 0); + return -1; + } + addhookfunc("list_matches", (Hookfn) complistmatches); + addhookfunc("menu_start", (Hookfn) domenuselect); + mskeymap = newkeymap(NULL, "menuselect"); + linkkeymap(mskeymap, "menuselect", 1); + bindkey(mskeymap, "\t", refthingy(t_completeword), NULL); + bindkey(mskeymap, "\n", refthingy(t_acceptline), NULL); + bindkey(mskeymap, "\r", refthingy(t_acceptline), NULL); + bindkey(mskeymap, "\33[A", refthingy(t_uplineorhistory), NULL); + bindkey(mskeymap, "\33[B", refthingy(t_downlineorhistory), NULL); + bindkey(mskeymap, "\33[C", refthingy(t_forwardchar), NULL); + bindkey(mskeymap, "\33[D", refthingy(t_backwardchar), NULL); + bindkey(mskeymap, "\33OA", refthingy(t_uplineorhistory), NULL); + bindkey(mskeymap, "\33OB", refthingy(t_downlineorhistory), NULL); + bindkey(mskeymap, "\33OC", refthingy(t_forwardchar), NULL); + bindkey(mskeymap, "\33OD", refthingy(t_backwardchar), NULL); + return 0; +} + +#ifdef MODULE + +/**/ +int +cleanup_complist(Module m) +{ + free(mtab); + free(mgtab); + + deletezlefunction(w_menuselect); + deletehookfunc("list_matches", (Hookfn) complistmatches); + deletehookfunc("menu_start", (Hookfn) domenuselect); + unlinkkeymap("menuselect", 1); + return 0; +} + +/**/ +int +finish_complist(Module m) +{ + return 0; +} + +#endif diff --git a/Src/Zle/complist.mdd b/Src/Zle/complist.mdd new file mode 100644 index 000000000..8ea60b0a8 --- /dev/null +++ b/Src/Zle/complist.mdd @@ -0,0 +1,3 @@ +moddeps="comp1 zle" + +objects="complist.o" diff --git a/Src/Zle/deltochar.c b/Src/Zle/deltochar.c index 66a301119..f0df33f95 100644 --- a/Src/Zle/deltochar.c +++ b/Src/Zle/deltochar.c @@ -33,8 +33,8 @@ static Widget w_deletetochar; /**/ -static void -deltochar(void) +static int +deltochar(char **args) { int c = getkey(0), dest = cs, ok = 0, n = zmult; @@ -67,8 +67,7 @@ deltochar(void) } } } - if (!ok) - feep(); + return !ok; } /**/ diff --git a/Src/Zle/iwidgets.list b/Src/Zle/iwidgets.list index e0c93bd03..c28acb438 100644 --- a/Src/Zle/iwidgets.list +++ b/Src/Zle/iwidgets.list @@ -19,6 +19,7 @@ "backward-kill-line", backwardkillline, ZLE_KILL | ZLE_KEEPSUFFIX "backward-kill-word", backwardkillword, ZLE_KILL | ZLE_KEEPSUFFIX "backward-word", backwardword, 0 +"beep", handlefeep, 0 "beginning-of-buffer-or-history", beginningofbufferorhistory, 0 "beginning-of-history", beginningofhistory, 0 "beginning-of-line", beginningofline, 0 diff --git a/Src/Zle/zle.export b/Src/Zle/zle.export index ccd5df98a..e0b88cd5c 100644 --- a/Src/Zle/zle.export +++ b/Src/Zle/zle.export @@ -1,10 +1,44 @@ #! +acceptlast addzlefunction backdel backkill +bindkey +clearflag +clearscreen deletezlefunction +do_menucmp +do_single feep foredel forekill getkey +getkeycmd +getzlequery +linkkeymap +listshown +menucomplete +menucur +menugrp +minfo +newkeymap +nlnct +printfmt +redisplay +refthingy +reversemenucomplete +selectlocalmap +showinglist +skipnolist +spaceinline +tcmultout +tcout +thingies +trashzle +ungetkeycmd +unlinkkeymap +zlenoargs zmod +zrefresh +zsetterm +ztat diff --git a/Src/Zle/zle.h b/Src/Zle/zle.h index d5e0ee89c..ff515e7c4 100644 --- a/Src/Zle/zle.h +++ b/Src/Zle/zle.h @@ -38,7 +38,7 @@ typedef struct thingy *Thingy; /* widgets (ZLE functions) */ -typedef void (*ZleIntFunc) _((void)); +typedef int (*ZleIntFunc) _((char **)); struct widget { int flags; /* flags (see below) */ @@ -54,16 +54,17 @@ struct widget { } u; }; -#define WIDGET_INT (1<<0) /* widget is internally implemented */ -#define WIDGET_NCOMP (1<<1) /* new style completion widget */ -#define ZLE_MENUCMP (1<<2) /* DON'T invalidate completion list */ +#define WIDGET_INT (1<<0) /* widget is internally implemented */ +#define WIDGET_NCOMP (1<<1) /* new style completion widget */ +#define ZLE_MENUCMP (1<<2) /* DON'T invalidate completion list */ #define ZLE_YANK (1<<3) -#define ZLE_LINEMOVE (1<<4) /* command is a line-oriented movement */ -#define ZLE_LASTCOL (1<<5) /* command maintains lastcol correctly */ +#define ZLE_LINEMOVE (1<<4) /* command is a line-oriented movement */ +#define ZLE_LASTCOL (1<<5) /* command maintains lastcol correctly */ #define ZLE_KILL (1<<6) -#define ZLE_KEEPSUFFIX (1<<7) /* DON'T remove added suffix */ -#define ZLE_NOTCOMMAND (1<<8) /* widget should not alter lastcmd */ -#define ZLE_ISCOMP (1<<9) /* usable for new style completion */ +#define ZLE_KEEPSUFFIX (1<<7) /* DON'T remove added suffix */ +#define ZLE_NOTCOMMAND (1<<8) /* widget should not alter lastcmd */ +#define ZLE_ISCOMP (1<<9) /* usable for new style completion */ + /* thingies */ struct thingy { @@ -142,3 +143,9 @@ typedef struct cutbuffer *Cutbuffer; #define CUTBUFFER_LINE 1 /* for vi: buffer contains whole lines of data */ #define KRINGCT 8 /* number of buffers in the kill ring */ + +/* Convenience macros for the hooks */ + +#define LISTMATCHESHOOK (zlehooks + 0) +#define INSERTMATCHHOOK (zlehooks + 1) +#define MENUSTARTHOOK (zlehooks + 2) diff --git a/Src/Zle/zle_hist.c b/Src/Zle/zle_hist.c index 2fc55e98c..f85fa00a6 100644 --- a/Src/Zle/zle_hist.c +++ b/Src/Zle/zle_hist.c @@ -73,12 +73,13 @@ forget_edits(void) } /**/ -void -uphistory(void) +int +uphistory(char **args) { int nodups = isset(HISTIGNOREDUPS); if (!zle_goto_hist(histline, -zmult, nodups) && isset(HISTBEEP)) - feep(); + return 1; + return 0; } /**/ @@ -116,53 +117,53 @@ upline(void) } /**/ -void -uplineorhistory(void) +int +uplineorhistory(char **args) { int ocs = cs; int n = upline(); if (n) { - int m = zmult; + int m = zmult, ret; cs = ocs; - if (virangeflag || !histallowed) { - feep(); - return; - } + if (virangeflag || !histallowed) + return 1; zmult = n; - uphistory(); + ret = uphistory(args); zmult = m; + return ret; } + return 0; } /**/ -void -viuplineorhistory(void) +int +viuplineorhistory(char **args) { int col = lastcol; - uplineorhistory(); + uplineorhistory(args); lastcol = col; - vifirstnonblank(); + return vifirstnonblank(args); } /**/ -void -uplineorsearch(void) +int +uplineorsearch(char **args) { int ocs = cs; int n = upline(); if (n) { - int m = zmult; + int m = zmult, ret; cs = ocs; - if (virangeflag || !histallowed) { - feep(); - return; - } + if (virangeflag || !histallowed) + return 1; zmult = n; - historysearchbackward(); + ret = historysearchbackward(args); zmult = m; + return ret; } + return 0; } /**/ @@ -200,202 +201,220 @@ downline(void) } /**/ -void -downlineorhistory(void) +int +downlineorhistory(char **args) { int ocs = cs; int n = downline(); if (n) { - int m = zmult; + int m = zmult, ret; cs = ocs; - if (virangeflag || !histallowed) { - feep(); - return; - } + if (virangeflag || !histallowed) + return 1; zmult = n; - downhistory(); + ret = downhistory(args); zmult = m; + return ret; } + return 0; } /**/ -void -vidownlineorhistory(void) +int +vidownlineorhistory(char **args) { int col = lastcol; - downlineorhistory(); + downlineorhistory(args); lastcol = col; - vifirstnonblank(); + return vifirstnonblank(zlenoargs); } /**/ -void -downlineorsearch(void) +int +downlineorsearch(char **args) { int ocs = cs; int n = downline(); if (n) { - int m = zmult; + int m = zmult, ret; cs = ocs; - if (virangeflag || !histallowed) { - feep(); - return; - } + if (virangeflag || !histallowed) + return 1; zmult = n; - historysearchforward(); + ret = historysearchforward(args); zmult = m; + return ret; } + return 0; } /**/ -void -acceptlineanddownhistory(void) +int +acceptlineanddownhistory(char **args) { Histent he; - if (!(he = movehistent(quietgethist(histline), 1, HIST_FOREIGN))) { - feep(); - return; - } + if (!(he = movehistent(quietgethist(histline), 1, HIST_FOREIGN))) + return 1; pushnode(bufstack, ztrdup(ZLETEXT(he))); done = 1; stackhist = he->histnum; + return 0; } /**/ -void -downhistory(void) +int +downhistory(char **args) { int nodups = isset(HISTIGNOREDUPS); if (!zle_goto_hist(histline, zmult, nodups) && isset(HISTBEEP)) - feep(); + return 1; + return 0; } static int histpos, srch_hl, srch_cs = -1; static char *srch_str; /**/ -void -historysearchbackward(void) +int +historysearchbackward(char **args) { Histent he; - int n = zmult; - char *s; + int n = zmult, hp; + char *s, *str; if (zmult < 0) { + int ret; zmult = -n; - historysearchforward(); + ret = historysearchforward(args); zmult = n; - return; + return ret; } - if (histline == curhist || histline != srch_hl || cs != srch_cs || mark != 0 - || memcmp(srch_str, line, histpos) != 0) { - zfree(srch_str, histpos); - for (histpos = 0; histpos < ll && !iblank(line[histpos]); histpos++) ; - if (histpos < ll) - histpos++; - srch_str = zalloc(histpos); - memcpy(srch_str, line, histpos); + if ((str = *args)) + hp = strlen(str); + else { + if (histline == curhist || histline != srch_hl || cs != srch_cs || + mark != 0 || memcmp(srch_str, line, histpos) != 0) { + zfree(srch_str, histpos); + for (histpos = 0; histpos < ll && !iblank(line[histpos]); histpos++) ; + if (histpos < ll) + histpos++; + srch_str = zalloc(histpos); + memcpy(srch_str, line, histpos); + } + str = srch_str; + hp = histpos; } he = quietgethist(histline); while ((he = movehistent(he, -1, hist_skip_flags))) { if (isset(HISTFINDNODUPS) && he->flags & HIST_DUP) continue; s = ZLETEXT(he); - if (metadiffer(s, srch_str, histpos) < 0 && - metadiffer(s, srch_str, ll)) { + if (metadiffer(s, str, hp) < 0 && + (*args || metadiffer(s, str, ll))) { if (--n <= 0) { zle_setline(he); srch_hl = histline; srch_cs = cs; - return; + return 0; } } } - feep(); + return 1; } /**/ -void -historysearchforward(void) +int +historysearchforward(char **args) { Histent he; - int n = zmult; - char *s; + int n = zmult, hp; + char *s, *str; if (zmult < 0) { + int ret; zmult = -n; - historysearchbackward(); + ret = historysearchbackward(args); zmult = n; - return; + return ret; } - if (histline == curhist || histline != srch_hl || cs != srch_cs || mark != 0 - || memcmp(srch_str, line, histpos) != 0) { - zfree(srch_str, histpos); - for (histpos = 0; histpos < ll && !iblank(line[histpos]); histpos++) ; - if (histpos < ll) - histpos++; - srch_str = zalloc(histpos); - memcpy(srch_str, line, histpos); + if ((str = *args)) + hp = strlen(str); + else { + if (histline == curhist || histline != srch_hl || cs != srch_cs || + mark != 0 || memcmp(srch_str, line, histpos) != 0) { + zfree(srch_str, histpos); + for (histpos = 0; histpos < ll && !iblank(line[histpos]); histpos++) ; + if (histpos < ll) + histpos++; + srch_str = zalloc(histpos); + memcpy(srch_str, line, histpos); + } + str = srch_str; + hp = histpos; } he = quietgethist(histline); while ((he = movehistent(he, 1, hist_skip_flags))) { if (isset(HISTFINDNODUPS) && he->flags & HIST_DUP) continue; s = ZLETEXT(he); - if (metadiffer(s, srch_str, histpos) < (he->histnum == curhist) && - metadiffer(s, srch_str, ll)) { + if (metadiffer(s, str, hp) < (he->histnum == curhist) && + (*args || metadiffer(s, str, ll))) { if (--n <= 0) { zle_setline(he); srch_hl = histline; srch_cs = cs; - return; + return 0; } } } - feep(); + return 1; } /**/ -void -beginningofbufferorhistory(void) +int +beginningofbufferorhistory(char **args) { if (findbol()) cs = 0; else - beginningofhistory(); + return beginningofhistory(args); + return 0; } /**/ -void -beginningofhistory(void) +int +beginningofhistory(char **args) { if (!zle_goto_hist(firsthist(), 0, 0) && isset(HISTBEEP)) - feep(); + return 1; + return 0; } /**/ -void -endofbufferorhistory(void) +int +endofbufferorhistory(char **args) { if (findeol() != ll) cs = ll; else - endofhistory(); + return endofhistory(args); + return 0; } /**/ -void -endofhistory(void) +int +endofhistory(char **args) { zle_goto_hist(curhist, 0, 0); + return 0; } /**/ -void -insertlastword(void) +int +insertlastword(char **args) { int n; char *s, *t; @@ -420,19 +439,15 @@ insertlastword(void) zsfree(lastinsert); lastinsert = NULL; } - if (!(he = quietgethist(evhist)) || !he->nwords) { - feep(); - return; - } + if (!(he = quietgethist(evhist)) || !he->nwords) + return 1; if (zmult > 0) { n = he->nwords - (zmult - 1); } else { n = 1 - zmult; } - if (n < 1 || n > he->nwords) { - feep(); - return; - } + if (n < 1 || n > he->nwords) + return 1; s = he->text + he->words[2*n-2]; t = he->text + he->words[2*n-1]; save = *t; @@ -446,6 +461,7 @@ insertlastword(void) doinsert(s); zmult = n; *t = save; + return 0; } /**/ @@ -461,15 +477,15 @@ zle_setline(Histent he) } /**/ -void -setlocalhistory(void) +int +setlocalhistory(char **args) { if (zmod.flags & MOD_MULT) { hist_skip_flags = zmult? HIST_FOREIGN : 0; - } - else { + } else { hist_skip_flags ^= HIST_FOREIGN; } + return 0; } /**/ @@ -489,13 +505,13 @@ zle_goto_hist(int ev, int n, int skipdups) } /**/ -void -pushline(void) +int +pushline(char **args) { int n = zmult; if (n < 0) - return; + return 1; pushnode(bufstack, metafy((char *) line, ll, META_DUP)); while (--n) pushnode(bufstack, ztrdup("")); @@ -503,18 +519,19 @@ pushline(void) *line = '\0'; ll = cs = 0; clearlist = 1; + return 0; } /**/ -void -pushlineoredit(void) +int +pushlineoredit(char **args) { - int ics; + int ics, ret; unsigned char *s; char *hline = hgetline(); if (zmult < 0) - return; + return 1; if (hline && *hline) { ics = ztrlen(hline); sizeline(ics + ll + 1); @@ -524,34 +541,36 @@ pushlineoredit(void) ll += ics; cs += ics; } - pushline(); + ret = pushline(args); if (!isfirstln) errflag = done = 1; clearlist = 1; + return ret; } /**/ -void -pushinput(void) +int +pushinput(char **args) { - int i; + int i, ret; if (zmult < 0) - return; + return 1; zmult += i = !isfirstln; - pushlineoredit(); + ret = pushlineoredit(args); zmult -= i; + return ret; } /**/ -void -getline(void) +int +getline(char **args) { char *s = (char *)getlinknode(bufstack); - if (!s) - feep(); - else { + if (!s) { + return 1; + } else { int cc; unmetafy(s, &cc); @@ -561,20 +580,23 @@ getline(void) free(s); clearlist = 1; } + return 0; } /**/ -void -historyincrementalsearchbackward(void) +int +historyincrementalsearchbackward(char **args) { - doisearch(-1); + doisearch(args, -1); + return 0; } /**/ -void -historyincrementalsearchforward(void) +int +historyincrementalsearchforward(char **args) { - doisearch(1); + doisearch(args, 1); + return 0; } static struct isrch_spot { @@ -642,13 +664,13 @@ get_isrch_spot(int num, int *hlp, int *posp, int *csp, int *lenp, int *dirp, int /**/ static void -doisearch(int dir) +doisearch(char **args, int dir) { char *s, *ibuf = zhalloc(80), *sbuf = ibuf + FIRST_SEARCH_CHAR; int sbptr = 0, top_spot = 0, pos, sibuf = 80; int nomatch = 0, skip_line = 0, skip_pos = 0; int odir = dir, sens = zmult == 1 ? 3 : 1; - int hl = histline; + int hl = histline, savekeys = -1, feep = 0; Thingy cmd; char *okeymap = curkeymapname; static char *previous_search = NULL; @@ -657,6 +679,14 @@ doisearch(int dir) clearlist = 1; + if (*args) { + int len; + char *arg; + savekeys = kungetct; + arg = getkeystring(*args, &len, 2, NULL); + ungetkeys(arg, len); + } + strcpy(ibuf, ISEARCH_PROMPT); memcpy(ibuf + NORM_PROMPT_POS, (dir == 1) ? "fwd" : "bck", 3); remember_edits(); @@ -709,7 +739,7 @@ doisearch(int dir) get_isrch_spot(top_spot, &hl, &pos, &cs, &sbptr, &dir, &nomatch); if (!nomatch) { - feep(); + feep = 1; nomatch = 1; } he = quietgethist(hl); @@ -743,14 +773,14 @@ doisearch(int dir) break; } if(cmd == Th(z_clearscreen)) { - clearscreen(); + clearscreen(zlenoargs); goto ref; } else if(cmd == Th(z_redisplay)) { - redisplay(); + redisplay(zlenoargs); goto ref; } else if(cmd == Th(z_vicmdmode)) { if(selectkeymap(invicmdmode() ? "main" : "vicmd", 0)) - feep(); + feep = 1; goto ref; } else if(cmd == Th(z_vibackwarddeletechar) || cmd == Th(z_backwarddeletechar)) { @@ -758,7 +788,7 @@ doisearch(int dir) get_isrch_spot(--top_spot, &hl, &pos, &cs, &sbptr, &dir, &nomatch); else - feep(); + feep = 1; if (nomatch) { statusline = ibuf; skip_pos = 1; @@ -773,16 +803,16 @@ doisearch(int dir) memcpy(ibuf + NORM_PROMPT_POS, (dir == 1) ? "fwd" : "bck", 3); continue; } else if(cmd == Th(z_acceptandhold)) { - acceptandhold(); + acceptandhold(zlenoargs); break; } else if(cmd == Th(z_acceptandinfernexthistory)) { - acceptandinfernexthistory(); + acceptandinfernexthistory(zlenoargs); break; } else if(cmd == Th(z_acceptlineanddownhistory)) { - acceptlineanddownhistory(); + acceptlineanddownhistory(zlenoargs); break; } else if(cmd == Th(z_acceptline)) { - acceptline(); + acceptline(zlenoargs); break; } else if(cmd == Th(z_historyincrementalsearchbackward)) { set_isrch_spot(top_spot++, hl, pos, cs, sbptr, dir, nomatch); @@ -825,7 +855,7 @@ doisearch(int dir) zrefresh(); } if ((c = getkey(0)) == EOF) - feep(); + feep = 1; else goto ins; } else { @@ -843,7 +873,7 @@ doisearch(int dir) } ins: if (sbptr == PATH_MAX) { - feep(); + feep = 1; continue; } set_isrch_spot(top_spot++, hl, pos, cs, sbptr, dir, nomatch); @@ -854,7 +884,9 @@ doisearch(int dir) } sbuf[sbptr++] = c; } - handlefeep(); + if (feep) + handlefeep(zlenoargs); + feep = 0; } if (sbptr) { zfree(previous_search, previous_search_len); @@ -863,11 +895,17 @@ doisearch(int dir) } statusline = NULL; selectkeymap(okeymap, 1); + /* + * Don't allow unused characters provided as a string to the + * widget to overflow and be used as separated commands. + */ + if (savekeys >= 0 && kungetct > savekeys) + kungetct = savekeys; } /**/ -void -acceptandinfernexthistory(void) +int +acceptandinfernexthistory(char **args) { Histent he; @@ -878,14 +916,15 @@ acceptandinfernexthistory(void) he = movehistent(he, 1, HIST_FOREIGN); pushnode(bufstack, ztrdup(ZLETEXT(he))); stackhist = he->histnum; - return; + return 0; } } + return 1; } /**/ -void -infernexthistory(void) +int +infernexthistory(char **args) { Histent he; @@ -894,28 +933,30 @@ infernexthistory(void) if (!metadiffer(ZLETEXT(he), (char *) line, ll)) { he = movehistent(he, 1, HIST_FOREIGN); zle_setline(he); - return; + return 0; } } - feep(); + return 1; } /**/ -void -vifetchhistory(void) +int +vifetchhistory(char **args) { if (zmult < 0) - return; + return 1; if (histline == curhist) { if (!(zmod.flags & MOD_MULT)) { cs = ll; cs = findbol(); - return; + return 0; } } if (!zle_goto_hist((zmod.flags & MOD_MULT) ? zmult : curhist, 0, 0) && - isset(HISTBEEP)) - feep(); + isset(HISTBEEP)) { + return 1; + } + return 0; } /* the last vi search */ @@ -928,7 +969,7 @@ static int getvisrchstr(void) { char *sbuf = zhalloc(80); - int sptr = 1, ret = 0, ssbuf = 80; + int sptr = 1, ret = 0, ssbuf = 80, feep = 0; Thingy cmd; char *okeymap = curkeymapname; @@ -953,9 +994,9 @@ getvisrchstr(void) cmd = Th(z_selfinsert); } if(cmd == Th(z_redisplay)) { - redisplay(); + redisplay(zlenoargs); } else if(cmd == Th(z_clearscreen)) { - clearscreen(); + clearscreen(zlenoargs); } else if(cmd == Th(z_acceptline) || cmd == Th(z_vicmdmode)) { sbuf[sptr] = 0; @@ -981,7 +1022,7 @@ getvisrchstr(void) zrefresh(); } if ((c = getkey(0)) == EOF) - feep(); + feep = 1; else goto ins; } else if(cmd == Th(z_selfinsertunmeta) || cmd == Th(z_selfinsert)) { @@ -998,9 +1039,11 @@ getvisrchstr(void) } sbuf[sptr++] = c; } else { - feep(); + feep = 1; } - handlefeep(); + if (feep) + handlefeep(zlenoargs); + feep = 0; } statusline = NULL; selectkeymap(okeymap, 1); @@ -1008,36 +1051,58 @@ getvisrchstr(void) } /**/ -void -vihistorysearchforward(void) +int +vihistorysearchforward(char **args) { + if (*args) { + int ose = visrchsense, ret; + char *ost = visrchstr; + + visrchsense = 1; + visrchstr = *args; + ret = virepeatsearch(zlenoargs); + visrchsense = ose; + visrchstr = ost; + return ret; + } visrchsense = 1; if (getvisrchstr()) - virepeatsearch(); + return virepeatsearch(zlenoargs); + return 1; } /**/ -void -vihistorysearchbackward(void) +int +vihistorysearchbackward(char **args) { + if (*args) { + int ose = visrchsense, ret; + char *ost = visrchstr; + + visrchsense = -1; + visrchstr = *args; + ret = virepeatsearch(zlenoargs); + visrchsense = ose; + visrchstr = ost; + return ret; + } visrchsense = -1; if (getvisrchstr()) - virepeatsearch(); + return virepeatsearch(zlenoargs); + return 1; } /**/ -void -virepeatsearch(void) +int +virepeatsearch(char **args) { Histent he; int t0; int n = zmult; char *s; - if (!visrchstr) { - feep(); - return; - } + if (!visrchstr) + return 1; if (zmult < 0) { n = -n; visrchsense = -visrchsense; @@ -1053,20 +1118,22 @@ virepeatsearch(void) : hstrnstr(s, 0, visrchstr, t0, 1, 1) != 0)) { if (--n <= 0) { zle_setline(he); - return; + return 0; } } } - feep(); + return 1; } /**/ -void -virevrepeatsearch(void) +int +virevrepeatsearch(char **args) { + int ret; visrchsense = -visrchsense; - virepeatsearch(); + ret = virepeatsearch(args); visrchsense = -visrchsense; + return ret; } /* Extra function added by A.R. Iano-Fletcher. */ @@ -1074,8 +1141,8 @@ virevrepeatsearch(void) /* history-beginning-search-backward */ /**/ -void -historybeginningsearchbackward(void) +int +historybeginningsearchbackward(char **args) { Histent he; int cpos = cs; /* save cursor position */ @@ -1083,10 +1150,11 @@ historybeginningsearchbackward(void) char *s; if (zmult < 0) { + int ret; zmult = -n; - historybeginningsearchforward(); + ret = historybeginningsearchforward(args); zmult = n; - return; + return ret; } he = quietgethist(histline); while ((he = movehistent(he, -1, hist_skip_flags))) { @@ -1098,19 +1166,19 @@ historybeginningsearchbackward(void) if (--n <= 0) { zle_setline(he); cs = cpos; - return; + return 0; } } } - feep(); + return 1; } /* Extra function added by A.R. Iano-Fletcher. */ /* history-beginning-search-forward */ /**/ -void -historybeginningsearchforward(void) +int +historybeginningsearchforward(char **args) { Histent he; int cpos = cs; /* save cursor position */ @@ -1118,10 +1186,11 @@ historybeginningsearchforward(void) char *s; if (zmult < 0) { + int ret; zmult = -n; - historybeginningsearchbackward(); + ret = historybeginningsearchbackward(args); zmult = n; - return; + return ret; } he = quietgethist(histline); while ((he = movehistent(he, 1, hist_skip_flags))) { @@ -1133,9 +1202,9 @@ historybeginningsearchforward(void) if (--n <= 0) { zle_setline(he); cs = cpos; - return; + return 0; } } } - feep(); + return 1; } diff --git a/Src/Zle/zle_keymap.c b/Src/Zle/zle_keymap.c index 7504ed809..28bc96b64 100644 --- a/Src/Zle/zle_keymap.c +++ b/Src/Zle/zle_keymap.c @@ -98,7 +98,7 @@ struct bindstate { /* currently selected keymap, and its name */ /**/ -Keymap curkeymap; +Keymap curkeymap, localkeymap; /**/ char *curkeymapname; @@ -216,7 +216,7 @@ freekeynode(HashNode hn) static HashTable copyto; /**/ -static Keymap +Keymap newkeymap(Keymap tocopy, char *kmname) { Keymap km = zcalloc(sizeof(*km)); @@ -250,7 +250,7 @@ scancopykeys(HashNode hn, int flags) } /**/ -static void +void deletekeymap(Keymap km) { int i; @@ -322,21 +322,21 @@ openkeymap(char *name) } /**/ -static int -unlinkkeymap(char *name) +int +unlinkkeymap(char *name, int ignm) { KeymapName n = (KeymapName) keymapnamtab->getnode(keymapnamtab, name); if(!n) return 2; - if(n->flags & KMN_IMMORTAL) + if(!ignm && (n->flags & KMN_IMMORTAL)) return 1; keymapnamtab->freenode(keymapnamtab->removenode(keymapnamtab, name)); return 0; } /**/ -static int -linkkeymap(Keymap km, char *name) +int +linkkeymap(Keymap km, char *name, int imm) { KeymapName n = (KeymapName) keymapnamtab->getnode(keymapnamtab, name); if(n) { @@ -347,9 +347,12 @@ linkkeymap(Keymap km, char *name) if(!--n->keymap->rc) deletekeymap(n->keymap); n->keymap = km; - } else - keymapnamtab->addnode(keymapnamtab, ztrdup(name), - makekeymapnamnode(km)); + } else { + n = makekeymapnamnode(km); + if (imm) + n->flags |= KMN_IMMORTAL; + keymapnamtab->addnode(keymapnamtab, ztrdup(name), n); + } km->rc++; return 0; } @@ -379,6 +382,15 @@ selectkeymap(char *name, int fb) return 0; } +/* Select a local key map. */ + +/**/ +void +selectlocalmap(Keymap m) +{ + localkeymap = m; +} + /* Reopen the currently selected keymap, in case it got deleted. This * * should be called after doing anything that might have run an * * arbitrary user-specified command. */ @@ -642,7 +654,7 @@ bin_bindkey(char *name, char **argv, char *ops, int func) return 1; } if(ops['e'] || ops['v']) - linkkeymap(km, "main"); + linkkeymap(km, "main", 0); } else { kmname = NULL; km = NULL; @@ -715,7 +727,7 @@ bin_bindkey_del(char *name, char *kmname, Keymap km, char **argv, char *ops, cha int ret = 0; do { - int r = unlinkkeymap(*argv); + int r = unlinkkeymap(*argv, 0); if(r == 1) zwarnnam(name, "keymap name `%s' is protected", *argv, 0); else if(r == 2) @@ -735,7 +747,7 @@ bin_bindkey_link(char *name, char *kmname, Keymap km, char **argv, char *ops, ch if(!km) { zwarnnam(name, "no such keymap `%s'", argv[0], 0); return 1; - } else if(linkkeymap(km, argv[1])) { + } else if(linkkeymap(km, argv[1], 0)) { zwarnnam(name, "keymap name `%s' is protected", argv[1], 0); return 1; } @@ -762,7 +774,7 @@ bin_bindkey_new(char *name, char *kmname, Keymap km, char **argv, char *ops, cha } } else km = NULL; - linkkeymap(newkeymap(km, argv[0]), argv[0]); + linkkeymap(newkeymap(km, argv[0]), argv[0], 0); return 0; } @@ -1108,20 +1120,18 @@ default_bindings(void) * will be linked to the "emacs" keymap, except that if VISUAL * * or EDITOR contain the string "vi" then it will be linked to * * the "viins" keymap. */ - linkkeymap(vmap, "viins"); - linkkeymap(emap, "emacs"); - linkkeymap(amap, "vicmd"); - linkkeymap(smap, ".safe"); + linkkeymap(vmap, "viins", 0); + linkkeymap(emap, "emacs", 0); + linkkeymap(amap, "vicmd", 0); + linkkeymap(smap, ".safe", 1); if (((ed = zgetenv("VISUAL")) && strstr(ed, "vi")) || ((ed = zgetenv("EDITOR")) && strstr(ed, "vi"))) - linkkeymap(vmap, "main"); + linkkeymap(vmap, "main", 0); else - linkkeymap(emap, "main"); + linkkeymap(emap, "main", 0); /* the .safe map cannot be modified or deleted */ smap->flags |= KM_IMMUTABLE; - ((KeymapName) keymapnamtab->getnode(keymapnamtab, ".safe"))->flags - |= KMN_IMMORTAL; } /*************************/ @@ -1142,7 +1152,12 @@ getkeymapcmd(Keymap km, Thingy *funcp, char **strp) keybuf[0] = 0; while((c = getkeybuf(!!lastlen)) != EOF) { char *s; - Thingy f = keybind(km, keybuf, &s); + Thingy f; + int loc = 1; + + if (!localkeymap || + (f = keybind(localkeymap, keybuf, &s)) == t_undefinedkey) + loc = 0, f = keybind(km, keybuf, &s); if(f != t_undefinedkey) { lastlen = keybuflen; @@ -1150,7 +1165,7 @@ getkeymapcmd(Keymap km, Thingy *funcp, char **strp) str = s; lastc = c; } - if(!keyisprefix(km, keybuf)) + if(!keyisprefix((loc ? localkeymap : km), keybuf)) break; } if(!lastlen && keybuflen) diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index 13f3cc402..8f6dfdf75 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -106,10 +106,12 @@ struct modifier zmod; /**/ int prefixflag; -/* != 0 if there is a pending beep (usually indicating an error) */ +/* Number of characters waiting to be read by the ungetkeys mechanism */ +/**/ +int kungetct; /**/ -int feepflag; +char *zlenoargs[1] = { NULL }; #ifdef FIONREAD static int delayzsetterm; @@ -262,7 +264,7 @@ zsetterm(void) } static char *kungetbuf; -static int kungetct, kungetsz; +static int kungetsz; /**/ void @@ -499,6 +501,7 @@ zleread(char *lp, char *rp, int flags) viinsbegin = 0; statusline = NULL; selectkeymap("main", 1); + selectlocalmap(NULL); fixsuffix(); if ((s = (unsigned char *)getlinknode(bufstack))) { setline((char *)s); @@ -527,20 +530,21 @@ zleread(char *lp, char *rp, int flags) lastcol = -1; initmodifier(&zmod); prefixflag = 0; - feepflag = 0; zrefresh(); while (!done && !errflag) { statusline = NULL; vilinerange = 0; reselectkeymap(); + selectlocalmap(NULL); bindk = getkeycmd(); if (!ll && isfirstln && c == eofchar) { eofsent = 1; break; } if (bindk) { - execzlefunc(bindk); + if (execzlefunc(bindk, zlenoargs)) + handlefeep(zlenoargs); handleprefixes(); /* for vi mode, make sure the cursor isn't somewhere illegal */ if (invicmdmode() && cs > findbol() && @@ -565,7 +569,6 @@ zleread(char *lp, char *rp, int flags) #endif if (!kungetct) zrefresh(); - handlefeep(); } statusline = NULL; invalidatelist(); @@ -591,10 +594,10 @@ zleread(char *lp, char *rp, int flags) /* execute a widget */ /**/ -void -execzlefunc(Thingy func) +int +execzlefunc(Thingy func, char **args) { - int r = 0; + int r = 0, ret = 0; Widget w; if(func->flags & DISABLED) { @@ -605,7 +608,7 @@ execzlefunc(Thingy func) zsfree(nm); showmsg(msg); zsfree(msg); - feep(); + ret = 1; } else if((w = func->widget)->flags & (WIDGET_INT|WIDGET_NCOMP)) { int wflags = w->flags; @@ -621,9 +624,9 @@ execzlefunc(Thingy func) lastcol = -1; if (wflags & WIDGET_NCOMP) { compwidget = w; - completecall(); + ret = completecall(args); } else - w->u.fn(); + ret = w->u.fn(args); if (!(wflags & ZLE_NOTCOMMAND)) lastcmd = wflags; r = 1; @@ -638,14 +641,23 @@ execzlefunc(Thingy func) zsfree(nm); showmsg(msg); zsfree(msg); - feep(); + ret = 1; } else { - int osc = sfcontext, osi = movefd(0); - + int osc = sfcontext, osi = movefd(0), olv = lastval; + LinkList largs = NULL; + + if (*args) { + largs = newlinklist(); + addlinknode(largs, dupstring(w->u.fnnam)); + while (*args) + addlinknode(largs, dupstring(*args++)); + } startparamscope(); makezleparams(0); sfcontext = SFC_WIDGET; - doshfunc(w->u.fnnam, l, NULL, 0, 1); + doshfunc(w->u.fnnam, l, largs, 0, 0); + ret = lastval; + lastval = olv; sfcontext = osc; endparamscope(); lastcmd = 0; @@ -658,6 +670,7 @@ execzlefunc(Thingy func) refthingy(func); lbindk = func; } + return ret; } /* initialise command modifiers */ @@ -826,14 +839,14 @@ bin_vared(char *name, char **args, char *ops, int func) } /**/ -void -describekeybriefly(void) +int +describekeybriefly(char **args) { char *seq, *str, *msg, *is; Thingy func; if (statusline) - return; + return 1; clearlist = 1; statusline = "Describe key briefly: _"; statusll = strlen(statusline); @@ -841,7 +854,7 @@ describekeybriefly(void) seq = getkeymapcmd(curkeymap, &func, &str); statusline = NULL; if(!*seq) - return; + return 1; msg = bindztrdup(seq); msg = appstr(msg, " is "); if (!func) @@ -852,6 +865,7 @@ describekeybriefly(void) zsfree(is); showmsg(msg); zsfree(msg); + return 0; } #define MAXFOUND 4 @@ -882,13 +896,13 @@ scanfindfunc(char *seq, Thingy func, char *str, void *magic) } /**/ -void -whereis(void) +int +whereis(char **args) { struct findfunc ff; if (!(ff.func = executenamedcommand("Where is: "))) - return; + return 1; ff.found = 0; ff.msg = niceztrdup(ff.func->nam); scankeymap(curkeymap, 1, scanfindfunc, &ff); @@ -898,6 +912,7 @@ whereis(void) ff.msg = appstr(ff.msg, " et al"); showmsg(ff.msg); zsfree(ff.msg); + return 0; } /**/ @@ -933,7 +948,17 @@ trashzle(void) static struct builtin bintab[] = { BUILTIN("bindkey", 0, bin_bindkey, 0, -1, 0, "evaMldDANmrsLR", NULL), BUILTIN("vared", 0, bin_vared, 1, 7, 0, NULL, NULL), - BUILTIN("zle", 0, bin_zle, 0, -1, 0, "lDANCLmMgGc", NULL), + BUILTIN("zle", 0, bin_zle, 0, -1, 0, "lDANCLmMgGcRa", NULL), +}; + +/* The order of the entries in this table has to match the *HOOK + * macros in zle.h */ + +/**/ +struct hookdef zlehooks[] = { + HOOKDEF("list_matches", ilistmatches, 0), + HOOKDEF("insert_match", NULL, HOOKF_ALL), + HOOKDEF("menu_start", NULL, HOOKF_ALL), }; /**/ @@ -955,6 +980,8 @@ setup_zle(Module m) unambig_dataptr = unambig_data; set_comp_sepptr = set_comp_sep; + getkeyptr = getkey; + /* initialise the thingies */ init_thingies(); lbindk = NULL; @@ -977,6 +1004,7 @@ int boot_zle(Module m) { addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); + addhookdefs(m->nam, zlehooks, sizeof(zlehooks)/sizeof(*zlehooks)); return 0; } @@ -992,6 +1020,7 @@ cleanup_zle(Module m) return 1; } deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); + deletehookdefs(m->nam, zlehooks, sizeof(zlehooks)/sizeof(*zlehooks)); return 0; } @@ -1031,6 +1060,8 @@ finish_zle(Module m) unambig_dataptr = NULL; set_comp_sepptr = NULL; + getkeyptr = NULL; + return 0; } diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c index e2ccfbc46..a51cdf92e 100644 --- a/Src/Zle/zle_misc.c +++ b/Src/Zle/zle_misc.c @@ -57,8 +57,8 @@ doinsert(char *str) } /**/ -void -selfinsert(void) +int +selfinsert(char **args) { char s[3], *p = s; @@ -69,56 +69,61 @@ selfinsert(void) *p++ = c; *p = 0; doinsert(s); + return 0; } /**/ -void -selfinsertunmeta(void) +int +selfinsertunmeta(char **args) { c &= 0x7f; if (c == '\r') c = '\n'; - selfinsert(); + return selfinsert(args); } /**/ -void -deletechar(void) +int +deletechar(char **args) { if (zmult < 0) { + int ret; zmult = -zmult; - backwarddeletechar(); + ret = backwarddeletechar(args); zmult = -zmult; - return; + return ret; } if (cs + zmult <= ll) { cs += zmult; backdel(zmult); - } else - feep(); + return 0; + } + return 1; } /**/ -void -backwarddeletechar(void) +int +backwarddeletechar(char **args) { if (zmult < 0) { + int ret; zmult = -zmult; - deletechar(); + ret = deletechar(args); zmult = -zmult; - return; + return ret; } backdel(zmult > cs ? cs : zmult); + return 0; } /**/ -void -killwholeline(void) +int +killwholeline(char **args) { int i, fg, n = zmult; if (n < 0) - return; + return 1; while (n--) { if ((fg = (cs && cs == ll))) cs--; @@ -128,28 +133,31 @@ killwholeline(void) forekill(i - cs + (i != ll), fg); } clearlist = 1; + return 0; } /**/ -void -killbuffer(void) +int +killbuffer(char **args) { cs = 0; forekill(ll, 0); clearlist = 1; + return 0; } /**/ -void -backwardkillline(void) +int +backwardkillline(char **args) { int i = 0, n = zmult; if (n < 0) { + int ret; zmult = -n; - killline(); + ret = killline(args); zmult = n; - return; + return ret; } while (n--) { if (cs && line[cs - 1] == '\n') @@ -160,11 +168,12 @@ backwardkillline(void) } forekill(i, 1); clearlist = 1; + return 0; } /**/ -void -gosmacstransposechars(void) +int +gosmacstransposechars(char **args) { int cc; @@ -172,19 +181,19 @@ gosmacstransposechars(void) if (cs == ll || line[cs] == '\n' || ((cs + 1 == ll || line[cs + 1] == '\n') && (!cs || line[cs - 1] == '\n'))) { - feep(); - return; + return 1; } cs += (cs == 0 || line[cs - 1] == '\n') ? 2 : 1; } cc = line[cs - 2]; line[cs - 2] = line[cs - 1]; line[cs - 1] = cc; + return 0; } /**/ -void -transposechars(void) +int +transposechars(char **args) { int cc, ct; int n = zmult; @@ -194,10 +203,8 @@ transposechars(void) n = -n; while (n--) { if (!(ct = cs) || line[cs - 1] == '\n') { - if (ll == cs || line[cs] == '\n') { - feep(); - return; - } + if (ll == cs || line[cs] == '\n') + return 1; if (!neg) cs++; ct++; @@ -214,29 +221,28 @@ transposechars(void) } if (ct == ll || line[ct] == '\n') ct--; - if (ct < 1 || line[ct - 1] == '\n') { - feep(); - return; - } + if (ct < 1 || line[ct - 1] == '\n') + return 1; cc = line[ct - 1]; line[ct - 1] = line[ct]; line[ct] = cc; } + return 0; } /**/ -void -poundinsert(void) +int +poundinsert(char **args) { cs = 0; - vifirstnonblank(); + vifirstnonblank(zlenoargs); if (line[cs] != '#') { spaceinline(1); line[cs] = '#'; cs = findeol(); while(cs != ll) { cs++; - vifirstnonblank(); + vifirstnonblank(zlenoargs); spaceinline(1); line[cs] = '#'; cs = findeol(); @@ -246,42 +252,46 @@ poundinsert(void) cs = findeol(); while(cs != ll) { cs++; - vifirstnonblank(); + vifirstnonblank(zlenoargs); if(line[cs] == '#') foredel(1); cs = findeol(); } } done = 1; + return 0; } /**/ -void -acceptline(void) +int +acceptline(char **args) { done = 1; + return 0; } /**/ -void -acceptandhold(void) +int +acceptandhold(char **args) { pushnode(bufstack, metafy((char *)line, ll, META_DUP)); stackcs = cs; done = 1; + return 0; } /**/ -void -killline(void) +int +killline(char **args) { int i = 0, n = zmult; if (n < 0) { + int ret; zmult = -n; - backwardkillline(); + ret = backwardkillline(args); zmult = n; - return; + return ret; } while (n--) { if (line[cs] == '\n') @@ -292,11 +302,12 @@ killline(void) } backkill(i, 0); clearlist = 1; + return 0; } /**/ -void -killregion(void) +int +killregion(char **args) { if (mark > ll) mark = ll; @@ -304,11 +315,12 @@ killregion(void) forekill(mark - cs, 0); else backkill(cs - mark, 1); + return 0; } /**/ -void -copyregionaskill(void) +int +copyregionaskill(char **args) { if (mark > ll) mark = ll; @@ -316,25 +328,24 @@ copyregionaskill(void) cut(cs, mark - cs, 0); else cut(mark, cs - mark, 1); + return 0; } static int kct, yankb, yanke; /**/ -void -yank(void) +int +yank(char **args) { Cutbuffer buf = &cutbuf; int n = zmult; if (n < 0) - return; + return 1; if (zmod.flags & MOD_VIBUF) buf = &vibuf[zmod.vibuf]; - if (!buf->buf) { - feep(); - return; - } + if (!buf->buf) + return 1; mark = cs; yankb = cs; while (n--) { @@ -344,18 +355,17 @@ yank(void) cs += buf->len; yanke = cs; } + return 0; } /**/ -void -yankpop(void) +int +yankpop(char **args) { int cc; - if (!(lastcmd & ZLE_YANK) || !kring[kct].buf) { - feep(); - return; - } + if (!(lastcmd & ZLE_YANK) || !kring[kct].buf) + return 1; cs = yankb; foredel(yanke - yankb); cc = kring[kct].len; @@ -364,17 +374,20 @@ yankpop(void) cs += cc; yanke = cs; kct = (kct + KRINGCT - 1) % KRINGCT; + return 0; } /**/ -void -overwritemode(void) +int +overwritemode(char **args) { insmode ^= 1; + return 0; } + /**/ -void -whatcursorposition(void) +int +whatcursorposition(char **args) { char msg[100]; char *s = msg; @@ -408,18 +421,19 @@ whatcursorposition(void) sprintf(s, " point %d of %d(%d%%) column %d", cs+1, ll+1, ll ? 100 * cs / ll : 0, cs - bol); showmsg(msg); + return 0; } /**/ -void -undefinedkey(void) +int +undefinedkey(char **args) { - feep(); + return 1; } /**/ -void -quotedinsert(void) +int +quotedinsert(char **args) { #ifndef HAS_TIO struct sgttyb sob; @@ -433,17 +447,20 @@ quotedinsert(void) zsetterm(); #endif if (c < 0) - feep(); + return 1; else - selfinsert(); + return selfinsert(args); } /**/ -void -digitargument(void) +int +digitargument(char **args) { int sign = (zmult < 0) ? -1 : 1; + if (c < '0' || c > '9') + return 1; + if (!(zmod.flags & MOD_TMULT)) zmod.tmult = 0; if (zmod.flags & MOD_NEG) { @@ -455,26 +472,31 @@ digitargument(void) zmod.tmult = zmod.tmult * 10 + sign * (c & 0xf); zmod.flags |= MOD_TMULT; prefixflag = 1; + return 0; } /**/ -void -negargument(void) +int +negargument(char **args) { - if(zmod.flags & MOD_TMULT) { - feep(); - return; - } + if (zmod.flags & MOD_TMULT) + return 1; zmod.tmult = -1; zmod.flags |= MOD_TMULT|MOD_NEG; prefixflag = 1; + return 0; } /**/ -void -universalargument(void) +int +universalargument(char **args) { int digcnt = 0, pref = 0, minus = 1, gotk; + if (*args) { + zmod.mult = atoi(*args); + zmod.flags |= MOD_MULT; + return 0; + } while ((gotk = getkey(0)) != EOF) { if (gotk == '-' && !digcnt) { minus = -1; @@ -493,11 +515,12 @@ universalargument(void) zmod.tmult *= 4; zmod.flags |= MOD_TMULT; prefixflag = 1; + return 0; } /**/ -void -copyprevword(void) +int +copyprevword(char **args) { int len, t0; @@ -513,18 +536,20 @@ copyprevword(void) spaceinline(len); memcpy((char *)&line[cs], (char *)&line[t0], len); cs += len; + return 0; } /**/ -void -sendbreak(void) +int +sendbreak(char **args) { errflag = 1; + return 1; } /**/ -void -quoteregion(void) +int +quoteregion(char **args) { char *str; size_t len; @@ -544,11 +569,12 @@ quoteregion(void) memcpy((char *)&line[cs], str, len); mark = cs; cs += len; + return 0; } /**/ -void -quoteline(void) +int +quoteline(char **args) { char *str; size_t len = ll; @@ -557,6 +583,7 @@ quoteline(void) sizeline(len); memcpy(line, str, len); cs = ll = len; + return 0; } /**/ @@ -612,7 +639,7 @@ Thingy executenamedcommand(char *prmt) { Thingy cmd; - int len, l = strlen(prmt), ols = listshown; + int len, l = strlen(prmt), ols = listshown, feep = 0; char *ptr; char *okeymap = curkeymapname; @@ -637,20 +664,20 @@ executenamedcommand(char *prmt) return NULL; } if(cmd == Th(z_clearscreen)) { - clearscreen(); + clearscreen(zlenoargs); } else if(cmd == Th(z_redisplay)) { - redisplay(); + redisplay(zlenoargs); } else if(cmd == Th(z_viquotedinsert)) { *ptr = '^'; zrefresh(); c = getkey(0); if(c == EOF || !c || len == NAMLEN) - feep(); + feep = 1; else *ptr++ = c, len++; } else if(cmd == Th(z_quotedinsert)) { if((c = getkey(0)) == EOF || !c || len == NAMLEN) - feep(); + feep = 1; else *ptr++ = c, len++; } else if(cmd == Th(z_backwarddeletechar) || @@ -701,7 +728,7 @@ executenamedcommand(char *prmt) scanhashtable(thingytab, 1, 0, DISABLED, scancompcmd, 0); } LASTALLOC; if (empty(cmdll)) - feep(); + feep = 1; else if (cmd == Th(z_listchoices) || cmd == Th(z_deletecharorlist)) { int zmultsav = zmult; @@ -723,7 +750,7 @@ executenamedcommand(char *prmt) !(isset(LISTAMBIGUOUS) && cmdambig > len)) { int zmultsav = zmult; if (isset(LISTBEEP)) - feep(); + feep = 1; statusll = l + cmdambig + 1; zmult = 1; listlist(cmdll); @@ -733,12 +760,14 @@ executenamedcommand(char *prmt) } } else { if (len == NAMLEN || icntrl(c) || cmd != Th(z_selfinsert)) - feep(); + feep = 1; else *ptr++ = c, len++; } } - handlefeep(); + if (feep) + handlefeep(zlenoargs); + feep = 0; } } diff --git a/Src/Zle/zle_move.c b/Src/Zle/zle_move.c index aec1c1767..9189218f1 100644 --- a/Src/Zle/zle_move.c +++ b/Src/Zle/zle_move.c @@ -33,64 +33,69 @@ static int vimarkcs[27], vimarkline[27]; /**/ -void -beginningofline(void) +int +beginningofline(char **args) { int n = zmult; if (n < 0) { + int ret; zmult = -n; - endofline(); + ret = endofline(args); zmult = n; - return; + return ret; } while (n--) { if (cs == 0) - return; + return 0; if (line[cs - 1] == '\n') if (!--cs) - return; + return 0; while (cs && line[cs - 1] != '\n') cs--; } + return 0; } /**/ -void -endofline(void) +int +endofline(char **args) { int n = zmult; if (n < 0) { + int ret; zmult = -n; - beginningofline(); + ret = beginningofline(args); zmult = n; - return; + return ret; } while (n--) { if (cs >= ll) { cs = ll; - return; + return 0; } if (line[cs] == '\n') if (++cs == ll) - return; + return 0; while (cs != ll && line[cs] != '\n') cs++; } + return 0; } /**/ -void -beginningoflinehist(void) +int +beginningoflinehist(char **args) { int n = zmult; if (n < 0) { + int ret; zmult = -n; - endoflinehist(); + ret = endoflinehist(args); zmult = n; - return; + return ret; } while (n) { if (cs == 0) @@ -103,26 +108,29 @@ beginningoflinehist(void) n--; } if (n) { - int m = zmult; + int m = zmult, ret; zmult = n; - uphistory(); + ret = uphistory(args); zmult = m; cs = 0; + return ret; } + return 0; } /**/ -void -endoflinehist(void) +int +endoflinehist(char **args) { int n = zmult; if (n < 0) { + int ret; zmult = -n; - beginningoflinehist(); + ret = beginningoflinehist(args); zmult = n; - return; + return ret; } while (n) { if (cs >= ll) { @@ -137,46 +145,51 @@ endoflinehist(void) n--; } if (n) { - int m = zmult; + int m = zmult, ret; zmult = n; - downhistory(); + ret = downhistory(args); zmult = m; + return ret; } + return 0; } /**/ -void -forwardchar(void) +int +forwardchar(char **args) { cs += zmult; if (cs > ll) cs = ll; if (cs < 0) cs = 0; + return 0; } /**/ -void -backwardchar(void) +int +backwardchar(char **args) { cs -= zmult; if (cs > ll) cs = ll; if (cs < 0) cs = 0; + return 0; } /**/ -void -setmarkcommand(void) +int +setmarkcommand(char **args) { mark = cs; + return 0; } /**/ -void -exchangepointandmark(void) +int +exchangepointandmark(char **args) { int x; @@ -185,11 +198,12 @@ exchangepointandmark(void) cs = x; if (cs > ll) cs = ll; + return 0; } /**/ -void -vigotocolumn(void) +int +vigotocolumn(char **args) { int x, y; @@ -202,20 +216,20 @@ vigotocolumn(void) cs = y; if (cs < x) cs = x; + return 0; } /**/ -void -vimatchbracket(void) +int +vimatchbracket(char **args) { int ocs = cs, dir, ct; unsigned char oth, me; otog: if (cs == ll || line[cs] == '\n') { - feep(); cs = ocs; - return; + return 1; } switch (me = line[cs]) { case '{': @@ -258,49 +272,49 @@ vimatchbracket(void) ct++; } if (cs < 0 || cs >= ll) { - feep(); cs = ocs; + return 1; } else if(dir > 0 && virangeflag) cs++; + return 0; } /**/ -void -viforwardchar(void) +int +viforwardchar(char **args) { int lim = findeol() - invicmdmode(); int n = zmult; if (n < 0) { + int ret; zmult = -n; - vibackwardchar(); + ret = vibackwardchar(args); zmult = n; - return; - } - if (cs >= lim) { - feep(); - return; + return ret; } + if (cs >= lim) + return 1; while (n-- && cs < lim) cs++; + return 0; } /**/ -void -vibackwardchar(void) +int +vibackwardchar(char **args) { int n = zmult; if (n < 0) { + int ret; zmult = -n; - viforwardchar(); + ret = viforwardchar(args); zmult = n; - return; - } - if (cs == findbol()) { - feep(); - return; + return ret; } + if (cs == findbol()) + return 1; while (n--) { cs--; if (cs < 0 || line[cs] == '\n') { @@ -308,157 +322,163 @@ vibackwardchar(void) break; } } + return 0; } /**/ -void -viendofline(void) +int +viendofline(char **args) { int oldcs = cs, n = zmult; - if (n < 1) { - feep(); - return; - } + if (n < 1) + return 1; while(n--) { if (cs > ll) { cs = oldcs; - feep(); - return; + return 1; } cs = findeol() + 1; } cs--; lastcol = 1<<30; + return 0; } /**/ -void -vibeginningofline(void) +int +vibeginningofline(char **args) { cs = findbol(); + return 0; } static int vfindchar, vfinddir, tailadd; /**/ -void -vifindnextchar(void) +int +vifindnextchar(char **args) { if ((vfindchar = vigetkey()) != -1) { vfinddir = 1; tailadd = 0; - virepeatfind(); + return virepeatfind(args); } + return 1; } /**/ -void -vifindprevchar(void) +int +vifindprevchar(char **args) { if ((vfindchar = vigetkey()) != -1) { vfinddir = -1; tailadd = 0; - virepeatfind(); + return virepeatfind(args); } + return 1; } /**/ -void -vifindnextcharskip(void) +int +vifindnextcharskip(char **args) { if ((vfindchar = vigetkey()) != -1) { vfinddir = 1; tailadd = -1; - virepeatfind(); + return virepeatfind(args); } + return 1; } /**/ -void -vifindprevcharskip(void) +int +vifindprevcharskip(char **args) { if ((vfindchar = vigetkey()) != -1) { vfinddir = -1; tailadd = 1; - virepeatfind(); + return virepeatfind(args); } + return 1; } /**/ -void -virepeatfind(void) +int +virepeatfind(char **args) { int ocs = cs, n = zmult; - if (!vfinddir) { - feep(); - return; - } + if (!vfinddir) + return 1; if (n < 0) { + int ret; zmult = -n; - virevrepeatfind(); + ret = virevrepeatfind(args); zmult = n; - return; + return ret; } while (n--) { do cs += vfinddir; while (cs >= 0 && cs < ll && line[cs] != vfindchar && line[cs] != '\n'); if (cs < 0 || cs >= ll || line[cs] == '\n') { - feep(); cs = ocs; - return; + return 1; } } cs += tailadd; if (vfinddir == 1 && virangeflag) cs++; + return 0; } /**/ -void -virevrepeatfind(void) +int +virevrepeatfind(char **args) { + int ret; + if (zmult < 0) { zmult = -zmult; - virepeatfind(); + ret = virepeatfind(args); zmult = -zmult; - return; + return ret; } vfinddir = -vfinddir; - virepeatfind(); + ret = virepeatfind(args); vfinddir = -vfinddir; + return ret; } /**/ -void -vifirstnonblank(void) +int +vifirstnonblank(char **args) { cs = findbol(); while (cs != ll && iblank(line[cs])) cs++; + return 0; } /**/ -void -visetmark(void) +int +visetmark(char **args) { int ch; ch = getkey(0); - if (ch < 'a' || ch > 'z') { - feep(); - return; - } + if (ch < 'a' || ch > 'z') + return 1; ch -= 'a'; vimarkcs[ch] = cs; vimarkline[ch] = histline; + return 0; } /**/ -void -vigotomark(void) +int +vigotomark(char **args) { int ch; @@ -466,30 +486,26 @@ vigotomark(void) if (ch == c) ch = 26; else { - if (ch < 'a' || ch > 'z') { - feep(); - return; - } + if (ch < 'a' || ch > 'z') + return 1; ch -= 'a'; } - if (!vimarkline[ch]) { - feep(); - return; - } + if (!vimarkline[ch]) + return 1; if (curhist != vimarkline[ch] && !zle_goto_hist(vimarkline[ch], 0, 0)) { vimarkline[ch] = 0; - feep(); - return; + return 1; } cs = vimarkcs[ch]; if (cs > ll) cs = ll; + return 0; } /**/ -void -vigotomarkline(void) +int +vigotomarkline(char **args) { - vigotomark(); - vifirstnonblank(); + vigotomark(args); + return vifirstnonblank(zlenoargs); } diff --git a/Src/Zle/zle_params.c b/Src/Zle/zle_params.c index 5c4feef50..bac399e7d 100644 --- a/Src/Zle/zle_params.c +++ b/Src/Zle/zle_params.c @@ -69,8 +69,8 @@ static struct zleparam { zleunsetfn, NULL }, { "keys", PM_ARRAY | PM_READONLY, NULL, FN(get_keys), zleunsetfn, NULL }, - { "NUMERIC", PM_INTEGER, FN(set_numeric), FN(get_numeric), - zleunsetfn, NULL }, + { "NUMERIC", PM_INTEGER | PM_UNSET, FN(set_numeric), FN(get_numeric), + unset_numeric, NULL }, { "HISTNO", PM_INTEGER | PM_READONLY, NULL, FN(get_histno), zleunsetfn, NULL }, { NULL, 0, NULL, NULL, NULL, NULL } @@ -84,12 +84,12 @@ makezleparams(int ro) for(zp = zleparams; zp->name; zp++) { Param pm = createparam(zp->name, (zp->type |PM_SPECIAL|PM_REMOVABLE| - (ro ? PM_READONLY : 0))); + PM_LOCAL|(ro ? PM_READONLY : 0))); if (!pm) pm = (Param) paramtab->getnode(paramtab, zp->name); DPUTS(!pm, "param not set in makezleparams"); - pm->level = locallevel; + pm->level = locallevel + 1; pm->u.data = zp->data; switch(PM_TYPE(zp->type)) { case PM_SCALAR: @@ -107,6 +107,8 @@ makezleparams(int ro) break; } pm->unsetfn = zp->unsetfn; + if ((zp->type & PM_UNSET) && (zmod.flags & MOD_MULT)) + pm->flags &= ~PM_UNSET; } } @@ -267,6 +269,7 @@ static void set_numeric(Param pm, zlong x) { zmult = x; + zmod.flags = MOD_MULT; } /**/ @@ -277,6 +280,17 @@ get_numeric(Param pm) } /**/ +static void +unset_numeric(Param pm, int exp) +{ + if (exp) { + stdunsetfn(pm, exp); + zmod.flags = 0; + zmult = 1; + } +} + +/**/ static zlong get_histno(Param pm) { diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c index ac18f52f0..da0b38bfe 100644 --- a/Src/Zle/zle_refresh.c +++ b/Src/Zle/zle_refresh.c @@ -1004,23 +1004,25 @@ tcoutarg(int cap, int arg) } /**/ -void -clearscreen(void) +int +clearscreen(char **args) { tcout(TCCLEARSCREEN); resetneeded = 1; clearflag = 0; + return 0; } /**/ -void -redisplay(void) +int +redisplay(char **args) { moveto(0, 0); zputc('\r', shout); /* extra care */ tc_upcurs(lprompth - 1); resetneeded = 1; clearflag = 0; + return 0; } /**/ diff --git a/Src/Zle/zle_thingy.c b/Src/Zle/zle_thingy.c index dbf982899..cf01f2fc1 100644 --- a/Src/Zle/zle_thingy.c +++ b/Src/Zle/zle_thingy.c @@ -318,9 +318,10 @@ deletezlefunction(Widget w) /* * The available operations are: * - * -l list user-defined widgets (no arguments) + * -l list widgets/test for existence * -D delete widget names * -A link the two named widgets (2 arguments) + * -C create completion widget (3 arguments) * -N create new user-defined widget (1 or 2 arguments) * invoke a widget (1 argument) */ @@ -334,12 +335,12 @@ bin_zle(char *name, char **args, char *ops, int func) int (*func) _((char *, char **, char *, char)); int min, max; } const opns[] = { - { 'l', bin_zle_list, 0, 0 }, + { 'l', bin_zle_list, 0, -1 }, { 'D', bin_zle_del, 1, -1 }, { 'A', bin_zle_link, 2, 2 }, { 'N', bin_zle_new, 1, 2 }, { 'C', bin_zle_complete, 3, 3 }, - { 'c', bin_zle_complete, 3, 3 }, + { 'R', bin_zle_refresh, 0, 1 }, { 0, bin_zle_call, 0, -1 }, }; struct opn const *op, *opp; @@ -357,10 +358,6 @@ bin_zle(char *name, char **args, char *ops, int func) /* check number of arguments */ for(n = 0; args[n]; n++) ; - if(!op->o && n != 1 && n != 2) { - zerrnam(name, "wrong number of arguments", NULL, 0); - return 1; - } if(n < op->min) { zerrnam(name, "not enough arguments for -%c", NULL, op->o); return 1; @@ -377,7 +374,41 @@ bin_zle(char *name, char **args, char *ops, int func) static int bin_zle_list(char *name, char **args, char *ops, char func) { - scanhashtable(thingytab, 1, 0, DISABLED, scanlistwidgets, ops['L']); + if (!*args) { + scanhashtable(thingytab, 1, 0, DISABLED, scanlistwidgets, + (ops['a'] ? -1 : ops['L'])); + return 0; + } else { + int ret = 0; + Thingy t; + + for (; *args && !ret; args++) { + if (!(t = (Thingy) thingytab->getnode2(thingytab, *args)) || + (!ops['a'] && (t->widget->flags & WIDGET_INT))) + ret = 1; + } + return ret; + } +} + +/**/ +static int +bin_zle_refresh(char *name, char **args, char *ops, char func) +{ + char *s = statusline; + int sl = statusll; + + if (*args) { + statusline = *args; + statusll = strlen(statusline); + } else { + statusline = NULL; + statusll = 0; + } + zrefresh(); + + statusline = s; + statusll = sl; return 0; } @@ -388,6 +419,10 @@ scanlistwidgets(HashNode hn, int list) Thingy t = (Thingy) hn; Widget w = t->widget; + if(list < 0) { + printf("%s\n", hn->nam); + return; + } if(w->flags & WIDGET_INT) return; if(list) { @@ -490,7 +525,8 @@ bin_zle_complete(char *name, char **args, char *ops, char func) return 1; } #endif - t = rthingy(args[1]); + + t = rthingy((args[1][0] == '.') ? args[1] : dyncat(".", args[1])); cw = t->widget; unrefthingy(t); if (!cw || !(cw->flags & ZLE_ISCOMP)) { @@ -517,31 +553,64 @@ bin_zle_call(char *name, char **args, char *ops, char func) { Thingy t; struct modifier modsave; + int ret, saveflag = 0; + char *wname = *args++; if(!zleactive || incompctlfunc || incompfunc) { zerrnam(name, "widgets can only be called when ZLE is active", NULL, 0); return 1; } - if (args[1]) { - modsave = zmod; - if (isdigit(*args[1])) { - zmod.mult = atoi(args[1]); - zmod.flags |= MOD_MULT; + + if (!wname) { + zwarnnam(name, "wrong number of arguments", NULL, 0); + if (saveflag) + zmod = modsave; + return 1; + } + while (*args && **args == '-') { + char *num; + if (!args[0][1] || args[0][1] == '-') { + args++; + break; } - else { - zmod.mult = 1; - zmod.flags &= ~MOD_MULT; + while (*++(*args)) { + switch (**args) { + case 'n': + num = args[0][1] ? args[0]+1 : args[1]; + if (!num) { + zwarnnam(name, "number expected after -%c", NULL, **args); + return 1; + } + if (!args[0][1]) + args++; + modsave = zmod; + saveflag = 1; + zmod.mult = atoi(num); + zmod.flags |= MOD_MULT; + break; + case 'N': + modsave = zmod; + saveflag = 1; + zmod.mult = 1; + zmod.flags &= ~MOD_MULT; + break; + default: + zwarnnam(name, "unknown option: %s", *args, 0); + return 1; + } } + args++; } - t = rthingy(args[0]); + + t = rthingy(wname); PERMALLOC { - execzlefunc(t); + ret = execzlefunc(t, args); } LASTALLOC; unrefthingy(t); - if (args[1]) + if (saveflag) zmod = modsave; - return 0; + return ret; } /*******************/ diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c index 8c2ae7bb6..65e1aeae9 100644 --- a/Src/Zle/zle_tricky.c +++ b/Src/Zle/zle_tricky.c @@ -110,20 +110,10 @@ static int movetoend; static int menucmp; -/* Pointers to the current position in the groups list and in the menu- * - * completion array (the one that was put in the command line last). */ +/* Information about menucompletion. */ -static Cmgroup menugrp; -static Cmatch *menucur; - -/* menupos is the point (in the command line) where the menu-completion * - * strings are inserted. menulen is the length of the string that was * - * inserted last. menuend is the end position of this string in the * - * command line. menuwe is non-zero if the cursor was at the end of the * - * word (meaning that suffixes should go before the cursor). menuinsc is * - * the length of any suffix that has been temporarily added. */ - -static int menupos, menulen, menuend, menuwe, menuinsc; +/**/ +struct menuinfo minfo; /* This is for completion inside a brace expansion. brbeg and brend hold * * strings that were temporarily removed from the string to complete. * @@ -376,157 +366,174 @@ static int lastend; #define FC_LINE 1 #define FC_INWORD 2 +/* Arguments for and return value of completion widget. */ + +static char **cfargs; +static int cfret; + /**/ -void -completecall(void) +int +completecall(char **args) { + cfargs = args; + cfret = 0; compfunc = compwidget->u.comp.func; - compwidget->u.comp.fn(); + if (compwidget->u.comp.fn(zlenoargs) && !cfret) + cfret = 1; compfunc = NULL; + + return cfret; } /**/ -void -completeword(void) +int +completeword(char **args) { usemenu = !!isset(MENUCOMPLETE); useglob = isset(GLOBCOMPLETE); if (c == '\t' && usetab()) - selfinsert(); + return selfinsert(args); else { + int ret; if (lastambig == 1 && isset(BASHAUTOLIST) && !usemenu && !menucmp) { - docomplete(COMP_LIST_COMPLETE); + ret = docomplete(COMP_LIST_COMPLETE); lastambig = 2; } else - docomplete(COMP_COMPLETE); + ret = docomplete(COMP_COMPLETE); + return ret; } } /**/ -void -menucomplete(void) +int +menucomplete(char **args) { usemenu = 1; useglob = isset(GLOBCOMPLETE); if (c == '\t' && usetab()) - selfinsert(); + return selfinsert(args); else - docomplete(COMP_COMPLETE); + return docomplete(COMP_COMPLETE); } /**/ -void -listchoices(void) +int +listchoices(char **args) { usemenu = !!isset(MENUCOMPLETE); useglob = isset(GLOBCOMPLETE); - docomplete(COMP_LIST_COMPLETE); + return docomplete(COMP_LIST_COMPLETE); } /**/ -void -spellword(void) +int +spellword(char **args) { usemenu = useglob = 0; - docomplete(COMP_SPELL); + return docomplete(COMP_SPELL); } /**/ -void -deletecharorlist(void) +int +deletecharorlist(char **args) { - Cmgroup mg = menugrp; - Cmatch *mc = menucur; + Cmgroup mg = minfo.group; + Cmatch *mc = minfo.cur; + int ret; usemenu = !!isset(MENUCOMPLETE); useglob = isset(GLOBCOMPLETE); if (cs != ll) { fixsuffix(); - deletechar(); + ret = deletechar(args); } else - docomplete(COMP_LIST_COMPLETE); + ret = docomplete(COMP_LIST_COMPLETE); - menucur = mc; - menugrp = mg; + minfo.cur = mc; + minfo.group = mg; + return ret; } /**/ -void -expandword(void) +int +expandword(char **args) { usemenu = useglob = 0; if (c == '\t' && usetab()) - selfinsert(); + return selfinsert(args); else - docomplete(COMP_EXPAND); + return docomplete(COMP_EXPAND); } /**/ -void -expandorcomplete(void) +int +expandorcomplete(char **args) { usemenu = !!isset(MENUCOMPLETE); useglob = isset(GLOBCOMPLETE); if (c == '\t' && usetab()) - selfinsert(); + return selfinsert(args); else { + int ret; if (lastambig == 1 && isset(BASHAUTOLIST) && !usemenu && !menucmp) { - docomplete(COMP_LIST_COMPLETE); + ret = docomplete(COMP_LIST_COMPLETE); lastambig = 2; } else - docomplete(COMP_EXPAND_COMPLETE); + ret = docomplete(COMP_EXPAND_COMPLETE); + return ret; } } /**/ -void -menuexpandorcomplete(void) +int +menuexpandorcomplete(char **args) { usemenu = 1; useglob = isset(GLOBCOMPLETE); if (c == '\t' && usetab()) - selfinsert(); + return selfinsert(args); else - docomplete(COMP_EXPAND_COMPLETE); + return docomplete(COMP_EXPAND_COMPLETE); } /**/ -void -listexpand(void) +int +listexpand(char **args) { usemenu = !!isset(MENUCOMPLETE); useglob = isset(GLOBCOMPLETE); - docomplete(COMP_LIST_EXPAND); + return docomplete(COMP_LIST_EXPAND); } /**/ -void -reversemenucomplete(void) +int +reversemenucomplete(char **args) { - if (!menucmp) { - menucomplete(); - return; - } + if (!menucmp) + return menucomplete(args); + HEAPALLOC { - if (menucur == menugrp->matches) { + if (minfo.cur == (minfo.group)->matches) { do { - if (!(menugrp = menugrp->prev)) - menugrp = lmatches; - } while (!menugrp->mcount); - menucur = menugrp->matches + menugrp->mcount - 1; + if (!(minfo.group = (minfo.group)->prev)) + minfo.group = lmatches; + } while (!(minfo.group)->mcount); + minfo.cur = (minfo.group)->matches + (minfo.group)->mcount - 1; } else - menucur--; + minfo.cur--; metafy_line(); - do_single(*menucur); + do_single(*(minfo.cur)); unmetafy_line(); } LASTALLOC; + return 0; } /* Accepts the current completion and starts a new arg, * * with the next completions. This gives you a way to * * accept several selections from the list of matches. */ -static void +/**/ +void acceptlast(void) { if (brbeg && *brbeg) { @@ -542,26 +549,24 @@ acceptlast(void) brbeg[l] = ','; brbeg[l + 1] = '\0'; } else { - cs = menupos + menulen + menuinsc; + cs = minfo.pos + minfo.len + minfo.insc; iremovesuffix(' ', 1); inststrlen(" ", 1, 1); - menuinsc = menulen = 0; - menupos = cs; - menuwe = 1; + minfo.insc = minfo.len = 0; + minfo.pos = cs; + minfo.we = 1; } } /**/ -void -acceptandmenucomplete(void) +int +acceptandmenucomplete(char **args) { - if (!menucmp) { - feep(); - return; - } + if (!menucmp) + return 1; acceptlast(); - menucomplete(); + return menucomplete(args); } /* These are flags saying if we are completing in the command * @@ -788,11 +793,11 @@ check_param(char *s, int set, int test) /* The main entry point for completion. */ /**/ -static void +static int docomplete(int lst) { char *s, *ol; - int olst = lst, chl = 0, ne = noerrs, ocs; + int olst = lst, chl = 0, ne = noerrs, ocs, ret = 0, omc = menucmp; if (showagain && validlist) showinglist = -2; @@ -803,7 +808,7 @@ docomplete(int lst) if (menucmp && lst != COMP_LIST_EXPAND && (!compwidget || compwidget == lastcompwidget)) { do_menucmp(lst); - return; + return 0; } lastcompwidget = compwidget; @@ -823,7 +828,7 @@ docomplete(int lst) * changed, do no more. */ if (doexpandhist()) - return; + return 0; metafy_line(); @@ -874,8 +879,7 @@ docomplete(int lst) ll = strlen((char *) line); cs = ocs; unmetafy_line(); - feep(); - return; + return 1; } ocs = cs; cs = 0; @@ -985,7 +989,7 @@ docomplete(int lst) inwhat = IN_CMD; if (lst == COMP_SPELL) { - char *x, *q; + char *x, *q, *ox; for (q = s; *q; q++) if (INULL(*q)) @@ -993,10 +997,11 @@ docomplete(int lst) cs = wb; foredel(we - wb); HEAPALLOC { - untokenize(x = dupstring(s)); + untokenize(x = ox = dupstring(s)); if (*s == Tilde || *s == Equals || *s == String) *x = *s; spckword(&x, 0, lincmd, 0); + ret = !strcmp(x, ox); } LASTALLOC; untokenize(x); inststr(x); @@ -1032,18 +1037,30 @@ docomplete(int lst) p++, skipparens(Inbrace, Outbrace, &p); } } - docompletion(s, lst, lincmd); - } + ret = docompletion(s, lst, lincmd); + } else + ret = !strcmp(ol, (char *) line); } else /* Just do completion. */ - docompletion(s, lst, lincmd); + ret = docompletion(s, lst, lincmd); zsfree(s); - } + } else + ret = 1; /* Reset the lexer state, pop the heap. */ lexrestore(); popheap(); zsfree(qword); unmetafy_line(); + + if (menucmp && !omc) { + struct chdata dat; + + dat.matches = amatches; + dat.num = nmatches; + dat.cur = NULL; + runhookdef(MENUSTARTHOOK, (void *) &dat); + } + return ret; } /* Do completion, given that we are in the middle of a menu completion. We * @@ -1052,7 +1069,7 @@ docomplete(int lst) * insert the next completion. */ /**/ -static void +void do_menucmp(int lst) { /* Just list the matches if the list was requested. */ @@ -1062,16 +1079,16 @@ do_menucmp(int lst) } /* Otherwise go to the next match in the array... */ HEAPALLOC { - if (!*++menucur) { + if (!*++(minfo.cur)) { do { - if (!(menugrp = menugrp->next)) - menugrp = amatches; - } while (!menugrp->mcount); - menucur = menugrp->matches; + if (!(minfo.group = (minfo.group)->next)) + minfo.group = amatches; + } while (!(minfo.group)->mcount); + minfo.cur = minfo.group->matches; } /* ... and insert it into the command line. */ metafy_line(); - do_single(*menucur); + do_single(*(minfo.cur)); unmetafy_line(); } LASTALLOC; } @@ -1425,7 +1442,6 @@ get_comp_string(void) lexrestore(); goto start; } - feep(); noaliases = 0; lexrestore(); LASTALLOC_RETURN NULL; @@ -1484,11 +1500,14 @@ get_comp_string(void) if (lev) lev--; } - wb++; p = (char *) line + wb; + wb++; if (wb && (*p == '[' || *p == '(') && - !skipparens(*p, (*p == '[' ? ']' : ')'), &p)) - we = p - (char *) line; + !skipparens(*p, (*p == '[' ? ']' : ')'), &p)) { + we = (p - (char *) line) - 1; + if (insubscr == 2) + insubscr = 3; + } } else { /* In mathematical expression, we complete parameter names * * (even if they don't have a `$' in front of them). So we * @@ -1513,9 +1532,10 @@ get_comp_string(void) varname = ztrdup((char *) line + i + 1); line[wb - 1] = sav; if ((keypm = (Param) paramtab->getnode(paramtab, varname)) && - (keypm->flags & PM_HASHED)) - insubscr = 2; - else + (keypm->flags & PM_HASHED)) { + if (insubscr != 3) + insubscr = 2; + } else insubscr = 1; } } @@ -1734,11 +1754,8 @@ doexpansion(char *s, int lst, int olst, int explincmd) } if (errflag) goto end; - if (empty(vl) || !*(char *)peekfirst(vl)) { - if (!noerrs) - feep(); + if (empty(vl) || !*(char *)peekfirst(vl)) goto end; - } if (peekfirst(vl) == (void *) ss || (olst == COMP_EXPAND_COMPLETE && !nextnode(firstnode(vl)) && *s == Tilde && @@ -1748,8 +1765,6 @@ doexpansion(char *s, int lst, int olst, int explincmd) * expandorcomplete was called, otherwise, just beep. */ if (lst == COMP_EXPAND_COMPLETE) docompletion(s, COMP_COMPLETE, explincmd); - else - feep(); goto end; } if (lst == COMP_LIST_EXPAND) { @@ -3776,9 +3791,10 @@ addmatches(Cadata dat, char **argv) } else dat->prpre = dupstring(dat->prpre); /* Select the group in which to store the matches. */ - if (dat->group) { + if (dat->group || dat->ylist) { endcmgroup(NULL); - begcmgroup(dat->group, (dat->aflags & CAF_NOSORT)); + begcmgroup((dat->ylist ? NULL : dat->group), + (dat->aflags & CAF_NOSORT)); if (dat->aflags & CAF_NOSORT) mgroup->flags |= CGF_NOSORT; } else { @@ -3800,6 +3816,10 @@ addmatches(Cadata dat, char **argv) lpre = quotename(lpre, NULL); lsuf = quotename(lsuf, NULL); } + if (dat->ppre) + dat->ppre = quotename(dat->ppre, NULL); + if (dat->psuf) + dat->psuf = quotename(dat->psuf, NULL); } /* Walk through the matches given. */ for (; (s = *argv); argv++) { @@ -3825,8 +3845,10 @@ addmatches(Cadata dat, char **argv) } } if (!(dat->aflags & CAF_MATCH)) { - ms = ((dat->aflags & CAF_QUOTE) ? dupstring(s) : - quotename(s, NULL)); + if (dat->aflags & CAF_QUOTE) + ms = dupstring(s); + else + sl = strlen(ms = quotename(s, NULL)); lc = bld_parts(ms, sl, -1, NULL); isexact = 0; } else if (!(ms = comp_match(lpre, lsuf, s, cp, &lc, @@ -3865,6 +3887,10 @@ addmatches(Cadata dat, char **argv) set_param(dat->opar, oparl); if (dat->dpar) set_param(dat->dpar, dparl); + if (dat->ylist) { + endcmgroup(get_user_var(dat->ylist)); + begcmgroup("default", 0); + } } LASTALLOC; } SWITCHBACKHEAPS; @@ -4288,9 +4314,11 @@ gen_matches_files(int dirs, int execs, int all) } /**/ -static void +static int docompletion(char *s, int lst, int incmd) { + int ret = 0; + HEAPALLOC { char *opm; LinkNode n; @@ -4328,8 +4356,8 @@ docompletion(char *s, int lst, int incmd) foredel(ll); inststr(origline); cs = origcs; - feep(); clearlist = 1; + ret = 1; goto compend; } if (comppatmatch && *comppatmatch && comppatmatch != opm) @@ -4339,17 +4367,17 @@ docompletion(char *s, int lst, int incmd) showinglist = -2; else if (useline) { /* We have matches. */ - if (nmatches > 1) + if (nmatches > 1) { /* There is more than one match. */ - do_ambiguous(); - - else if (nmatches == 1) { + ret = do_ambiguous(); + } else if (nmatches == 1) { /* Only one match. */ Cmgroup m = amatches; while (!m->mcount) m = m->next; - menucur = NULL; + minfo.cur = NULL; + minfo.asked = 0; do_single(m->matches[0]); invalidatelist(); } @@ -4363,7 +4391,7 @@ docompletion(char *s, int lst, int incmd) int up = 0, tr = 1, nn = 0; if (!nmatches) - feep(); + ret = 1; while (g) { if ((e = g->expls)) @@ -4404,6 +4432,7 @@ docompletion(char *s, int lst, int incmd) cs = ll; popheap(); } LASTALLOC; + return ret; } /* This calls the given function for new style completion. */ @@ -4604,8 +4633,8 @@ callcompfunc(char *s, char *fn) else compoldlist = "yes"; kset |= CP_OLDLIST; - if (menucur) { - sprintf(buf, "%d", (*menucur)->gnum); + if (minfo.cur) { + sprintf(buf, "%d", (*(minfo.cur))->gnum); compoldins = buf; kset |= CP_OLDINS; } else @@ -4623,7 +4652,20 @@ callcompfunc(char *s, char *fn) makezleparams(1); sfcontext = SFC_CWIDGET; NEWHEAPS(compheap) { - doshfunc(fn, list, NULL, 0, 1); + LinkList largs = NULL; + int olv = lastval; + + if (*cfargs) { + char **p = cfargs; + + largs = newlinklist(); + addlinknode(largs, dupstring(fn)); + while (*p) + addlinknode(largs, dupstring(*p++)); + } + doshfunc(fn, list, largs, 0, 0); + cfret = lastval; + lastval = olv; } OLDHEAPS; sfcontext = osc; endparamscope(); @@ -4673,7 +4715,7 @@ callcompfunc(char *s, char *fn) movetoend = 2; oldlist = (hasperm && compoldlist && !strcmp(compoldlist, "keep")); - oldins = (hasperm && menucur && + oldins = (hasperm && minfo.cur && compoldins && !strcmp(compoldins, "keep")); zfree(comprpms, CP_REALPARAMS * sizeof(Param)); @@ -4710,7 +4752,7 @@ makecomplist(char *s, int incmd, int lst) int onm = nmatches, osi = movefd(0); /* Inside $... ? */ - if (compfunc && (p = check_param(s, 0, NULL))) + if (compfunc && (p = check_param(s, 0, 0))) os = s = p; /* We build a copy of the list of matchers to use to make sure that this @@ -5281,10 +5323,10 @@ makecomplistglobal(char *os, int incmd, int lst, int flags) cc = &cc_default; keypm = NULL; } else if (linwhat == IN_MATH) { - if (insubscr == 2) { + if (insubscr >= 2) { /* Inside subscript of assoc array, complete keys. */ cc_dummy.mask = 0; - cc_dummy.suffix = "]"; + cc_dummy.suffix = (insubscr == 2 ? "]" : ""); } else { /* Other math environment, complete paramete names. */ keypm = NULL; @@ -5590,7 +5632,7 @@ makecomplistext(Compctl occ, char *os, int incmd) case CCT_RANGEPAT: if (cc->type == CCT_RANGEPAT) tokenize(sc = dupstring(cc->u.l.a[i])); - for (j = clwpos; j; j--) { + for (j = clwpos - 1; j > 0; j--) { untokenize(s = ztrdup(clwords[j])); if (cc->type == CCT_RANGESTR) sc = rembslash(cc->u.l.a[i]); @@ -5791,7 +5833,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) ic = 0; /* Check if we have to complete a parameter name... */ - if (!incompfunc && (p = check_param(s, 1, NULL))) { + if (!incompfunc && (p = check_param(s, 1, 0))) { s = p; /* And now make sure that we complete parameter names. */ cc = &cc_dummy; @@ -6267,8 +6309,15 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) maketildelist(); addwhat = oaw; } - if (cc->widget) + if (cc->widget) { + char **ocfa = cfargs; + int ocfr = cfret; + + cfargs = zlenoargs; callcompfunc(os, cc->widget); + cfargs = ocfa; + cfret = ocfr; + } if (cc->func) { /* This handles the compctl -K flag. */ List list; @@ -6313,20 +6362,14 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) if (cc->mask & (CC_JOBS | CC_RUNNING | CC_STOPPED)) { /* Get job names. */ int i; - char *j, *jj; + char *j; for (i = 0; i < MAXJOB; i++) if ((jobtab[i].stat & STAT_INUSE) && jobtab[i].procs && jobtab[i].procs->text) { int stopped = jobtab[i].stat & STAT_STOPPED; - j = jj = dupstring(jobtab[i].procs->text); - /* Find the first word. */ - for (; *jj; jj++) - if (*jj == ' ') { - *jj = '\0'; - break; - } + j = dupstring(jobtab[i].procs->text); if ((cc->mask & CC_JOBS) || (stopped && (cc->mask & CC_STOPPED)) || (!stopped && (cc->mask & CC_RUNNING))) @@ -6507,7 +6550,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) if (cc->subcmd) { /* Handle -l sub-completion. */ char **ow = clwords, *os = cmdstr, *ops = NULL; - int oldn = clwnum, oldp = clwpos; + int oldn = clwnum, oldp = clwpos, br; unsigned long occ = ccont; ccont = CC_CCCONT; @@ -6523,21 +6566,22 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) erange = 1; clwnum = erange - brange + 1; clwpos = clwpos - brange; - + br = brange; + if (cc->subcmd[0]) { /* And probably put the command name given to the flag * * in the array. */ clwpos++; clwnum++; incmd = 0; - ops = clwords[brange - 1]; - clwords[brange - 1] = cc->subcmd; + ops = clwords[br - 1]; + clwords[br - 1] = ztrdup(cc->subcmd); cmdstr = ztrdup(cc->subcmd); - clwords += brange - 1; + clwords += br - 1; } else { - cmdstr = ztrdup(clwords[brange]); + cmdstr = ztrdup(clwords[br]); incmd = !clwpos; - clwords += brange; + clwords += br; } /* Produce the matches. */ makecomplistcmd(s, incmd, CFN_FIRST); @@ -6548,8 +6592,10 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) cmdstr = os; clwnum = oldn; clwpos = oldp; - if (ops) - clwords[brange - 1] = ops; + if (ops) { + zsfree(clwords[br - 1]); + clwords[br - 1] = ops; + } ccont = occ; } if (cc->substr) @@ -6570,7 +6616,8 @@ invalidatelist(void) if (validlist) freematches(); lastambig = menucmp = validlist = showinglist = fromcomp = 0; - menucur = NULL; + minfo.cur = NULL; + minfo.asked = 0; compwidget = NULL; } @@ -7337,19 +7384,20 @@ instmatch(Cmatch m, int *scs) /* Handle the case were we found more than one match. */ /**/ -static void +static int do_ambiguous(void) { + int ret = 0; menucmp = 0; /* If we have to insert the first match, call do_single(). This is * * how REC_EXACT takes effect. We effectively turn the ambiguous * * completion into an unambiguous one. */ if (ainfo && ainfo->exact == 1 && useexact && !(fromcomp & FC_LINE)) { - menucur = NULL; + minfo.cur = NULL; do_single(ainfo->exactm); invalidatelist(); - return; + return ret; } /* Setting lastambig here means that the completion is ambiguous and * * AUTO_MENU might want to start a menu completion next time round, * @@ -7369,7 +7417,8 @@ do_ambiguous(void) int atend = (cs == we), oll = ll, la, eq, tcs; VARARR(char, oline, ll); - menucur = NULL; + minfo.cur = NULL; + minfo.asked = 0; /* Copy the line buffer to be able to easily test if it changed. */ memcpy(oline, line, ll); @@ -7418,19 +7467,21 @@ do_ambiguous(void) fromcomp = fc; lastambig = 0; clearlist = 1; - return; + return ret; } } else - return; + return ret; /* At this point, we might want a completion listing. Show the listing * * if it is needed. */ if (isset(LISTBEEP)) - feep(); - if (uselist && usemenu != 2 && - (!showinglist || (usemenu == 3 && !oldlist)) && + ret = 1; + if (uselist && (usemenu != 2 || (!showinglist && !oldlist)) && + ((!showinglist && (!listshown || !oldlist)) || + (usemenu == 3 && !oldlist)) && (smatches >= 2 || (compforcelist && *compforcelist))) showinglist = -2; + return ret; } /* This is a stat that ignores backslashes in the filename. The `ls' * @@ -7440,7 +7491,7 @@ do_ambiguous(void) * (l)stat(). */ /**/ -static int +int ztat(char *nam, struct stat *buf, int ls) { char b[PATH_MAX], *p; @@ -7458,7 +7509,7 @@ ztat(char *nam, struct stat *buf, int ls) /* Insert a single match in the command line. */ /**/ -static void +void do_single(Cmatch m) { int l, sr = 0, scs; @@ -7471,39 +7522,39 @@ do_single(Cmatch m) fixsuffix(); - if (!menucur) { + if (!minfo.cur) { /* We are currently not in a menu-completion, * * so set the position variables. */ - menupos = wb; - menuwe = (movetoend >= 2 || (movetoend == 1 && !menucmp)); - menuend = we; + minfo.pos = wb; + minfo.we = (movetoend >= 2 || (movetoend == 1 && !menucmp)); + minfo.end = we; } /* If we are already in a menu-completion or if we have done a * * glob completion, we have to delete some of the stuff on the * * command line. */ - if (menucur) - l = menulen + menuinsc; + if (minfo.cur) + l = minfo.len + minfo.insc; else l = we - wb; - menuinsc = 0; - cs = menupos; + minfo.insc = 0; + cs = minfo.pos; foredel(l); /* And then we insert the new string. */ - menulen = instmatch(m, &scs); - menuend = cs; - cs = menupos + menulen; + minfo.len = instmatch(m, &scs); + minfo.end = cs; + cs = minfo.pos + minfo.len; if (m->suf) { havesuff = 1; - menuinsc = ztrlen(m->suf); - menulen -= menuinsc; - if (menuwe) { - menuend += menuinsc; + minfo.insc = ztrlen(m->suf); + minfo.len -= minfo.insc; + if (minfo.we) { + minfo.end += minfo.insc; if (m->flags & CMF_REMOVE) { - makesuffixstr(m->remf, m->rems, menuinsc); - if (menuinsc == 1) + makesuffixstr(m->remf, m->rems, minfo.insc); + if (minfo.insc == 1) suffixlen[STOUC(m->suf[0])] = 1; } } @@ -7519,11 +7570,11 @@ do_single(Cmatch m) cs += eparq; for (pq = parq; pq; pq--) inststrlen("\"", 1, 1); - menuinsc += parq; + minfo.insc += parq; inststrlen("}", 1, 1); - menuinsc++; - if (menuwe) - menuend += menuinsc; + minfo.insc++; + if (minfo.we) + minfo.end += minfo.insc; } if ((m->flags & CMF_FILE) || (m->ripre && isset(AUTOPARAMSLASH))) { /* If we have a filename or we completed a parameter name * @@ -7559,10 +7610,10 @@ do_single(Cmatch m) /* It is a directory, so add the slash. */ havesuff = 1; inststrlen("/", 1, 1); - menuinsc++; - if (menuwe) - menuend++; - if (!menucmp || menuwe) { + minfo.insc++; + if (minfo.we) + minfo.end++; + if (!menucmp || minfo.we) { if (m->remf || m->rems) makesuffixstr(m->remf, m->rems, 1); else if (isset(AUTOREMOVESLASH)) { @@ -7572,8 +7623,8 @@ do_single(Cmatch m) } } } - if (!menuinsc) - cs = menupos + menulen; + if (!minfo.insc) + cs = minfo.pos + minfo.len; } /* If completing in a brace expansion... */ if (brbeg) { @@ -7589,9 +7640,9 @@ do_single(Cmatch m) cs = scs; havesuff = 1; inststrlen(",", 1, 1); - menuinsc++; + minfo.insc++; makesuffix(1); - if ((!menucmp || menuwe) && isset(AUTOPARAMKEYS)) + if ((!menucmp || minfo.we) && isset(AUTOPARAMKEYS)) suffixlen[','] = suffixlen['}'] = 1; } } else if (!havesuff && (!(m->flags & CMF_FILE) || !sr)) { @@ -7600,20 +7651,33 @@ do_single(Cmatch m) * the string doesn't name an existing file. */ if (m->autoq && (!m->isuf || m->isuf[0] != m->autoq)) { inststrlen(&(m->autoq), 1, 1); - menuinsc++; + minfo.insc++; } - if (!menucmp) { + if (!menucmp && usemenu != 3) { inststrlen(" ", 1, 1); - menuinsc++; - if (menuwe) + minfo.insc++; + if (minfo.we) makesuffix(1); } } - if (menuwe && m->ripre && isset(AUTOPARAMKEYS)) - makeparamsuffix(((m->flags & CMF_PARBR) ? 1 : 0), menuinsc - parq); + if (minfo.we && m->ripre && isset(AUTOPARAMKEYS)) + makeparamsuffix(((m->flags & CMF_PARBR) ? 1 : 0), minfo.insc - parq); - if ((menucmp && !menuwe) || !movetoend) - cs = menuend; + if ((menucmp && !minfo.we) || !movetoend) + cs = minfo.end; + { + Cmatch *om = minfo.cur; + struct chdata dat; + + dat.matches = amatches; + dat.num = nmatches; + dat.cur = m; + + if (menucmp) + minfo.cur = &m; + runhookdef(INSERTMATCHHOOK, (void *) &dat); + minfo.cur = om; + } } /* This maps the value in v into the range [0,m-1], decrementing v @@ -7643,40 +7707,42 @@ do_ambig_menu(void) if (usemenu != 3) { menucmp = 1; - menucur = NULL; + minfo.cur = NULL; } else { if (oldlist) { if (oldins) acceptlast(); } else - menucur = NULL; + minfo.cur = NULL; } if (insgroup) { insgnum = comp_mod(insgnum, permgnum); - for (menugrp = amatches; - menugrp && menugrp->num != insgnum + 1; - menugrp = menugrp->next); - if (!menugrp || !menugrp->mcount) { - menucur = NULL; + for (minfo.group = amatches; + minfo.group && (minfo.group)->num != insgnum + 1; + minfo.group = (minfo.group)->next); + if (!minfo.group || !(minfo.group)->mcount) { + minfo.cur = NULL; + minfo.asked = 0; return; } - insmnum = comp_mod(insmnum, menugrp->mcount); + insmnum = comp_mod(insmnum, (minfo.group)->mcount); } else { int c = 0; insmnum = comp_mod(insmnum, permmnum); - for (menugrp = amatches; - menugrp && (c += menugrp->mcount) <= insmnum; - menugrp = menugrp->next) - insmnum -= menugrp->mcount; - if (!menugrp) { - menucur = NULL; + for (minfo.group = amatches; + minfo.group && (c += (minfo.group)->mcount) <= insmnum; + minfo.group = (minfo.group)->next) + insmnum -= (minfo.group)->mcount; + if (!minfo.group) { + minfo.cur = NULL; + minfo.asked = 0; return; } } - mc = menugrp->matches + insmnum; + mc = (minfo.group)->matches + insmnum; do_single(*mc); - menucur = mc; + minfo.cur = mc; } /* Return the length of the common prefix of s and t. */ @@ -7715,7 +7781,7 @@ sfxlen(char *s, char *t) * It returns the number of lines printed. */ /**/ -static int +int printfmt(char *fmt, int n, int dopr) { char *p = fmt, nc[DIGBUFSIZE]; @@ -7798,7 +7864,8 @@ printfmt(char *fmt, int n, int dopr) /* This skips over matches that are not to be listed. */ -static Cmatch * +/**/ +Cmatch * skipnolist(Cmatch *p) { while (*p && ((*p)->flags & CMF_NOLIST)) @@ -7813,11 +7880,7 @@ skipnolist(Cmatch *p) void listmatches(void) { - Cmgroup g; - Cmatch *p, m; - Cexpl *e; - int nlines = 0, ncols, nlist = 0, longest = 1, pnl = 0; - int of = isset(LISTTYPES), opl = 0; + struct chdata dat; #ifdef DEBUG /* Sanity check */ @@ -7827,6 +7890,22 @@ listmatches(void) } #endif + dat.matches = amatches; + dat.num = nmatches; + dat.cur = NULL; + runhookdef(LISTMATCHESHOOK, (void *) &dat); +} + +/**/ +int +ilistmatches(Hookdef dummy, Chdata dat) +{ + Cmgroup g; + Cmatch *p, m; + Cexpl *e; + int nlines = 0, ncols, nlist = 0, longest = 1, pnl = 0; + int of = isset(LISTTYPES), opl = 0; + /* Set the cursor below the prompt. */ trashzle(); showinglist = listshown = 0; @@ -7911,8 +7990,9 @@ listmatches(void) } /* Maybe we have to ask if the user wants to see the list. */ - if ((complistmax && nlist > complistmax) || - (!complistmax && nlines >= lines)) { + if ((!minfo.cur || !minfo.asked) && + ((complistmax && nlist > complistmax) || + (!complistmax && nlines >= lines))) { int qup; zsetterm(); qup = printfmt("zsh: do you wish to see all %n possibilities? ", nlist, 1); @@ -7926,7 +8006,9 @@ listmatches(void) tcmultout(TCUP, TCMULTUP, nlnct); } else putc('\n', shout); - return; + if (minfo.cur) + minfo.asked = 2; + return 0; } if (clearflag) { putc('\r', shout); @@ -7936,6 +8018,8 @@ listmatches(void) } else putc('\n', shout); settyinfo(&shttyinfo); + if (minfo.cur) + minfo.asked = 1; } /* Now print the matches. */ @@ -7956,7 +8040,7 @@ listmatches(void) e++; } } - if (pp) { + if (pp && *pp) { if (pnl) { putc('\n', shout); pnl = 0; @@ -8055,6 +8139,7 @@ listmatches(void) clearflag = 0, putc('\n', shout); } else putc('\n', shout); + return 0; } /* This is used to print expansions. */ @@ -8064,9 +8149,9 @@ void listlist(LinkList l) { struct cmgroup dg; - Cmgroup am = amatches; int vl = validlist, sm = smatches; char *oclp = complastprompt; + Cmgroup am = amatches; if (listshown) showagain = 1; @@ -8074,12 +8159,12 @@ listlist(LinkList l) complastprompt = ((zmult == 1) == !!isset(ALWAYSLASTPROMPT) ? "yes" : NULL); smatches = 1; validlist = 1; - amatches = &dg; memset(&dg, 0, sizeof(struct cmgroup)); dg.ylist = (char **) makearray(l, 1, &(dg.lcount), NULL); - listmatches(); - + amatches = &dg; + ilistmatches(NULL, NULL); amatches = am; + validlist = vl; smatches = sm; complastprompt = oclp; @@ -8153,20 +8238,22 @@ doexpandhist(void) } /**/ -void -magicspace(void) +int +magicspace(char **args) { + int ret; c = ' '; - selfinsert(); - doexpandhist(); + ret = selfinsert(args); + return !doexpandhist(); } /**/ -void -expandhistory(void) +int +expandhistory(char **args) { if (!doexpandhist()) - feep(); + return 1; + return 0; } static int cmdwb, cmdwe; @@ -8210,19 +8297,17 @@ getcurcmd(void) } /**/ -void -processcmd(void) +int +processcmd(char **args) { char *s; int m = zmult; s = getcurcmd(); - if (!s) { - feep(); - return; - } + if (!s) + return 1; zmult = 1; - pushline(); + pushline(zlenoargs); zmult = m; inststr(bindk->nam); inststr(" "); @@ -8232,11 +8317,12 @@ processcmd(void) } LASTALLOC; zsfree(s); done = 1; + return 0; } /**/ -void -expandcmdpath(void) +int +expandcmdpath(char **args) { int oldcs = cs, na = noaliases; char *s, *str; @@ -8244,16 +8330,12 @@ expandcmdpath(void) noaliases = 1; s = getcurcmd(); noaliases = na; - if (!s || cmdwb < 0 || cmdwe < cmdwb) { - feep(); - return; - } + if (!s || cmdwb < 0 || cmdwe < cmdwb) + return 1; str = findcmd(s, 1); zsfree(s); - if (!str) { - feep(); - return; - } + if (!str) + return 1; cs = cmdwb; foredel(cmdwe - cmdwb); spaceinline(strlen(str)); @@ -8263,16 +8345,20 @@ expandcmdpath(void) cs += cmdwe - cmdwb + strlen(str); if (cs > ll) cs = ll; + return 0; } /* Extra function added by AR Iano-Fletcher. */ /* This is a expand/complete in the vein of wash. */ /**/ -void -expandorcompleteprefix(void) +int +expandorcompleteprefix(char **args) { + int ret; + comppref = 1; - expandorcomplete(); + ret = expandorcomplete(args); comppref = 0; + return ret; } diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c index 8524fd21e..bd2f39a06 100644 --- a/Src/Zle/zle_utils.c +++ b/Src/Zle/zle_utils.c @@ -409,19 +409,11 @@ showmsg(char const *msg) /* handle the error flag */ /**/ -void -feep(void) -{ - feepflag = 1; -} - -/**/ -void -handlefeep(void) +int +handlefeep(char **args) { - if(feepflag) - zbeep(); - feepflag = 0; + zbeep(); + return 0; } /***************/ @@ -554,18 +546,17 @@ setlastline(void) /* move backwards through the change list */ /**/ -void -undo(void) +int +undo(char **args) { handleundo(); do { - if(!curchange->prev) { - feep(); - return; - } + if(!curchange->prev) + return 1; unapplychange(curchange = curchange->prev); } while(curchange->flags & CH_PREV); setlastline(); + return 0; } /**/ @@ -592,19 +583,18 @@ unapplychange(struct change *ch) /* move forwards through the change list */ /**/ -void -redo(void) +int +redo(char **args) { handleundo(); do { - if(!curchange->next) { - feep(); - return; - } + if(!curchange->next) + return 1; applychange(curchange); curchange = curchange->next; } while(curchange->prev->flags & CH_NEXT); setlastline(); + return 0; } /**/ @@ -631,8 +621,8 @@ applychange(struct change *ch) /* vi undo: toggle between the end of the undo list and the preceding point */ /**/ -void -viundochange(void) +int +viundochange(char **args) { handleundo(); if(curchange->next) { @@ -641,6 +631,7 @@ viundochange(void) curchange = curchange->next; } while(curchange->next); setlastline(); + return 0; } else - undo(); + return undo(args); } diff --git a/Src/Zle/zle_vi.c b/Src/Zle/zle_vi.c index 5b1548e25..71f766739 100644 --- a/Src/Zle/zle_vi.c +++ b/Src/Zle/zle_vi.c @@ -102,10 +102,8 @@ vigetkey(void) char m[3], *str; Thingy cmd; - if((c = getkey(0)) == EOF) { - feep(); + if((c = getkey(0)) == EOF) return -1; - } m[0] = c; metafy(m, 1, META_NOALLOC); @@ -115,13 +113,10 @@ vigetkey(void) cmd = t_undefinedkey; if (!cmd || cmd == Th(z_sendbreak)) { - feep(); return -1; } else if (cmd == Th(z_quotedinsert)) { - if ((c = getkey(0)) == EOF) { - feep(); + if ((c = getkey(0)) == EOF) return -1; - } } else if(cmd == Th(z_viquotedinsert)) { char sav = line[cs]; @@ -129,10 +124,8 @@ vigetkey(void) zrefresh(); c = getkey(0); line[cs] = sav; - if(c == EOF) { - feep(); + if(c == EOF) return -1; - } } else if (cmd == Th(z_vicmdmode)) return -1; return c; @@ -142,7 +135,7 @@ vigetkey(void) static int getvirange(int wf) { - int pos = cs; + int pos = cs, ret = 0; int mult1 = zmult, hist1 = histline; Thingy k2; @@ -168,39 +161,37 @@ getvirange(int wf) k2 == Th(z_sendbreak)) { wordflag = 0; virangeflag = 0; - feep(); return -1; } - if(k2 == bindk) - /* The command key is repeated: a number of lines is used. */ - dovilinerange(); - else - execzlefunc(k2); + /* + * With k2 == bindk, the command key is repeated: + * a number of lines is used. If the function used + * returns 1, we fail. + */ + if ((k2 == bindk) ? dovilinerange() : execzlefunc(k2, zlenoargs)) + ret = -1; if(vichgrepeat) zmult = mult1; else zmult = mult1 * zmod.tmult; - } while(prefixflag); + } while(prefixflag && !ret); wordflag = 0; virangeflag = 0; /* It is an error to use a non-movement command to delimit the * * range. We here reject the case where the command modified * * the line, or selected a different history line. */ - if(histline != hist1 || ll != lastll || memcmp(line, lastline, ll)) { + if (histline != hist1 || ll != lastll || memcmp(line, lastline, ll)) { histline = hist1; memcpy(line, lastline, ll = lastll); cs = pos; - feep(); return -1; } /* Can't handle an empty file. Also, if the movement command * * failed, or didn't move, it is an error. */ - if (!ll || (cs == pos && virangeflag != 2)) { - feep(); + if (!ll || (cs == pos && virangeflag != 2) || ret == -1) return -1; - } /* vi-match-bracket changes the value of virangeflag when * * moving to the opening bracket, meaning that we need to * @@ -233,7 +224,7 @@ getvirange(int wf) } /**/ -static void +static int dovilinerange(void) { int pos = cs, n = zmult; @@ -243,17 +234,14 @@ dovilinerange(void) * downward, otherwise upward. The repeat count gives the * * number of lines. */ vilinerange = 1; - if (!n) { - feep(); - return; - } + if (!n) + return 1; if (n > 0) { while(n-- && cs <= ll) cs = findeol() + 1; if (n != -1) { cs = pos; - feep(); - return; + return 1; } cs--; } else { @@ -261,123 +249,127 @@ dovilinerange(void) cs = findbol() - 1; if (n != 1) { cs = pos; - feep(); - return; + return 1; } cs++; } virangeflag = 2; + return 0; } /**/ -void -viaddnext(void) +int +viaddnext(char **args) { if (cs != findeol()) cs++; startvitext(1); + return 0; } /**/ -void -viaddeol(void) +int +viaddeol(char **args) { cs = findeol(); startvitext(1); + return 0; } /**/ -void -viinsert(void) +int +viinsert(char **args) { startvitext(1); + return 0; } /**/ -void -viinsertbol(void) +int +viinsertbol(char **args) { - vifirstnonblank(); + vifirstnonblank(zlenoargs); startvitext(1); + return 0; } /**/ -void -videlete(void) +int +videlete(char **args) { - int c2; + int c2, ret = 1; startvichange(1); if ((c2 = getvirange(0)) != -1) { forekill(c2 - cs, 0); + ret = 0; if (vilinerange && ll) { if (cs == ll) cs--; foredel(1); - vifirstnonblank(); + vifirstnonblank(zlenoargs); } } vichgflag = 0; + return ret; } /**/ -void -videletechar(void) +int +videletechar(char **args) { int n = zmult; startvichange(-1); /* handle negative argument */ if (n < 0) { + int ret; zmult = -n; - vibackwarddeletechar(); + ret = vibackwarddeletechar(args); zmult = n; - return; + return ret; } /* it is an error to be on the end of line */ - if (cs == ll || line[cs] == '\n') { - feep(); - return; - } + if (cs == ll || line[cs] == '\n') + return 1; /* Put argument into the acceptable range -- it is not an error to * * specify a greater count than the number of available characters. */ if (n > findeol() - cs) n = findeol() - cs; /* do the deletion */ forekill(n, 0); + return 0; } /**/ -void -vichange(void) +int +vichange(char **args) { - int c2; + int c2, ret = 1; startvichange(1); if ((c2 = getvirange(1)) != -1) { + ret = 0; forekill(c2 - cs, 0); selectkeymap("main", 1); viinsbegin = cs; undoing = 0; } + return ret; } /**/ -void -visubstitute(void) +int +visubstitute(char **args) { int n = zmult; startvichange(1); - if (n < 0) { - feep(); - return; - } + if (n < 0) + return 1; /* it is an error to be on the end of line */ - if (cs == ll || line[cs] == '\n') { - feep(); - return; - } + if (cs == ll || line[cs] == '\n') + return 1; /* Put argument into the acceptable range -- it is not an error to * * specify a greater count than the number of available characters. */ if (n > findeol() - cs) @@ -385,79 +377,84 @@ visubstitute(void) /* do the substitution */ forekill(n, 0); startvitext(1); + return 0; } /**/ -void -vichangeeol(void) +int +vichangeeol(char **args) { forekill(findeol() - cs, 0); startvitext(1); + return 0; } /**/ -void -vichangewholeline(void) +int +vichangewholeline(char **args) { - vifirstnonblank(); - vichangeeol(); + vifirstnonblank(args); + return vichangeeol(zlenoargs); } /**/ -void -viyank(void) +int +viyank(char **args) { - int oldcs = cs, c2; + int oldcs = cs, c2, ret = 1; startvichange(1); - if ((c2 = getvirange(0)) != -1) + if ((c2 = getvirange(0)) != -1) { cut(cs, c2 - cs, 0); + ret = 0; + } vichgflag = 0; cs = oldcs; + return ret; } /**/ -void -viyankeol(void) +int +viyankeol(char **args) { int x = findeol(); startvichange(-1); - if (x == cs) { - feep(); - return; - } + if (x == cs) + return 1; cut(cs, x - cs, 0); + return 0; } /**/ -void -viyankwholeline(void) +int +viyankwholeline(char **args) { int bol = findbol(), oldcs = cs; int n = zmult; startvichange(-1); if (n < 1) - return; + return 1; while(n--) { if (cs > ll) { - feep(); cs = oldcs; - return; + return 1; } cs = findeol() + 1; } vilinerange = 1; cut(bol, cs - bol - 1, 0); cs = oldcs; + return 0; } /**/ -void -vireplace(void) +int +vireplace(char **args) { startvitext(0); + return 0; } /* vi-replace-chars has some oddities relating to vi-repeat-change. In * @@ -474,32 +471,27 @@ vireplace(void) * without a rewrite of the repeat code. */ /**/ -void -vireplacechars(void) +int +vireplacechars(char **args) { int ch, n = zmult; startvichange(1); /* check argument range */ if (n < 1 || n + cs > findeol()) { - if(vichgrepeat) { - int ofeep = feepflag; + if(vichgrepeat) vigetkey(); - feepflag = ofeep; - } if(vichgflag) { free(vichgbuf); vichgbuf = NULL; vichgflag = 0; } - feep(); - return; + return 1; } /* get key */ if((ch = vigetkey()) == -1) { vichgflag = 0; - feep(); - return; + return 1; } /* do change */ if (ch == '\r' || ch == '\n') { @@ -513,47 +505,51 @@ vireplacechars(void) cs--; } vichgflag = 0; + return 0; } /**/ -void -vicmdmode(void) +int +vicmdmode(char **args) { if (invicmdmode() || selectkeymap("vicmd", 0)) - feep(); + return 1; undoing = 1; vichgflag = 0; if (cs != findbol()) cs--; + return 0; } /**/ -void -viopenlinebelow(void) +int +viopenlinebelow(char **args) { cs = findeol(); spaceinline(1); line[cs++] = '\n'; startvitext(1); clearlist = 1; + return 0; } /**/ -void -viopenlineabove(void) +int +viopenlineabove(char **args) { cs = findbol(); spaceinline(1); line[cs] = '\n'; startvitext(1); clearlist = 1; + return 0; } /**/ -void -vioperswapcase(void) +int +vioperswapcase(char **args) { - int oldcs, c2; + int oldcs, c2, ret = 1; /* get the range */ startvichange(1); @@ -569,22 +565,22 @@ vioperswapcase(void) } /* go back to the first line of the range */ cs = oldcs; + ret = 0; #if 0 vifirstnonblank(); #endif } vichgflag = 0; + return ret; } /**/ -void -virepeatchange(void) +int +virepeatchange(char **args) { /* make sure we have a change to repeat */ - if (!vichgbuf || vichgflag) { - feep(); - return; - } + if (!vichgbuf || vichgflag) + return 1; /* restore or update the saved count and buffer */ if (zmod.flags & MOD_MULT) { lastmod.mult = zmod.mult; @@ -598,11 +594,12 @@ virepeatchange(void) /* repeat the command */ inrepeat = 1; ungetkeys(vichgbuf, vichgbufptr); + return 0; } /**/ -void -viindent(void) +int +viindent(char **args) { int oldcs = cs, c2; @@ -610,14 +607,13 @@ viindent(void) startvichange(1); if ((c2 = getvirange(0)) == -1) { vichgflag = 0; - return; + return 1; } vichgflag = 0; /* must be a line range */ if (!vilinerange) { - feep(); cs = oldcs; - return; + return 1; } oldcs = cs; /* add a tab to the beginning of each line within range */ @@ -628,12 +624,13 @@ viindent(void) } /* go back to the first line of the range */ cs = oldcs; - vifirstnonblank(); + vifirstnonblank(zlenoargs); + return 0; } /**/ -void -viunindent(void) +int +viunindent(char **args) { int oldcs = cs, c2; @@ -641,14 +638,13 @@ viunindent(void) startvichange(1); if ((c2 = getvirange(0)) == -1) { vichgflag = 0; - return; + return 1; } vichgflag = 0; /* must be a line range */ if (!vilinerange) { - feep(); cs = oldcs; - return; + return 1; } oldcs = cs; /* remove a tab from the beginning of each line within range */ @@ -659,12 +655,13 @@ viunindent(void) } /* go back to the first line of the range */ cs = oldcs; - vifirstnonblank(); + vifirstnonblank(zlenoargs); + return 0; } /**/ -void -vibackwarddeletechar(void) +int +vibackwarddeletechar(char **args) { int n = zmult; @@ -672,16 +669,16 @@ vibackwarddeletechar(void) startvichange(-1); /* handle negative argument */ if (n < 0) { + int ret; zmult = -n; - videletechar(); + ret = videletechar(args); zmult = n; - return; + return ret; } /* It is an error to be at the beginning of the line, or (in * * insert mode) to delete past the beginning of insertion. */ if ((!invicmdmode() && cs - n < viinsbegin) || cs == findbol()) { - feep(); - return; + return 1; } /* Put argument into the acceptable range -- it is not an error to * * specify a greater count than the number of available characters. */ @@ -689,41 +686,39 @@ vibackwarddeletechar(void) n = cs - findbol(); /* do the deletion */ backkill(n, 1); + return 0; } /**/ -void -vikillline(void) +int +vikillline(char **args) { - if (viinsbegin > cs) { - feep(); - return; - } + if (viinsbegin > cs) + return 1; backdel(cs - viinsbegin); + return 0; } /**/ -void -viputbefore(void) +int +viputbefore(char **args) { Cutbuffer buf = &cutbuf; int n = zmult; startvichange(-1); if (n < 0) - return; + return 1; if (zmod.flags & MOD_VIBUF) buf = &vibuf[zmod.vibuf]; - if (!buf->buf) { - feep(); - return; - } + if (!buf->buf) + return 1; if(buf->flags & CUTBUFFER_LINE) { cs = findbol(); spaceinline(buf->len + 1); memcpy((char *)line + cs, buf->buf, buf->len); line[cs + buf->len] = '\n'; - vifirstnonblank(); + vifirstnonblank(zlenoargs); } else { while (n--) { spaceinline(buf->len); @@ -733,30 +728,29 @@ viputbefore(void) if (cs) cs--; } + return 0; } /**/ -void -viputafter(void) +int +viputafter(char **args) { Cutbuffer buf = &cutbuf; int n = zmult; startvichange(-1); if (n < 0) - return; + return 1; if (zmod.flags & MOD_VIBUF) buf = &vibuf[zmod.vibuf]; - if (!buf->buf) { - feep(); - return; - } + if (!buf->buf) + return 1; if(buf->flags & CUTBUFFER_LINE) { cs = findeol(); spaceinline(buf->len + 1); line[cs++] = '\n'; memcpy((char *)line + cs, buf->buf, buf->len); - vifirstnonblank(); + vifirstnonblank(zlenoargs); } else { if (cs != findeol()) cs++; @@ -768,20 +762,18 @@ viputafter(void) if (cs) cs--; } - + return 0; } /**/ -void -vijoin(void) +int +vijoin(char **args) { int x; startvichange(-1); - if ((x = findeol()) == ll) { - feep(); - return; - } + if ((x = findeol()) == ll) + return 1; cs = x + 1; for (x = 1; cs != ll && iblank(line[cs]); cs++, x++); backdel(x); @@ -791,17 +783,18 @@ vijoin(void) spaceinline(1); line[cs] = ' '; } + return 0; } /**/ -void -viswapcase(void) +int +viswapcase(char **args) { int eol, n = zmult; startvichange(-1); if (n < 1) - return; + return 1; eol = findeol(); while (cs < eol && n--) { if (islower(line[cs])) @@ -812,11 +805,12 @@ viswapcase(void) } if (cs && cs == eol) cs--; + return 0; } /**/ -void -vicapslockpanic(void) +int +vicapslockpanic(char **args) { clearlist = 1; zbeep(); @@ -825,20 +819,19 @@ vicapslockpanic(void) zrefresh(); while (!islower(getkey(0))); statusline = NULL; + return 0; } /**/ -void -visetbuffer(void) +int +visetbuffer(char **args) { int ch; if ((zmod.flags & MOD_VIBUF) || (((ch = getkey(0)) < '1' || ch > '9') && - (ch < 'a' || ch > 'z') && (ch < 'A' || ch > 'Z'))) { - feep(); - return; - } + (ch < 'a' || ch > 'z') && (ch < 'A' || ch > 'Z'))) + return 1; if (ch >= 'A' && ch <= 'Z') /* needed in cut() */ zmod.flags |= MOD_VIAPP; else @@ -846,32 +839,33 @@ visetbuffer(void) zmod.vibuf = tulower(ch) + (idigit(ch) ? -'1' + 26 : -'a'); zmod.flags |= MOD_VIBUF; prefixflag = 1; + return 0; } /**/ -void -vikilleol(void) +int +vikilleol(char **args) { int n = findeol() - cs; startvichange(-1); if (!n) { /* error -- line already empty */ - feep(); - return; + return 1; } /* delete to end of line */ forekill(findeol() - cs, 0); + return 0; } /**/ -void -vipoundinsert(void) +int +vipoundinsert(char **args) { int oldcs = cs; startvichange(-1); - vifirstnonblank(); + vifirstnonblank(zlenoargs); if(line[cs] != '#') { spaceinline(1); line[cs] = '#'; @@ -884,11 +878,12 @@ vipoundinsert(void) viinsbegin--; cs = oldcs - (cs < oldcs); } + return 0; } /**/ -void -viquotedinsert(void) +int +viquotedinsert(char **args) { #ifndef HAS_TIO struct sgttyb sob; @@ -908,23 +903,23 @@ viquotedinsert(void) #endif foredel(1); if(c < 0) - feep(); + return 1; else - selfinsert(); + return selfinsert(args); } /* the 0 key in vi: continue a repeat count in the manner of * * digit-argument if possible, otherwise do vi-beginning-of-line. */ /**/ -void -vidigitorbeginningofline(void) +int +vidigitorbeginningofline(char **args) { if(zmod.flags & MOD_TMULT) - digitargument(); + return digitargument(args); else { removesuffix(); invalidatelist(); - vibeginningofline(); + return vibeginningofline(args); } } diff --git a/Src/Zle/zle_word.c b/Src/Zle/zle_word.c index f446d1769..31f83a2df 100644 --- a/Src/Zle/zle_word.c +++ b/Src/Zle/zle_word.c @@ -31,38 +31,41 @@ #include "zle_word.pro" /**/ -void -forwardword(void) +int +forwardword(char **args) { int n = zmult; if (n < 0) { + int ret; zmult = -n; - backwardword(); + ret = backwardword(args); zmult = n; - return; + return ret; } while (n--) { while (cs != ll && iword(line[cs])) cs++; if (wordflag && !n) - return; + return 0; while (cs != ll && !iword(line[cs])) cs++; } + return 0; } /**/ -void -viforwardword(void) +int +viforwardword(char **args) { int n = zmult; if (n < 0) { + int ret; zmult = -n; - backwardword(); + ret = backwardword(args); zmult = n; - return; + return ret; } while (n--) { if (iident(line[cs])) @@ -72,64 +75,69 @@ viforwardword(void) while (cs != ll && !iident(line[cs]) && !iblank(line[cs])) cs++; if (wordflag && !n) - return; + return 0; while (cs != ll && (iblank(line[cs]) || line[cs] == '\n')) cs++; } + return 0; } /**/ -void -viforwardblankword(void) +int +viforwardblankword(char **args) { int n = zmult; if (n < 0) { + int ret; zmult = -n; - vibackwardblankword(); + ret = vibackwardblankword(args); zmult = n; - return; + return ret; } while (n--) { while (cs != ll && !iblank(line[cs])) cs++; if (wordflag && !n) - return; + return 0; while (cs != ll && iblank(line[cs])) cs++; } + return 0; } /**/ -void -emacsforwardword(void) +int +emacsforwardword(char **args) { int n = zmult; if (n < 0) { + int ret; zmult = -n; - emacsbackwardword(); + ret = emacsbackwardword(args); zmult = n; - return; + return ret; } while (n--) { while (cs != ll && !iword(line[cs])) cs++; if (wordflag && !n) - return; + return 0; while (cs != ll && iword(line[cs])) cs++; } + return 0; } /**/ -void -viforwardblankwordend(void) +int +viforwardblankwordend(char **args) { int n = zmult; if (n < 0) - return; + return 1; while (n--) { while (cs != ll && iblank(line[cs + 1])) cs++; @@ -138,19 +146,21 @@ viforwardblankwordend(void) } if (cs != ll && virangeflag) cs++; + return 0; } /**/ -void -viforwardwordend(void) +int +viforwardwordend(char **args) { int n = zmult; if (n < 0) { + int ret; zmult = -n; - backwardword(); + ret = backwardword(args); zmult = n; - return; + return ret; } while (n--) { if (iblank(line[cs + 1])) @@ -165,19 +175,21 @@ viforwardwordend(void) } if (cs != ll && virangeflag) cs++; + return 0; } /**/ -void -backwardword(void) +int +backwardword(char **args) { int n = zmult; if (n < 0) { + int ret; zmult = -n; - forwardword(); + ret = forwardword(args); zmult = n; - return; + return ret; } while (n--) { while (cs && !iword(line[cs - 1])) @@ -185,19 +197,21 @@ backwardword(void) while (cs && iword(line[cs - 1])) cs--; } + return 0; } /**/ -void -vibackwardword(void) +int +vibackwardword(char **args) { int n = zmult; if (n < 0) { + int ret; zmult = -n; - backwardword(); + ret = backwardword(args); zmult = n; - return; + return ret; } while (n--) { while (cs && iblank(line[cs - 1])) @@ -209,19 +223,21 @@ vibackwardword(void) while (cs && !iident(line[cs - 1]) && !iblank(line[cs - 1])) cs--; } + return 0; } /**/ -void -vibackwardblankword(void) +int +vibackwardblankword(char **args) { int n = zmult; if (n < 0) { + int ret; zmult = -n; - viforwardblankword(); + ret = viforwardblankword(args); zmult = n; - return; + return ret; } while (n--) { while (cs && iblank(line[cs - 1])) @@ -229,19 +245,21 @@ vibackwardblankword(void) while (cs && !iblank(line[cs - 1])) cs--; } + return 0; } /**/ -void -emacsbackwardword(void) +int +emacsbackwardword(char **args) { int n = zmult; if (n < 0) { + int ret; zmult = -n; - emacsforwardword(); + ret = emacsforwardword(args); zmult = n; - return; + return ret; } while (n--) { while (cs && !iword(line[cs - 1])) @@ -249,19 +267,21 @@ emacsbackwardword(void) while (cs && iword(line[cs - 1])) cs--; } + return 0; } /**/ -void -backwarddeleteword(void) +int +backwarddeleteword(char **args) { int x = cs, n = zmult; if (n < 0) { + int ret; zmult = -n; - deleteword(); + ret = deleteword(args); zmult = n; - return; + return ret; } while (n--) { while (x && !iword(line[x - 1])) @@ -270,19 +290,18 @@ backwarddeleteword(void) x--; } backdel(cs - x); + return 0; } /**/ -void -vibackwardkillword(void) +int +vibackwardkillword(char **args) { int x = cs, lim = (viinsbegin > findbol()) ? viinsbegin : findbol(); int n = zmult; - if (n < 0) { - feep(); - return; - } + if (n < 0) + return 1; /* this taken from "vibackwardword" */ while (n--) { while ((x > lim) && iblank(line[x - 1])) @@ -295,20 +314,22 @@ vibackwardkillword(void) x--; } backkill(cs - x, 1); + return 0; } /**/ -void -backwardkillword(void) +int +backwardkillword(char **args) { int x = cs; int n = zmult; if (n < 0) { + int ret; zmult = -n; - killword(); + ret = killword(args); zmult = n; - return; + return ret; } while (n--) { while (x && !iword(line[x - 1])) @@ -317,11 +338,12 @@ backwardkillword(void) x--; } backkill(cs - x, 1); + return 0; } /**/ -void -upcaseword(void) +int +upcaseword(char **args) { int n = zmult; int neg = n < 0, ocs = cs; @@ -338,11 +360,12 @@ upcaseword(void) } if (neg) cs = ocs; + return 0; } /**/ -void -downcaseword(void) +int +downcaseword(char **args) { int n = zmult; int neg = n < 0, ocs = cs; @@ -359,11 +382,12 @@ downcaseword(void) } if (neg) cs = ocs; + return 0; } /**/ -void -capitalizeword(void) +int +capitalizeword(char **args) { int first, n = zmult; int neg = n < 0, ocs = cs; @@ -384,20 +408,22 @@ capitalizeword(void) } if (neg) cs = ocs; + return 0; } /**/ -void -deleteword(void) +int +deleteword(char **args) { int x = cs; int n = zmult; if (n < 0) { + int ret; zmult = -n; - backwarddeleteword(); + ret = backwarddeleteword(args); zmult = n; - return; + return ret; } while (n--) { while (x != ll && !iword(line[x])) @@ -406,20 +432,22 @@ deleteword(void) x++; } foredel(x - cs); + return 0; } /**/ -void -killword(void) +int +killword(char **args) { int x = cs; int n = zmult; if (n < 0) { + int ret; zmult = -n; - backwardkillword(); + ret = backwardkillword(args); zmult = n; - return; + return ret; } while (n--) { while (x != ll && !iword(line[x])) @@ -428,11 +456,12 @@ killword(void) x++; } forekill(x - cs, 0); + return 0; } /**/ -void -transposewords(void) +int +transposewords(char **args) { int p1, p2, p3, p4, x = cs; char *temp, *pp; @@ -448,22 +477,16 @@ transposewords(void) x = cs; while (x && line[x - 1] != '\n' && !iword(line[x])) x--; - if (!x || line[x - 1] == '\n') { - feep(); - return; - } + if (!x || line[x - 1] == '\n') + return 1; } for (p4 = x; p4 != ll && iword(line[p4]); p4++); for (p3 = p4; p3 && iword(line[p3 - 1]); p3--); - if (!p3) { - feep(); - return; - } + if (!p3) + return 1; for (p2 = p3; p2 && !iword(line[p2 - 1]); p2--); - if (!p2) { - feep(); - return; - } + if (!p2) + return 1; for (p1 = p2; p1 && iword(line[p1 - 1]); p1--); pp = temp = (char *)zhalloc(p4 - p1 + 1); struncpy(&pp, (char *) line + p3, p4 - p3); @@ -474,4 +497,5 @@ transposewords(void) } if (neg) cs = ocs; + return 0; } diff --git a/Src/builtin.c b/Src/builtin.c index d74d9cd88..8fe112cb5 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -50,7 +50,7 @@ static struct builtin builtins[] = BUILTIN("cd", 0, bin_cd, 0, 2, BIN_CD, NULL, NULL), BUILTIN("chdir", 0, bin_cd, 0, 2, BIN_CD, NULL, NULL), BUILTIN("continue", BINF_PSPECIAL, bin_break, 0, 1, BIN_CONTINUE, NULL, NULL), - BUILTIN("declare", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRTUZafilrtux", NULL), + BUILTIN("declare", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRTUZafgilrtux", NULL), BUILTIN("dirs", 0, bin_dirs, 0, -1, 0, "v", NULL), BUILTIN("disable", 0, bin_enable, 0, -1, BIN_DISABLE, "afmr", NULL), BUILTIN("disown", 0, bin_fg, 0, -1, BIN_DISOWN, NULL, NULL), @@ -60,7 +60,7 @@ static struct builtin builtins[] = BUILTIN("enable", 0, bin_enable, 0, -1, BIN_ENABLE, "afmr", NULL), BUILTIN("eval", BINF_PSPECIAL, bin_eval, 0, -1, BIN_EVAL, NULL, NULL), BUILTIN("exit", BINF_PSPECIAL, bin_break, 0, 1, BIN_EXIT, NULL, NULL), - BUILTIN("export", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, BIN_EXPORT, "LRTUZafilrtu", "x"), + BUILTIN("export", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, BIN_EXPORT, "LRTUZafilrtu", "xg"), BUILTIN("false", 0, bin_false, 0, -1, 0, NULL, NULL), BUILTIN("fc", BINF_FCOPTS, bin_fc, 0, -1, BIN_FC, "nlreIRWAdDfEim", NULL), BUILTIN("fg", 0, bin_fg, 0, -1, BIN_FG, NULL, NULL), @@ -74,7 +74,7 @@ static struct builtin builtins[] = #endif BUILTIN("history", 0, bin_fc, 0, -1, BIN_FC, "nrdDfEim", "l"), - BUILTIN("integer", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "lrtux", "i"), + BUILTIN("integer", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "glrtux", "i"), BUILTIN("jobs", 0, bin_fg, 0, -1, BIN_JOBS, "dlpZrs", NULL), BUILTIN("kill", 0, bin_kill, 0, -1, 0, NULL, NULL), BUILTIN("let", 0, bin_let, 1, -1, 0, NULL, NULL), @@ -93,7 +93,7 @@ static struct builtin builtins[] = BUILTIN("pwd", 0, bin_pwd, 0, 0, 0, "rLP", NULL), BUILTIN("r", BINF_R, bin_fc, 0, -1, BIN_FC, "nrl", NULL), BUILTIN("read", 0, bin_read, 0, -1, 0, "rzu0123456789pkqecnAlE", NULL), - BUILTIN("readonly", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRTUZafiltux", "r"), + BUILTIN("readonly", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRTUZafgiltux", "r"), BUILTIN("rehash", 0, bin_hash, 0, 0, 0, "dfv", "r"), BUILTIN("return", BINF_PSPECIAL, bin_break, 0, 1, BIN_RETURN, NULL, NULL), BUILTIN("set", BINF_PSPECIAL, bin_set, 0, -1, 0, NULL, NULL), @@ -107,7 +107,7 @@ static struct builtin builtins[] = BUILTIN("trap", BINF_PSPECIAL, bin_trap, 0, -1, 0, NULL, NULL), BUILTIN("true", 0, bin_true, 0, -1, 0, NULL, NULL), BUILTIN("type", 0, bin_whence, 0, -1, 0, "ampfsw", "v"), - BUILTIN("typeset", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRTUZafilrtuxm", NULL), + BUILTIN("typeset", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRTUZafgilrtuxm", NULL), BUILTIN("umask", 0, bin_umask, 0, 1, 0, "S", NULL), BUILTIN("unalias", 0, bin_unhash, 1, -1, 0, "m", "a"), BUILTIN("unfunction", 0, bin_unhash, 1, -1, 0, "m", "f"), @@ -120,7 +120,9 @@ static struct builtin builtins[] = BUILTIN("which", 0, bin_whence, 0, -1, 0, "ampsw", "c"), #ifdef DYNAMIC - BUILTIN("zmodload", 0, bin_zmodload, 0, -1, 0, "ILabcdipu", NULL), + BUILTIN("zmodload", 0, bin_zmodload, 0, -1, 0, "ILabcdipue", NULL), +#else + BUILTIN("zmodload", 0, bin_zmodload, 0, -1, 0, "e", NULL), #endif }; @@ -351,7 +353,8 @@ execbuiltin(LinkList args, Builtin bn) /* display execution trace information, if required */ if (xtr) { - fprintf(stderr, "%s%s", (prompt4) ? prompt4 : "", name); + printprompt4(); + fprintf(stderr, "%s", name); if (xarg) fprintf(stderr, " %s", xarg); while (*oargv) @@ -1349,7 +1352,7 @@ fclist(FILE *f, int n, int r, int D, int d, int first, int last, struct asgment fclistdone = 1; ent = gethistent(first, first < last? GETHIST_DOWNWARD : GETHIST_UPWARD); - if (!ent || ent->histnum < first || ent->histnum > last) { + if (!ent || (first < last? ent->histnum > last : ent->histnum < last)) { if (first == last) zwarnnam("fc", "no such event: %d", NULL, first); else @@ -1491,8 +1494,14 @@ typeset_single(char *cname, char *pname, Param pm, int func, { int usepm, tc, keeplocal = 0; - /* use the existing pm? */ - usepm = pm && !(pm->flags & (PM_UNSET | PM_AUTOLOAD)); + /* + * Do we use the existing pm? Note that this isn't the end of the + * story, because if we try and create a new pm at the same + * locallevel as an unset one we use the pm struct anyway: that's + * handled in createparam(). Here we just avoid using it for the + * present tests if it's unset. + */ + usepm = pm && !(pm->flags & PM_UNSET); /* Always use an existing pm if special at current locallevel */ if (pm && (pm->flags & PM_SPECIAL) && pm->level == locallevel) @@ -1501,15 +1510,15 @@ typeset_single(char *cname, char *pname, Param pm, int func, /* * Don't use a non-special existing param if * - the local level has changed, and - * - the function is not `export'. + * - we are really locallizing the parameter */ if (usepm && !(pm->flags & PM_SPECIAL) && - locallevel != pm->level && func != BIN_EXPORT) + locallevel != pm->level && (on & PM_LOCAL)) usepm = 0; /* attempting a type conversion, or making a tied colonarray? */ if ((tc = usepm && (((off & pm->flags) | (on & ~pm->flags)) & - (PM_INTEGER|PM_HASHED|PM_ARRAY|PM_TIED)))) + (PM_INTEGER|PM_HASHED|PM_ARRAY|PM_TIED|PM_AUTOLOAD)))) usepm = 0; if (tc && (pm->flags & PM_SPECIAL)) { zerrnam(cname, "%s: can't change type of a special parameter", @@ -1518,6 +1527,7 @@ typeset_single(char *cname, char *pname, Param pm, int func, } if (usepm) { + on &= ~PM_LOCAL; if (!on && !roff && !value) { paramtab->printnode((HashNode)pm, 0); return pm; @@ -1604,7 +1614,7 @@ typeset_single(char *cname, char *pname, Param pm, int func, if (keeplocal) pm->level = keeplocal; - else if (func != BIN_EXPORT) + else if (on & PM_LOCAL) pm->level = locallevel; if (value && !(pm->flags & (PM_ARRAY|PM_HASHED))) setsparam(pname, ztrdup(value)); @@ -1677,6 +1687,9 @@ bin_typeset(char *name, char **argv, char *ops, int func) return 0; } + if (!ops['g']) + on |= PM_LOCAL; + if (on & PM_TIED) { Param apm; struct asgment asg0; @@ -3073,7 +3086,7 @@ bin_emulate(char *nam, char **argv, char *ops, int func) { emulate(*argv, ops['R']); if (ops['L']) - dosetopt(LOCALOPTIONS, 1, 0); + opts[LOCALOPTIONS] = opts[LOCALTRAPS] = 1; return 0; } @@ -3121,7 +3134,7 @@ bin_read(char *name, char **args, char *ops, int func) char *reply, *readpmpt; int bsiz, c = 0, gotnl = 0, al = 0, first, nchars = 1, bslash; int haso = 0; /* true if /dev/tty has been opened specially */ - int isem = !strcmp(term, "emacs"); + int isem = !strcmp(term, "emacs"), izle = zleactive && getkeyptr; char *buf, *bptr, *firstarg, *zbuforig; LinkList readll = newlinklist(); @@ -3146,33 +3159,37 @@ bin_read(char *name, char **args, char *ops, int func) return compctlread(name, args, ops, reply); if ((ops['k'] && !ops['u'] && !ops['p']) || ops['q']) { - if (SHTTY == -1) { - /* need to open /dev/tty specially */ - SHTTY = open("/dev/tty", O_RDWR|O_NOCTTY); - haso = 1; - } - /* We should have a SHTTY opened by now. */ - if (SHTTY == -1) { - /* Unfortunately, we didn't. */ - fprintf(stderr, "not interactive and can't open terminal\n"); - fflush(stderr); - return 1; + if (!zleactive) { + if (SHTTY == -1) { + /* need to open /dev/tty specially */ + SHTTY = open("/dev/tty", O_RDWR|O_NOCTTY); + haso = 1; + } + /* We should have a SHTTY opened by now. */ + if (SHTTY == -1) { + /* Unfortunately, we didn't. */ + fprintf(stderr, "not interactive and can't open terminal\n"); + fflush(stderr); + return 1; + } + if (unset(INTERACTIVE)) + gettyinfo(&shttyinfo); + /* attach to the tty */ + attachtty(mypgrp); + if (!isem && ops['k']) + setcbreak(); + readfd = SHTTY; } - if (unset(INTERACTIVE)) - gettyinfo(&shttyinfo); - /* attach to the tty */ - attachtty(mypgrp); - if (!isem && ops['k']) - setcbreak(); - readfd = SHTTY; } else if (ops['u'] && !ops['p']) { /* -u means take input from the specified file descriptor. * * -up means take input from the coprocess. */ for (readfd = 9; readfd && !ops[readfd + '0']; --readfd); - } else if (ops['p']) + izle = 0; + } else if (ops['p']) { readfd = coprocin; - else - readfd = 0; + izle = 0; + } else + readfd = izle = 0; /* handle prompt */ if (firstarg) { @@ -3196,18 +3213,25 @@ bin_read(char *name, char **args, char *ops, int func) bptr = buf = (char *)zalloc(nchars+1); do { - /* If read returns 0, is end of file */ - if ((val = read(readfd, bptr, nchars)) <= 0) - break; + if (izle) { + if ((val = getkeyptr(0)) < 0) + break; + *bptr++ = (char) val; + nchars--; + } else { + /* If read returns 0, is end of file */ + if ((val = read(readfd, bptr, nchars)) <= 0) + break; - /* decrement number of characters read from number required */ - nchars -= val; + /* decrement number of characters read from number required */ + nchars -= val; - /* increment pointer past read characters */ - bptr += val; + /* increment pointer past read characters */ + bptr += val; + } } while (nchars > 0); - if (!ops['u'] && !ops['p']) { + if (!izle && !ops['u'] && !ops['p']) { /* dispose of result appropriately, etc. */ if (isem) while (val > 0 && read(SHTTY, &d, 1) == 1 && d != '\n'); @@ -3236,14 +3260,19 @@ bin_read(char *name, char **args, char *ops, int func) readbuf[1] = '\0'; /* get, and store, reply */ - readbuf[0] = ((char)getquery(NULL, 0)) == 'y' ? 'y' : 'n'; + if (izle) { + int key = getkeyptr(0); - /* dispose of result appropriately, etc. */ - if (haso) { - close(SHTTY); - SHTTY = -1; - } + readbuf[0] = (key == 'y' ? 'y' : 'n'); + } else { + readbuf[0] = ((char)getquery(NULL, 0)) == 'y' ? 'y' : 'n'; + /* dispose of result appropriately, etc. */ + if (haso) { + close(SHTTY); + SHTTY = -1; + } + } if (ops['e'] || ops['E']) printf("%s\n", readbuf); if (!ops['e']) @@ -3265,7 +3294,7 @@ bin_read(char *name, char **args, char *ops, int func) buf = bptr = (char *)zalloc(bsiz = 64); /* get input, a character at a time */ while (!gotnl) { - c = zread(); + c = zread(izle); /* \ at the end of a line indicates a continuation * * line, except in raw mode (-r option) */ if (bslash && c == '\n') { @@ -3355,7 +3384,7 @@ bin_read(char *name, char **args, char *ops, int func) bslash = 0; if (!gotnl) for (;;) { - c = zread(); + c = zread(izle); /* \ at the end of a line introduces a continuation line, except in raw mode (-r option) */ if (bslash && c == '\n') { @@ -3419,10 +3448,15 @@ bin_read(char *name, char **args, char *ops, int func) /**/ static int -zread(void) +zread(int izle) { char cc, retry = 0; + if (izle) { + int c = getkeyptr(0); + + return (c < 0 ? EOF : c); + } /* use zbuf if possible */ if (zbuf) { /* If zbuf points to anything, it points to the next character in the @@ -3618,7 +3652,7 @@ bin_trap(char *name, char **argv, char *ops, int func) arg = *argv++; if (!*arg) l = NULL; - else if (!(l = parse_string(arg))) { + else if (!(l = parse_string(arg, 0))) { zwarnnam(name, "couldn't parse trap command", NULL, 0); return 1; } diff --git a/Src/exec.c b/Src/exec.c index 5cfe3e3ef..5ae4f0d33 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -133,14 +133,17 @@ static int doneps4; /**/ List -parse_string(char *s) +parse_string(char *s, int ln) { List l; + int oldlineno = lineno; lexsave(); - inpush(s, 0, NULL); + inpush(s, (ln ? INP_LINENO : 0), NULL); strinbeg(0); + lineno = ln ? 1 : -1; l = parse_list(); + lineno = oldlineno; strinend(); inpop(); lexrestore(); @@ -301,7 +304,9 @@ execcursh(Cmd cmd, LinkList args, int flags) { if (!list_pipe) deletejob(jobtab + thisjob); + cmdpush(CS_CURSH); execlist(cmd->u.list, 1, flags & CFLAG_EXEC); + cmdpop(); return lastval; } @@ -354,7 +359,9 @@ zexecve(char *pth, char **argv) if (execvebuf[1] == '!') { for (t0 = 0; t0 != ct; t0++) if (execvebuf[t0] == '\n') - execvebuf[t0] = '\0'; + break; + while (inblank(execvebuf[t0])) + execvebuf[t0--] = '\0'; execvebuf[POUNDBANGLIMIT] = '\0'; for (ptr = execvebuf + 2; *ptr && *ptr == ' '; ptr++); for (ptr2 = ptr; *ptr && *ptr != ' '; ptr++); @@ -676,7 +683,7 @@ execstring(char *s, int dont_change_job, int exiting) List list; pushheap(); - if ((list = parse_string(s))) + if ((list = parse_string(s, 0))) execlist(list, dont_change_job, exiting); popheap(); } @@ -694,8 +701,8 @@ execlist(List list, int dont_change_job, int exiting) { Sublist slist; static int donetrap; - int ret, cj; - int old_pline_level, old_list_pipe; + int ret, cj, csp; + int old_pline_level, old_list_pipe, oldlineno; /* * ERREXIT only forces the shell to exit if the last command in a && * or || fails. This is the case even if an earlier command is a @@ -707,6 +714,7 @@ execlist(List list, int dont_change_job, int exiting) cj = thisjob; old_pline_level = pline_level; old_list_pipe = list_pipe; + oldlineno = lineno; if (sourcelevel && unset(SHINSTDIN)) pline_level = list_pipe = 0; @@ -718,6 +726,7 @@ execlist(List list, int dont_change_job, int exiting) * called once for each sublist that fails. */ donetrap = 0; slist = list->left; + csp = cmdsp; /* Loop through code followed by &&, ||, or end of sublist. */ while (slist) { @@ -744,6 +753,7 @@ execlist(List list, int dont_change_job, int exiting) goto sublist_done; } } + cmdpush(CS_CMDAND); break; case ORNEXT: /* If the return code is zero, we skip pipelines until * @@ -760,12 +770,14 @@ execlist(List list, int dont_change_job, int exiting) goto sublist_done; } } + cmdpush(CS_CMDOR); break; } slist = slist->right; } sublist_done: + cmdsp = csp; noerrexit = oldnoerrexit; if (sigtrapped[SIGDEBUG]) @@ -794,6 +806,7 @@ sublist_done: pline_level = old_pline_level; list_pipe = old_list_pipe; + lineno = oldlineno; if (dont_change_job) thisjob = cj; } @@ -888,6 +901,9 @@ execpline(Sublist l, int how, int last1) DPUTS(!list_pipe_pid, "invalid list_pipe_pid"); addproc(list_pipe_pid, list_pipe_text); + if (!jn->procs->next) + jn->gleader = mypgrp; + for (pn = jobtab[jn->other].procs; pn; pn = pn->next) if (WIFSTOPPED(pn->status)) break; @@ -901,12 +917,14 @@ execpline(Sublist l, int how, int last1) jn->stat |= STAT_STOPPED | STAT_CHANGED; printjob(jn, !!isset(LONGLISTJOBS), 1); } - else + else if (newjob != list_pipe_job) deletejob(jn); + else + lastwj = -1; } for (; !nowait;) { - if (list_pipe_child) { + if (list_pipe_child || pline_level) { jn->stat |= STAT_NOPRINT; makerunning(jn); } @@ -917,8 +935,11 @@ execpline(Sublist l, int how, int last1) jn->stat & STAT_DONE && lastval2 & 0200) killpg(mypgrp, lastval2 & ~0200); - if ((list_pipe || last1) && !list_pipe_child && - jn->stat & STAT_STOPPED) { + if ((list_pipe || last1 || pline_level) && + !list_pipe_child && + ((jn->stat & STAT_STOPPED) || + (list_pipe_job && pline_level && + (jobtab[list_pipe_job].stat & STAT_STOPPED)))) { pid_t pid; int synch[2]; @@ -944,21 +965,28 @@ execpline(Sublist l, int how, int last1) close(synch[1]); read(synch[0], &dummy, 1); close(synch[0]); - jobtab[list_pipe_job].other = newjob; - jobtab[list_pipe_job].stat |= STAT_SUPERJOB; - jn->stat |= STAT_SUBJOB | STAT_NOPRINT; - jn->other = pid; - killpg(jobtab[list_pipe_job].gleader, SIGSTOP); + /* If this job has finished, we leave it as a + * normal (non-super-) job. */ + if (!(jn->stat & STAT_DONE)) { + jobtab[list_pipe_job].other = newjob; + jobtab[list_pipe_job].stat |= STAT_SUPERJOB; + jn->stat |= STAT_SUBJOB | STAT_NOPRINT; + jn->other = pid; + } + if ((list_pipe || last1) && jobtab[list_pipe_job].procs) + killpg(jobtab[list_pipe_job].gleader, SIGSTOP); break; } else { close(synch[0]); entersubsh(Z_ASYNC, 0, 0); - setpgrp(0L, mypgrp = jobtab[list_pipe_job].gleader); + if (jobtab[list_pipe_job].procs) + setpgrp(0L, mypgrp = jobtab[list_pipe_job].gleader); close(synch[1]); kill(getpid(), SIGSTOP); list_pipe = 0; list_pipe_child = 1; + opts[INTERACTIVE] = 0; break; } } @@ -975,7 +1003,8 @@ execpline(Sublist l, int how, int last1) jn->stat |= STAT_NOPRINT; killjb(jobtab + pj, lastval & ~0200); } - if (list_pipe_child || (list_pipe && (jn->stat & STAT_DONE))) + if (list_pipe_child || ((list_pipe || pline_level) && + (jn->stat & STAT_DONE))) deletejob(jn); thisjob = pj; @@ -998,19 +1027,19 @@ execpline2(Pline pline, int how, int input, int output, int last1) { pid_t pid; int pipes[2]; - int oldlineno; if (breaks || retflag) return; - oldlineno = lineno; - lineno = pline->left->lineno; + if (pline->left->lineno >= 0) + lineno = pline->left->lineno; - if (pline_level == 1) + if (pline_level == 1) { if (!sfcontext) strcpy(list_pipe_text, getjobtext((void *) pline->left)); else list_pipe_text[0] = '\0'; + } if (pline->type == END) execcmd(pline->left, input, output, how, last1 ? 1 : 2); else { @@ -1054,15 +1083,15 @@ execpline2(Pline pline, int how, int input, int output, int last1) if (pline->right) { /* if another execpline() is invoked because the command is * * a list it must know that we're already in a pipeline */ + cmdpush(CS_PIPE); list_pipe = 1; execpline2(pline->right, how, pipes[0], output, last1); list_pipe = old_list_pipe; + cmdpop(); zclose(pipes[0]); subsh_close = -1; } } - - lineno = oldlineno; } /* make the argv array */ @@ -1079,7 +1108,7 @@ makecline(LinkList list) argv = 2 + (char **) ncalloc((countlinknodes(list) + 4) * sizeof(char *)); if (isset(XTRACE)) { if (!doneps4) - fprintf(stderr, "%s", (prompt4) ? prompt4 : ""); + printprompt4(); for (node = firstnode(list); node; incnode(node)) { *ptr++ = (char *)getdata(node); @@ -1283,7 +1312,7 @@ addvars(LinkList l, int export) xtr = isset(XTRACE); if (xtr && nonempty(l)) { - fprintf(stderr, "%s", prompt4 ? prompt4 : ""); + printprompt4(); doneps4 = 1; } @@ -2179,8 +2208,9 @@ entersubsh(int how, int cl, int fake) attachtty(jobtab[thisjob].gleader); } } - else if (!jobtab[thisjob].gleader || - (setpgrp(0L, jobtab[thisjob].gleader) == -1)) { + else if (!(list_pipe || list_pipe_child || pline_level > 1) && + (!jobtab[thisjob].gleader || + setpgrp(0L, jobtab[thisjob].gleader) == -1)) { jobtab[thisjob].gleader = getpid(); if (list_pipe_job != thisjob && !jobtab[list_pipe_job].gleader) @@ -2322,7 +2352,7 @@ getoutput(char *cmd, int qt) Cmd c; Redir r; - if (!(list = parse_string(cmd))) + if (!(list = parse_string(cmd, 0))) return NULL; if (list != &dummy_list && !list->right && !list->left->flags && list->left->type == END && list->left->left->type == END && @@ -2451,7 +2481,7 @@ parsecmd(char *cmd) return NULL; } *str = '\0'; - if (str[1] || !(list = parse_string(cmd + 2))) { + if (str[1] || !(list = parse_string(cmd + 2, 0))) { zerr("parse error in process substitution", NULL, 0); return NULL; } @@ -2661,7 +2691,8 @@ execcond(Cmd cmd, LinkList args, int flags) { int stat; if (isset(XTRACE)) { - fprintf(stderr, "%s[[", prompt4 ? prompt4 : ""); + printprompt4(); + fprintf(stderr, "[["); tracingcond++; } stat = !evalcond(cmd->u.cond); @@ -2682,8 +2713,10 @@ execarith(Cmd cmd, LinkList args, int flags) char *e; zlong val = 0; - if (isset(XTRACE)) - fprintf(stderr, "%s((", prompt4 ? prompt4 : ""); + if (isset(XTRACE)) { + printprompt4(); + fprintf(stderr, "(("); + } if (args) while ((e = (char *) ugetnode(args))) { if (isset(XTRACE)) @@ -2759,21 +2792,22 @@ static void execshfunc(Cmd cmd, Shfunc shf, LinkList args) { LinkList last_file_list = NULL; + unsigned char *ocs; + int ocsp; if (errflag) return; - if (!list_pipe) { + if (!list_pipe && thisjob != list_pipe_job) { /* Without this deletejob the process table * * would be filled by a recursive function. */ last_file_list = jobtab[thisjob].filelist; jobtab[thisjob].filelist = NULL; deletejob(jobtab + thisjob); } - if (isset(XTRACE)) { LinkNode lptr; - fprintf(stderr, "%s", prompt4 ? prompt4 : prompt4); + printprompt4(); if (args) for (lptr = firstnode(args); lptr; incnode(lptr)) { if (lptr != firstnode(args)) @@ -2783,8 +2817,14 @@ execshfunc(Cmd cmd, Shfunc shf, LinkList args) fputc('\n', stderr); fflush(stderr); } - + ocs = cmdstack; + ocsp = cmdsp; + cmdstack = (unsigned char *) zalloc(CMDSTACKSZ); + cmdsp = 0; doshfunc(shf->nam, shf->funcdef, args, shf->flags, 0); + free(cmdstack); + cmdstack = ocs; + cmdsp = ocsp; if (!list_pipe) deletefilelist(last_file_list); @@ -2842,9 +2882,8 @@ doshfunc(char *name, List list, LinkList doshargs, int flags, int noreturnval) * was executed. */ { char **tab, **x, *oargv0 = NULL; - int xexittr, newexittr, oldzoptind, oldlastval; - void *xexitfn, *newexitfn; - char saveopts[OPT_SIZE]; + int oldzoptind, oldlastval; + char saveopts[OPT_SIZE], *oldscriptname; int obreaks = breaks; HEAPALLOC { @@ -2852,14 +2891,12 @@ doshfunc(char *name, List list, LinkList doshargs, int flags, int noreturnval) if (trapreturn < 0) trapreturn--; oldlastval = lastval; - xexittr = sigtrapped[SIGEXIT]; - if (xexittr & ZSIG_FUNC) - xexitfn = shfunctab->removenode(shfunctab, "TRAPEXIT"); - else - xexitfn = sigfuncs[SIGEXIT]; - sigtrapped[SIGEXIT] = 0; - sigfuncs[SIGEXIT] = NULL; + + starttrapscope(); + tab = pparams; + oldscriptname = scriptname; + scriptname = name; oldzoptind = zoptind; zoptind = 1; @@ -2902,6 +2939,7 @@ doshfunc(char *name, List list, LinkList doshargs, int flags, int noreturnval) argzero = oargv0; } zoptind = oldzoptind; + scriptname = oldscriptname; pparams = tab; if (isset(LOCALOPTIONS)) { @@ -2916,27 +2954,7 @@ doshfunc(char *name, List list, LinkList doshargs, int flags, int noreturnval) opts[LOCALOPTIONS] = saveopts[LOCALOPTIONS]; } - /* - * The trap '...' EXIT runs in the environment of the caller, - * so remember it here but run it after resetting the - * traps for the parent. - */ - newexittr = sigtrapped[SIGEXIT]; - newexitfn = sigfuncs[SIGEXIT]; - if (newexittr & ZSIG_FUNC) - shfunctab->removenode(shfunctab, "TRAPEXIT"); - - sigtrapped[SIGEXIT] = xexittr; - if (xexittr & ZSIG_FUNC) { - shfunctab->addnode(shfunctab, ztrdup("TRAPEXIT"), xexitfn); - sigfuncs[SIGEXIT] = ((Shfunc) xexitfn)->funcdef; - } else - sigfuncs[SIGEXIT] = (List) xexitfn; - - if (newexitfn) { - dotrapargs(SIGEXIT, &newexittr, newexitfn); - freestruct(newexitfn); - } + endtrapscope(); if (trapreturn < -1) trapreturn++; @@ -3008,7 +3026,7 @@ getfpfunc(char *s) d[len] = '\0'; d = metafy(d, len, META_REALLOC); HEAPALLOC { - r = parse_string(d); + r = parse_string(d, 1); } LASTALLOC; return r; } else diff --git a/Src/glob.c b/Src/glob.c index 93b497632..ea4980b8b 100644 --- a/Src/glob.c +++ b/Src/glob.c @@ -1993,7 +1993,7 @@ dyncat(char *s1, char *s2) char *ptr; int l1 = strlen(s1); - ptr = (char *)ncalloc(l1 + strlen(s2) + 1); + ptr = (char *)zhalloc(l1 + strlen(s2) + 1); strcpy(ptr, s1); strcpy(ptr + l1, s2); return ptr; diff --git a/Src/hashtable.c b/Src/hashtable.c index e80461b4e..c4c0b00ac 100644 --- a/Src/hashtable.c +++ b/Src/hashtable.c @@ -133,6 +133,7 @@ deletehashtable(HashTable ht) ht->last->next = ht->next; else firstht = ht->next; + zsfree(ht->tablename); #endif /* ZSH_HASH_DEBUG */ zfree(ht->nodes, ht->hsize * sizeof(HashNode)); zfree(ht, sizeof(*ht)); diff --git a/Src/hist.c b/Src/hist.c index 49dac724c..edf74009e 100644 --- a/Src/hist.c +++ b/Src/hist.c @@ -888,9 +888,14 @@ prepnexthistent(int histnum) else { he = hist_ring->down; if (isset(HISTEXPIREDUPSFIRST) && !(he->flags & HIST_DUP)) { + int max_unique_ct = getiparam("SAVEHIST"); do { + if (max_unique_ct-- <= 0) { + he = hist_ring->down; + break; + } he = he->down; - } while (he != hist_ring->down && !(he->flags & HIST_DUP)) ; + } while (he != hist_ring->down && !(he->flags & HIST_DUP)); if (he != hist_ring->down) { he->up->down = he->down; he->down->up = he->up; @@ -989,7 +994,7 @@ hend(void) } #endif /* get rid of pesky \n which we've already nulled out */ - if (!chline[chwords[chwordpos-2]]) + if (chwordpos > 1 && !chline[chwords[chwordpos-2]]) chwordpos -= 2; /* strip superfluous blanks, if desired */ if (isset(HISTREDUCEBLANKS)) diff --git a/Src/init.c b/Src/init.c index 89cbf2a8b..51c2b88a5 100644 --- a/Src/init.c +++ b/Src/init.c @@ -75,6 +75,11 @@ int tclen[TC_COUNT]; /**/ int tclines, tccolumns, hasam; +/* Pointer to read-key function from zle */ + +/**/ +int (*getkeyptr) _((int)); + #ifdef DEBUG /* depth of allocation type stack */ @@ -194,6 +199,7 @@ parseargs(char **argv) /* loop through command line options (begins with "-" or "+") */ while (*argv && (**argv == '-' || **argv == '+')) { + char *args = *argv; action = (**argv == '-'); if(!argv[0][1]) *argv = "--"; @@ -228,6 +234,14 @@ parseargs(char **argv) restricted = action; else dosetopt(optno, action, 1); + break; + } else if (isspace(**argv)) { + /* zsh's typtab not yet set, have to use ctype */ + while (*++*argv) + if (!isspace(**argv)) { + zerr("bad option string: `%s'", args, 0); + exit(1); + } break; } else { if (!(optno = optlookupc(**argv))) { @@ -376,7 +390,16 @@ init_io(void) #ifdef JOB_CONTROL /* If interactive, make the shell the foreground process */ if (opts[MONITOR] && interact && (SHTTY != -1)) { - attachtty(GETPGRP()); + /* Since we now sometimes execute programs in the process group + * of the parent shell even when using job-control, we have to + * make sure that we run in our own process group. Otherwise if + * we are called from a program that doesn't put us in our own + * group a SIGTSTP that we ignore might stop our parent process. + * Instead of the two calls below we once had: + * attachtty(GETPGRP()); + */ + attachtty(getpid()); + setpgrp(0L, 0L); if ((mypgrp = GETPGRP()) > 0) { while ((ttpgrp = gettygrp()) != -1 && ttpgrp != mypgrp) { sleep(1); @@ -530,12 +553,15 @@ setupvals(void) int i; #endif + getkeyptr = NULL; + + lineno = 1; noeval = 0; curhist = 0; histsiz = DEFAULT_HISTSIZE; inithist(); - cmdstack = (unsigned char *) zalloc(256); + cmdstack = (unsigned char *) zalloc(CMDSTACKSZ); cmdsp = 0; bangchar = '!'; @@ -869,7 +895,7 @@ source(char *s) SHIN = tempfd; bshin = fdopen(SHIN, "r"); subsh = 0; - lineno = 0; + lineno = 1; loops = 0; dosetopt(SHINSTDIN, 0, 1); scriptname = s; diff --git a/Src/input.c b/Src/input.c index b4a6fe22d..d05c75c0b 100644 --- a/Src/input.c +++ b/Src/input.c @@ -186,6 +186,8 @@ ingetc(void) inbufct--; if (itok(lastc = STOUC(*inbufptr++))) continue; + if (((inbufflags & INP_LINENO) || !strin) && lastc == '\n') + lineno++; return lastc; } @@ -279,23 +281,20 @@ inputline(void) zputs(ingetcline, stderr); fflush(stderr); } - if (*ingetcline && ingetcline[strlen(ingetcline) - 1] == '\n') { - /* We've now read a complete line. */ - lineno++; - if (interact && isset(SUNKEYBOARDHACK) && isset(SHINSTDIN) && - SHTTY != -1 && *ingetcline && ingetcline[1] && - ingetcline[strlen(ingetcline) - 2] == '`') { - /* Junk an unmatched "`" at the end of the line. */ - int ct; - char *ptr; - - for (ct = 0, ptr = ingetcline; *ptr; ptr++) - if (*ptr == '`') - ct++; - if (ct & 1) { - ptr[-2] = '\n'; - ptr[-1] = '\0'; - } + if (*ingetcline && ingetcline[strlen(ingetcline) - 1] == '\n' && + interact && isset(SUNKEYBOARDHACK) && isset(SHINSTDIN) && + SHTTY != -1 && *ingetcline && ingetcline[1] && + ingetcline[strlen(ingetcline) - 2] == '`') { + /* Junk an unmatched "`" at the end of the line. */ + int ct; + char *ptr; + + for (ct = 0, ptr = ingetcline; *ptr; ptr++) + if (*ptr == '`') + ct++; + if (ct & 1) { + ptr[-2] = '\n'; + ptr[-1] = '\0'; } } isfirstch = 1; @@ -359,6 +358,8 @@ inungetc(int c) inbufptr--; inbufct++; inbufleft++; + if (((inbufflags & INP_LINENO) || !strin) && c == '\n') + lineno--; } #ifdef DEBUG else if (!(inbufflags & INP_CONT)) { diff --git a/Src/jobs.c b/Src/jobs.c index 31861e284..a50b84fd7 100644 --- a/Src/jobs.c +++ b/Src/jobs.c @@ -92,9 +92,13 @@ makerunning(Job jn) jn->stat &= ~STAT_STOPPED; for (pn = jn->procs; pn; pn = pn->next) +#if 0 if (WIFSTOPPED(pn->status) && (!(jn->stat & STAT_SUPERJOB) || pn->next)) pn->status = SP_RUNNING; +#endif + if (WIFSTOPPED(pn->status)) + pn->status = SP_RUNNING; if (jn->stat & STAT_SUPERJOB) makerunning(jobtab + jn->other); @@ -181,8 +185,9 @@ update_job(Job jn) for (i = 1; i < MAXJOB; i++) if ((jobtab[i].stat & STAT_SUPERJOB) && - jobtab[i].other == job) { - killpg(jobtab[i].gleader, SIGSTOP); + jobtab[i].other == job && + jobtab[i].gleader) { + killpg(jobtab[i].gleader, SIGTSTP); break; } } diff --git a/Src/lex.c b/Src/lex.c index 8dc836329..33b6598b9 100644 --- a/Src/lex.c +++ b/Src/lex.c @@ -219,7 +219,7 @@ lexsave(void) ls->hlinesz = hlinesz; ls->cstack = cmdstack; ls->csp = cmdsp; - cmdstack = (unsigned char *)zalloc(256); + cmdstack = (unsigned char *)zalloc(CMDSTACKSZ); ls->tok = tok; ls->isnewlin = isnewlin; ls->tokstr = tokstr; @@ -1150,7 +1150,7 @@ gettokstr(int c, int sub) cmdpush(CS_BQUOTE); SETPARBEGIN inquote = 0; - while ((c = hgetc()) != '`' && !lexstop) + while ((c = hgetc()) != '`' && !lexstop) { if (c == '\\') { c = hgetc(); if (c != '\n') { @@ -1171,6 +1171,7 @@ gettokstr(int c, int sub) ALLOWHIST } } + } if (inquote) ALLOWHIST cmdpop(); diff --git a/Src/loop.c b/Src/loop.c index 07a7a56b0..16e4ff314 100644 --- a/Src/loop.c +++ b/Src/loop.c @@ -71,6 +71,7 @@ execfor(Cmd cmd, LinkList args, int flags) lastval = 0; loops++; pushheap(); + cmdpush(CS_FOR); for (;;) { if (node->condition) { str = dupstring(node->condition); @@ -119,6 +120,7 @@ execfor(Cmd cmd, LinkList args, int flags) freeheap(); } popheap(); + cmdpop(); loops--; return lastval; } @@ -147,6 +149,7 @@ execselect(Cmd cmd, LinkList args, int flags) loops++; lastval = 0; pushheap(); + cmdpush(CS_SELECT); inp = fdopen(dup((SHTTY == -1) ? 0 : SHTTY), "r"); more = selectlist(args, 0); for (;;) { @@ -201,6 +204,7 @@ execselect(Cmd cmd, LinkList args, int flags) break; } done: + cmdpop(); popheap(); fclose(inp); loops--; @@ -279,6 +283,7 @@ execwhile(Cmd cmd, LinkList args, int flags) node = cmd->u.whilecmd; oldval = 0; pushheap(); + cmdpush(node->cond ? CS_UNTIL : CS_WHILE); loops++; for (;;) { noerrexit = 1; @@ -304,6 +309,7 @@ execwhile(Cmd cmd, LinkList args, int flags) } oldval = lastval; } + cmdpop(); popheap(); loops--; return lastval; @@ -322,6 +328,7 @@ execrepeat(Cmd cmd, LinkList args, int flags) } count = atoi(peekfirst(args)); pushheap(); + cmdpush(CS_REPEAT); loops++; while (count--) { execlist(cmd->u.list, 1, 0); @@ -337,6 +344,7 @@ execrepeat(Cmd cmd, LinkList args, int flags) break; } } + cmdpop(); popheap(); loops--; return lastval; @@ -347,7 +355,7 @@ int execif(Cmd cmd, LinkList args, int flags) { struct ifcmd *node; - int olderrexit; + int olderrexit, s = 0; List *i, *t; olderrexit = noerrexit; @@ -358,17 +366,22 @@ execif(Cmd cmd, LinkList args, int flags) if (!noerrexit) noerrexit = 1; while (*i) { + cmdpush(s ? CS_ELIF : CS_IF); execlist(*i, 1, 0); + cmdpop(); if (!lastval) break; + s = 1; i++; t++; } noerrexit = olderrexit; - if (*t) + if (*t) { + cmdpush(*i ? (s ? CS_ELIFTHEN : CS_IFTHEN) : CS_ELSE); execlist(*t, 1, flags & CFLAG_EXEC); - else + cmdpop(); + } else lastval = 0; return lastval; @@ -393,6 +406,7 @@ execcase(Cmd cmd, LinkList args, int flags) lastval = 0; if (node) { + cmdpush(CS_CASE); while (*p) { char *pat = dupstring(*p + 1); singsub(&pat); @@ -405,6 +419,7 @@ execcase(Cmd cmd, LinkList args, int flags) p++; l++; } + cmdpop(); } return lastval; } diff --git a/Src/module.c b/Src/module.c index fa7dd2774..ce926c27a 100644 --- a/Src/module.c +++ b/Src/module.c @@ -709,7 +709,14 @@ bin_zmodload(char *nam, char **args, char *ops, int func) zwarnnam(nam, "what do you want to unload?", NULL, 0); return 1; } - if (ops['d']) + if (ops['e'] && (ops['I'] || ops['L'] || ops['a'] || ops['d'] || + ops['i'] || ops['u'])) { + zwarnnam(nam, "-e cannot be combined with other options", NULL, 0); + return 1; + } + if (ops['e']) + return bin_zmodload_exist(nam, args, ops); + else if (ops['d']) return bin_zmodload_dep(nam, args, ops); else if ((ops['a'] || ops['b']) && !(ops['c'] || ops['p'])) return bin_zmodload_auto(nam, args, ops); @@ -727,6 +734,46 @@ bin_zmodload(char *nam, char **args, char *ops, int func) /**/ static int +bin_zmodload_exist(char *nam, char **args, char *ops) +{ + LinkNode node; + Module m; + + if (!*args) { + for (node = firstnode(bltinmodules); node; incnode(node)) { + nicezputs((char *) getdata(node), stdout); + putchar('\n'); + } + for (node = firstnode(modules); node; incnode(node)) { + m = (Module) getdata(node); + if (m->handle && !(m->flags & MOD_UNLOAD)) { + nicezputs(m->nam, stdout); + putchar('\n'); + } + } + return 0; + } else { + int ret = 0, f; + + for (; !ret && *args; args++) { + f = 0; + for (node = firstnode(bltinmodules); + !f && node; incnode(node)) + f = !strcmp(*args, (char *) getdata(node)); + for (node = firstnode(modules); + !f && node; incnode(node)) { + m = (Module) getdata(node); + if (m->handle && !(m->flags & MOD_UNLOAD)) + f = !strcmp(*args, m->nam); + } + ret = !f; + } + return ret; + } +} + +/**/ +static int bin_zmodload_dep(char *nam, char **args, char *ops) { LinkNode node; @@ -1116,6 +1163,37 @@ bin_zmodload_load(char *nam, char **args, char *ops) } /**/ +#else /* DYNAMIC */ + +/* This is the version for shells without dynamic linking. */ + +/**/ +int +bin_zmodload(char *nam, char **args, char *ops, int func) +{ + /* We understand only the -e option. */ + + if (ops['e']) { + LinkNode node; + + if (!*args) { + for (node = firstnode(bltinmodules); node; incnode(node)) { + nicezputs((char *) getdata(node), stdout); + putchar('\n'); + } + } else { + for (; *args; args++) + for (node = firstnode(bltinmodules); node; incnode(node)) + if (strcmp(*args, (char *) getdata(node))) + return 1; + } + return 0; + } + /* Otherwise we return 1 -- different from the dynamic version. */ + return 1; +} + +/**/ #endif /* DYNAMIC */ /* The list of module-defined conditions. */ @@ -1206,6 +1284,180 @@ addconddefs(char const *nam, Conddef c, int size) return hadf ? hads : 1; } +/* This list of hook functions defined. */ + +/**/ +Hookdef hooktab; + +/* Find a hook definition given the name. */ + +/**/ +Hookdef +gethookdef(char *n) +{ + Hookdef p; + + for (p = hooktab; p; p = p->next) + if (!strcmp(n, p->name)) + return p; + return NULL; +} + +/* This adds the given hook definition. The return value is zero on * + * success and 1 on failure. */ + +/**/ +int +addhookdef(Hookdef h) +{ + if (gethookdef(h->name)) + return 1; + + h->next = hooktab; + hooktab = h; + PERMALLOC { + h->funcs = newlinklist(); + } LASTALLOC; + + return 0; +} + +/* This adds multiple hook definitions. This is like addbuiltins(). */ + +/**/ +int +addhookdefs(char const *nam, Hookdef h, int size) +{ + int hads = 0, hadf = 0; + + while (size--) { + if (addhookdef(h)) { + zwarnnam(nam, "name clash when adding condition `%s'", h->name, 0); + hadf = 1; + } else + hads = 2; + h++; + } + return hadf ? hads : 1; +} + +/* Delete hook definitions. */ + +/**/ +int +deletehookdef(Hookdef h) +{ + Hookdef p, q; + + for (p = hooktab, q = NULL; p && p != h; q = p, p = p->next); + + if (!p) + return 1; + + if (q) + q->next = p->next; + else + hooktab = p->next; + freelinklist(p->funcs, NULL); + return 0; +} + +/**/ +int +deletehookdefs(char const *nam, Hookdef h, int size) +{ + while (size--) { + deletehookdef(h); + h++; + } + return 1; +} + +/* Add a function to a hook. */ + +/**/ +int +addhookdeffunc(Hookdef h, Hookfn f) +{ + PERMALLOC { + addlinknode(h->funcs, (void *) f); + } LASTALLOC; + return 0; +} + +/**/ +int +addhookfunc(char *n, Hookfn f) +{ + Hookdef h = gethookdef(n); + + if (h) + return addhookdeffunc(h, f); + return 1; +} + +/* Delete a function from a hook. */ + +/**/ +int +deletehookdeffunc(Hookdef h, Hookfn f) +{ + LinkNode p; + + for (p = firstnode(h->funcs); p; incnode(p)) + if (f == (Hookfn) getdata(p)) { + remnode(h->funcs, p); + return 0; + } + return 1; +} + +/**/ +int +deletehookfunc(char *n, Hookfn f) +{ + Hookdef h = gethookdef(n); + + if (h) + return deletehookdeffunc(h, f); + return 1; +} + +/* Run the function(s) for a hook. */ + +/**/ +int +runhookdef(Hookdef h, void *d) +{ + if (empty(h->funcs)) { + if (h->def) + return h->def(h, d); + return 0; + } else if (h->flags & HOOKF_ALL) { + LinkNode p; + int r; + + for (p = firstnode(h->funcs); p; incnode(p)) + if ((r = ((Hookfn) getdata(p))(h, d))) + return r; + if (h->def) + return h->def(h, d); + return 0; + } else + return ((Hookfn) getdata(lastnode(h->funcs)))(h, d); +} + +/**/ +int +runhook(char *n, void *d) +{ + Hookdef h = gethookdef(n); + + if (h) + return runhookdef(h, d); + return 0; +} + /* This adds the given parameter definition. The return value is zero on * * success and 1 on failure. */ diff --git a/Src/options.c b/Src/options.c index 504ccdf7e..2eb73690e 100644 --- a/Src/options.c +++ b/Src/options.c @@ -143,6 +143,7 @@ static struct optname optns[] = { {NULL, "listbeep", OPT_ALL, LISTBEEP}, {NULL, "listtypes", OPT_ALL, LISTTYPES}, {NULL, "localoptions", OPT_EMULATE|OPT_KSH, LOCALOPTIONS}, +{NULL, "localtraps", OPT_EMULATE|OPT_KSH, LOCALTRAPS}, {NULL, "login", OPT_SPECIAL, LOGINSHELL}, {NULL, "longlistjobs", 0, LONGLISTJOBS}, {NULL, "magicequalsubst", 0, MAGICEQUALSUBST}, diff --git a/Src/params.c b/Src/params.c index b9f3d33a0..d71cfb46e 100644 --- a/Src/params.c +++ b/Src/params.c @@ -588,7 +588,7 @@ createparam(char *name, int flags) DPUTS(oldpm && oldpm->level > locallevel, "BUG: old local parameter not deleteed"); - if (oldpm && oldpm->level == locallevel) { + if (oldpm && (oldpm->level == locallevel || !(flags & PM_LOCAL))) { if (!(oldpm->flags & PM_UNSET) || (oldpm->flags & PM_SPECIAL)) { oldpm->flags &= ~PM_UNSET; return NULL; @@ -616,7 +616,7 @@ createparam(char *name, int flags) pm = (Param) alloc(sizeof *pm); pm->nam = nulstring; } - pm->flags = flags; + pm->flags = flags & ~PM_LOCAL; if(!(pm->flags & PM_SPECIAL)) assigngetset(pm); @@ -1898,7 +1898,7 @@ arrhashsetfn(Param pm, char **val) * since that could cause trouble for special hashes. This way, * * it's up to pm->sets.hfn() what to do. */ int alen = arrlen(val); - HashTable opmtab = paramtab, ht; + HashTable opmtab = paramtab, ht = 0; char **aptr = val; Value v = (Value) hcalloc(sizeof *v); v->b = -1; @@ -1909,7 +1909,8 @@ arrhashsetfn(Param pm, char **val) NULL, 0); return; } - ht = paramtab = newparamtable(17, pm->nam); + if (alen) + ht = paramtab = newparamtable(17, pm->nam); while (*aptr) { /* The parameter name is ztrdup'd... */ v->pm = createparam(*aptr, PM_SCALAR|PM_UNSET); diff --git a/Src/parse.c b/Src/parse.c index 520181750..626ffc982 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -890,6 +890,8 @@ par_subsh(Cmd c) static void par_funcdef(Cmd c) { + int oldlineno = lineno; + lineno = 0; nocorrect = 1; incmdpos = 0; yylex(); @@ -912,13 +914,17 @@ par_funcdef(Cmd c) if (tok == INBRACE) { yylex(); c->u.list = par_list(); - if (tok != OUTBRACE) + if (tok != OUTBRACE) { + lineno += oldlineno; YYERRORV; + } yylex(); } else if (unset(SHORTLOOPS)) { + lineno += oldlineno; YYERRORV; } else c->u.list = par_list1(); + lineno += oldlineno; } /* @@ -1023,6 +1029,8 @@ par_simple(Cmd c) c->redir = newlinklist(); par_redir(c->redir); } else if (tok == INOUTPAR) { + int oldlineno = lineno; + lineno = 0; incmdpos = 1; cmdpush(CS_FUNCDEF); yylex(); @@ -1033,6 +1041,7 @@ par_simple(Cmd c) c->u.list = par_list(); if (tok != OUTBRACE) { cmdpop(); + lineno += oldlineno; YYERROR; } yylex(); @@ -1051,6 +1060,7 @@ par_simple(Cmd c) } cmdpop(); c->type = FUNCDEF; + lineno += oldlineno; } else break; isnull = 0; diff --git a/Src/signals.c b/Src/signals.c index f69da0140..e9851b57a 100644 --- a/Src/signals.c +++ b/Src/signals.c @@ -602,6 +602,57 @@ killjb(Job jn, int sig) return err; } +/* + * List for saving traps. We don't usually have that many traps + * at once, so just use a linked list. + */ +struct savetrap { + int sig, flags, local; + void *list; +}; + +static LinkList savetraps; + +/* Flag to unsettrap not to free the structs, which we're keeping */ + +/**/ +int notrapfree; + +/* + * Save the current trap and unset it. + */ + +static void +dosavetrap(int sig, int level) +{ + struct savetrap *st; + st = (struct savetrap *)zalloc(sizeof(*st)); + st->sig = sig; + st->local = level; + notrapfree++; + if ((st->flags = sigtrapped[sig]) & ZSIG_FUNC) { + /* + * Get the old function: this assumes we haven't added + * the new one yet. + */ + char func[20]; + sprintf(func, "TRAP%s", sigs[sig]); + st->list = shfunctab->removenode(shfunctab, func); + } else { + st->list = sigfuncs[sig]; + unsettrap(sig); + } + notrapfree--; + PERMALLOC { + if (!savetraps) + savetraps = newlinklist(); + /* + * Put this at the front of the list + */ + insertlinknode(savetraps, (LinkNode)savetraps, st); + } LASTALLOC; +} + /**/ int settrap(int sig, List l) @@ -612,7 +663,15 @@ settrap(int sig, List l) zerr("can't trap SIG%s in interactive shells", sigs[sig], 0); return 1; } - if (sigfuncs[sig]) + /* + * Note that we save the trap here even if there isn't an existing + * one, to aid in removing this one. However, if there's + * already one at the current locallevel we just overwrite it. + */ + if (isset(LOCALTRAPS) && locallevel && + (!sigtrapped[sig] || locallevel > (sigtrapped[sig] >> ZSIG_SHIFT))) { + dosavetrap(sig, locallevel); + } else if (sigfuncs[sig]) unsettrap(sig); sigfuncs[sig] = l; if (!l) { @@ -632,6 +691,12 @@ settrap(int sig, List l) sig != SIGCHLD) install_handler(sig); } + /* + * Note that introducing the locallevel does not affect whether + * sigtrapped[sig] is zero or not, i.e. a test without a mask + * works just the same. + */ + sigtrapped[sig] |= (locallevel << ZSIG_SHIFT); return 0; } @@ -645,6 +710,19 @@ unsettrap(int sig) (jobbing && (sig == SIGTTOU || sig == SIGTSTP || sig == SIGTTIN))) { return; } + if (isset(LOCALTRAPS) && locallevel && + sigtrapped[sig] && locallevel > (sigtrapped[sig] >> ZSIG_SHIFT)) { + /* + * This calls unsettrap recursively to do any dirty work, so + * make sure this bit doesn't happen: a bit messy, but hard + * to avoid. + */ + int oldlt = opts[LOCALTRAPS]; + opts[LOCALTRAPS] = 0; + dosavetrap(sig, locallevel); + opts[LOCALTRAPS] = oldlt; + return; + } sigtrapped[sig] = 0; if (sig == SIGINT && interact) { /* PWS 1995/05/16: added test for interactive, also noholdintr() * @@ -659,6 +737,8 @@ unsettrap(int sig) #endif sig != SIGCHLD) signal_default(sig); + if (notrapfree) + return; if (trapped & ZSIG_FUNC) { char func[20]; HashNode hn; @@ -672,6 +752,83 @@ unsettrap(int sig) } } +/**/ +void +starttrapscope(void) +{ + /* + * SIGEXIT needs to be restored at the current locallevel, + * so give it the next higher one. + */ + if (sigtrapped[SIGEXIT]) + dosavetrap(SIGEXIT, locallevel+1); +} + +/* + * Reset traps after the end of a function: must be called after + * endparamscope() so that the locallevel has been decremented. + */ + +/**/ +void +endtrapscope(void) +{ + LinkNode ln; + struct savetrap *st; + int exittr; + void *exitfn = NULL; + + /* + * Remember the exit trap, but don't run it until + * after all the other traps have been put back. + */ + if ((exittr = sigtrapped[SIGEXIT])) { + notrapfree++; + if (exittr & ZSIG_FUNC) { + exitfn = shfunctab->removenode(shfunctab, "TRAPEXIT"); + } else { + exitfn = sigfuncs[SIGEXIT]; + unsettrap(SIGEXIT); + } + notrapfree--; + } + + if (savetraps) { + while ((ln = firstnode(savetraps)) && + (st = (struct savetrap *) ln->dat) && + st->local > locallevel) { + int sig = st->sig; + + remnode(savetraps, ln); + + if (sigtrapped[sig]) + unsettrap(sig); + if (st->flags) { + List list = (st->flags & ZSIG_FUNC) ? + ((Shfunc) st->list)->funcdef : (List) st->list; + /* prevent settrap from saving this */ + int oldlt = opts[LOCALTRAPS]; + opts[LOCALTRAPS] = 0; + settrap(sig, list); + opts[LOCALTRAPS] = oldlt; + if ((sigtrapped[sig] = st->flags) & ZSIG_FUNC) + shfunctab->addnode(shfunctab, ((Shfunc)st->list)->nam, + (Shfunc) st->list); + } + zfree(st, sizeof(*st)); + } + } + + if (exittr) { + dotrapargs(SIGEXIT, &exittr, (exittr & ZSIG_FUNC) ? + ((Shfunc)exitfn)->funcdef : (List) exitfn); + if (exittr & ZSIG_FUNC) + shfunctab->freenode((HashNode)exitfn); + else + freestruct(exitfn); + } +} + /* Execute a trap function for a given signal, possibly * with non-standard sigtrapped & sigfuncs values */ diff --git a/Src/subst.c b/Src/subst.c index d85d73f58..18d815404 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -1328,10 +1328,15 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) else t = aval; } else if (!isarr) { - arr[0] = val; - arr[1] = NULL; + if (!*val && arrasg > 1) { + arr[0] = NULL; + l = 0; + } else { + arr[0] = val; + arr[1] = NULL; + l = 1; + } t = aval = arr; - l = 1; } else l = arrlen(aval), t = aval; p = a = zalloc(sizeof(char *) * (l + 1)); @@ -1944,6 +1949,8 @@ dstackent(char ch, int val) else for (end=NULL, n=firstnode(dirstack); n && val; val--, n=nextnode(n)); if (n == end) { + if (backwards && !val) + return pwd; if (isset(NOMATCH)) zerr("not enough directory stack entries.", NULL, 0); return NULL; diff --git a/Src/utils.c b/Src/utils.c index ba4f3dc9d..a409ab03c 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -62,9 +62,10 @@ zerr(const char *fmt, const char *str, int num) /* * scriptname is set when sourcing scripts, so that we get the * correct name instead of the generic name of whatever - * program/script is running. + * program/script is running. It's also set in shell functions, + * so test locallevel, too. */ - nicezputs(isset(SHINSTDIN) ? "zsh" : + nicezputs((isset(SHINSTDIN) && !locallevel) ? "zsh" : scriptname ? scriptname : argzero, stderr); fputs(": ", stderr); zerrnam(NULL, fmt, str, num); @@ -79,7 +80,7 @@ zerrnam(const char *cmd, const char *fmt, const char *str, int num) return; errflag = 1; trashzle(); - if(unset(SHINSTDIN)) { + if (unset(SHINSTDIN) || locallevel) { nicezputs(scriptname ? scriptname : argzero, stderr); fputs(": ", stderr); } @@ -133,7 +134,7 @@ zerrnam(const char *cmd, const char *fmt, const char *str, int num) putc(*fmt == Meta ? *++fmt ^ 32 : *fmt, stderr); fmt++; } - if (unset(SHINSTDIN) && lineno) + if ((unset(SHINSTDIN) || locallevel) && lineno) fprintf(stderr, " [%ld]\n", (long)lineno); else putc('\n', stderr); @@ -774,6 +775,23 @@ checkmailpath(char **s) } } +/* This prints the XTRACE prompt. */ + +/**/ +void +printprompt4(void) +{ + if (prompt4) { + int l; + char *s = dupstring(prompt4); + + unmetafy(s, &l); + s = unmetafy(promptexpand(metafy(s, l, META_NOALLOC), 0, NULL, NULL), &l); + + fprintf(stderr, "%s", s); + } +} + /**/ void freestr(void *a) @@ -2116,7 +2134,12 @@ mkarray(char *s) void zbeep(void) { - if (isset(BEEP)) + char *vb; + if ((vb = getsparam("ZBEEP"))) { + int len; + vb = getkeystring(vb, &len, 2, NULL); + write(SHTTY, vb, len); + } else if (isset(BEEP)) write(SHTTY, "\07", 1); } @@ -3150,6 +3173,22 @@ dquotedzputs(char const *s, FILE *stream) } #endif +/* + * Decode a key string, turning it into the literal characters. + * The length is returned in len. + * fromwhere determines how the processing works. + * 0: Don't handle keystring, just print-like escapes. + * Expects misc to be present. + * 1: Handle Emacs-like \C-X arguments etc., but not ^X + * Expects misc to be present. + * 2: Handle ^X as well as emacs-like keys; don't handle \c + * for no newlines. + * 3: As 1, but don't handle \c. + * 4: Do $'...' quoting. Overwrites the existing string instead of + * zhalloc'ing + * 5: As 2, but \- is special. Expects misc to be defined. + */ + /**/ char * getkeystring(char *s, int *len, int fromwhere, int *misc) diff --git a/Src/xmods.conf b/Src/xmods.conf index c36105721..6b7f1701a 100644 --- a/Src/xmods.conf +++ b/Src/xmods.conf @@ -3,3 +3,4 @@ comp1 zle compctl sched +complist diff --git a/Src/zsh.export b/Src/zsh.export index 72779e24a..5a3a94c70 100644 --- a/Src/zsh.export +++ b/Src/zsh.export @@ -5,6 +5,8 @@ addconddefs addedx addhashnode addhistnum +addhookdefs +addhookfunc addparamdefs addwrapper arrvargetfn @@ -43,6 +45,8 @@ current_limits deletebuiltins deleteconddefs deletehashtable +deletehookdefs +deletehookfunc deleteparamdefs deleteparamtable deletewrapper @@ -83,6 +87,7 @@ gethashnode2 gethparam getintvalue getiparam +getkeyptr getkeystring getlinknode getpermtext @@ -206,6 +211,7 @@ resetneeded restoredir reswdtab retflag +runhookdef runshfunc scancountparams scanhashtable diff --git a/Src/zsh.h b/Src/zsh.h index e7b6e5ae0..45691039e 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -226,6 +226,7 @@ enum { #define INP_HIST (1<<2) /* expanding history */ #define INP_CONT (1<<3) /* continue onto previously stacked input */ #define INP_ALCONT (1<<4) /* stack is continued from alias expn. */ +#define INP_LINENO (1<<5) /* update line number */ /* Flags for metafy */ #define META_REALLOC 0 @@ -277,8 +278,9 @@ typedef struct heapstack *Heapstack; typedef struct histent *Histent; typedef struct forcmd *Forcmd; typedef struct autofn *AutoFn; +typedef struct hookdef *Hookdef; -typedef struct asgment *Asgment; +typedef struct asgment *Asgment; /********************************/ @@ -886,6 +888,22 @@ struct module { #define MOD_UNLOAD (1<<1) #define MOD_SETUP (1<<2) +/* C-function hooks */ + +typedef int (*Hookfn) _((Hookdef, void *)); + +struct hookdef { + Hookdef next; + char *name; + Hookfn def; + int flags; + LinkList funcs; +}; + +#define HOOKF_ALL 1 + +#define HOOKDEF(name, func, flags) { NULL, name, (Hookfn) func, flags, NULL } + /* node used in parameter hash table (paramtab) */ struct param { @@ -958,12 +976,13 @@ struct param { #define PM_UNALIASED (1<<11) /* do not expand aliases when autoloading */ #define PM_TIED (1<<12) /* array tied to colon-path or v.v. */ -#define PM_SPECIAL (1<<13) /* special builtin parameter */ -#define PM_DONTIMPORT (1<<14) /* do not import this variable */ -#define PM_RESTRICTED (1<<15) /* cannot be changed in restricted mode */ -#define PM_UNSET (1<<16) /* has null value */ -#define PM_REMOVABLE (1<<17) /* special can be removed from paramtab */ -#define PM_AUTOLOAD (1<<18) /* autoloaded from module */ +#define PM_LOCAL (1<<13) /* this parameter will be made local */ +#define PM_SPECIAL (1<<14) /* special builtin parameter */ +#define PM_DONTIMPORT (1<<15) /* do not import this variable */ +#define PM_RESTRICTED (1<<16) /* cannot be changed in restricted mode */ +#define PM_UNSET (1<<17) /* has null value */ +#define PM_REMOVABLE (1<<18) /* special can be removed from paramtab */ +#define PM_AUTOLOAD (1<<19) /* autoloaded from module */ /* Flags for extracting elements of arrays and associative arrays */ #define SCANPM_WANTVALS (1<<0) @@ -1201,6 +1220,7 @@ enum { LISTBEEP, LISTTYPES, LOCALOPTIONS, + LOCALTRAPS, LOGINSHELL, LONGLISTJOBS, MAGICEQUALSUBST, @@ -1358,7 +1378,8 @@ struct ttyinfo { /* Definitions for the %_ prompt escape */ /****************************************/ -#define cmdpush(X) if (!(cmdsp >= 0 && cmdsp < 256)) {;} else cmdstack[cmdsp++]=(X) +#define CMDSTACKSZ 256 +#define cmdpush(X) if (!(cmdsp >= 0 && cmdsp < CMDSTACKSZ)) {;} else cmdstack[cmdsp++]=(X) #ifdef DEBUG # define cmdpop() if (cmdsp <= 0) { \ fputs("BUG: cmdstack empty\n", stderr); \ @@ -1491,9 +1512,13 @@ struct heap { /* These used in the sigtrapped[] array */ -#define ZSIG_TRAPPED (1<<0) -#define ZSIG_IGNORED (1<<1) -#define ZSIG_FUNC (1<<2) +#define ZSIG_TRAPPED (1<<0) /* Signal is trapped */ +#define ZSIG_IGNORED (1<<1) /* Signal is ignored */ +#define ZSIG_FUNC (1<<2) /* Trap is a function, not an eval list */ +/* Mask to get the above flags */ +#define ZSIG_MASK (ZSIG_TRAPPED|ZSIG_IGNORED|ZSIG_FUNC) +/* No. of bits to shift local level when storing in sigtrapped */ +#define ZSIG_SHIFT 3 /**********************************/ /* Flags to third argument of zle */ |