From 7c670f1e6a0e154f0b1a2d4b6eed0e71c9404b56 Mon Sep 17 00:00:00 2001 From: Tanaka Akira Date: Sat, 3 Jul 1999 13:16:46 +0000 Subject: zsh-3.1.5-pws-25 --- Src/Makefile.in | 4 +- Src/Zle/.distfiles | 1 + Src/Zle/comp.h | 24 ++++ Src/Zle/compctl.c | 6 +- Src/Zle/complist.c | 141 ++++++++++++-------- Src/Zle/deltochar.c | 2 - Src/Zle/iwidgets.list | 1 + Src/Zle/zle.export | 36 +++++ Src/Zle/zle.h | 6 + Src/Zle/zle_hist.c | 78 ++++------- Src/Zle/zle_keymap.c | 65 +++++---- Src/Zle/zle_main.c | 31 +++-- Src/Zle/zle_misc.c | 48 +++---- Src/Zle/zle_move.c | 35 ++--- Src/Zle/zle_params.c | 2 +- Src/Zle/zle_refresh.c | 2 +- Src/Zle/zle_thingy.c | 41 ++++-- Src/Zle/zle_tricky.c | 359 +++++++++++++++++++++++++++----------------------- Src/Zle/zle_utils.c | 24 +--- Src/Zle/zle_vi.c | 126 ++++++------------ Src/Zle/zle_word.c | 16 +-- Src/builtin.c | 38 ++++-- Src/exec.c | 80 +++++++---- Src/glob.c | 2 +- Src/hashtable.c | 1 + Src/init.c | 7 +- Src/jobs.c | 55 ++++++-- Src/loop.c | 2 +- Src/module.c | 254 ++++++++++++++++++++++++++++++++++- Src/params.c | 9 +- Src/prompt.c | 8 ++ Src/signals.c | 5 +- Src/subst.c | 11 +- Src/utils.c | 16 ++- Src/xmods.conf | 1 + Src/zsh.export | 5 + Src/zsh.h | 40 ++++-- 37 files changed, 1003 insertions(+), 579 deletions(-) (limited to 'Src') diff --git a/Src/Makefile.in b/Src/Makefile.in index e98a696e4..0dcfbdee1 100644 --- a/Src/Makefile.in +++ b/Src/Makefile.in @@ -206,9 +206,9 @@ distclean: distclean-modules realclean: realclean-modules # Don't remake Makemod just to delete things, even if it doesn't exist. -mostlyclean-modules clean-modules distclean-modules realclean-modules: +mostlyclean-modules clean-modules distclean-modules realclean-modules: modules.index if test -f Makemod; then \ - @$(MAKE) -f Makemod $(MAKEDEFS) `echo $@ | sed 's/-modules//'`; \ + $(MAKE) -f Makemod $(MAKEDEFS) `echo $@ | sed 's/-modules//'`; \ fi; \ exit 0 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 78c65ffeb..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 @@ -299,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 e0f9a9089..2b426492e 100644 --- a/Src/Zle/compctl.c +++ b/Src/Zle/compctl.c @@ -2221,7 +2221,8 @@ 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"); @@ -2261,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 index 63bc4c6e3..aac8b410d 100644 --- a/Src/Zle/complist.c +++ b/Src/Zle/complist.c @@ -198,7 +198,7 @@ getcoldef(Listcols c, char *s) /* This initializes the given terminal color structure. */ -static int +static void getcols(Listcols c) { char *s; @@ -206,16 +206,17 @@ getcols(Listcols c) 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->cols[COL_MA] = tcstr[TCSTANDOUTBEG]) || + !c->cols[COL_MA][0]) + c->cols[COL_MA] = ""; + else + c->cols[COL_EC] = tcstr[TCSTANDOUTEND]; + return; } - if (!c) - return 0; /* We have one of the parameters, use it. */ memset(c, 0, sizeof(*c)); s = dupstring(s); @@ -230,48 +231,65 @@ getcols(Listcols c) 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); + return; +} - /* If no `ec' was given, we is `' 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; +static int last_col = COL_NO; + +static void +zcputs(Listcols c, int colour) +{ + if (colour != last_col + && (last_col < COL_NO + || strcmp(c->cols[last_col], c->cols[colour]))) { + fputs(c->cols[COL_LC], shout); + fputs(c->cols[colour], shout); + fputs(c->cols[COL_RC], shout); + last_col = colour; } - return 0; + return; } /* 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) +static void +putcolstr(Listcols c, char *n, mode_t m) { + int colour; Extcol e; for (e = c->exts; e; e = e->next) - if (strsfx(e->ext, n)) - return e->col; + if (strsfx(e->ext, n)) { /* XXX: unoptimised if used */ + if (last_col < COL_NO + || strcmp(c->cols[last_col], e->col)) { + fputs(c->cols[COL_LC], shout); + fputs(e->col, shout); + fputs(c->cols[COL_RC], shout); + } + last_col = COL_NO - 1; + return; + } if (S_ISDIR(m)) - return c->cols[COL_DI]; + colour = COL_DI; else if (S_ISLNK(m)) - return c->cols[COL_LN]; + colour = COL_LN; else if (S_ISFIFO(m)) - return c->cols[COL_PI]; + colour = COL_PI; else if (S_ISSOCK(m)) - return c->cols[COL_SO]; + colour = COL_SO; else if (S_ISBLK(m)) - return c->cols[COL_BD]; + colour = COL_BD; else if (S_ISCHR(m)) - return c->cols[COL_CD]; + colour = COL_CD; else if (S_ISREG(m) && (m & S_IXUGO)) - return c->cols[COL_EX]; + colour = COL_EX; + else + colour = COL_FI; - return c->cols[COL_FI]; + zcputs(c, colour); + return; } /* Information about the list shown. */ @@ -505,14 +523,15 @@ complistmatches(Hookdef dummy, Chdata dat) 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); + zcputs(&col, COL_MI); a = longest - 2; while (a--) putc(' ', shout); - fputs(col.cols[COL_EC], shout); + if (col.cols[COL_EC]) + fputs(col.cols[COL_EC], shout); + else + zcputs(&col, COL_NO); break; } hasm = 1; @@ -539,20 +558,18 @@ complistmatches(Hookdef dummy, Chdata dat) zt = ztat(pb, &buf, 1); if (cc >= 0) - fputs(col.cols[cc], shout); + zcputs(&col, cc); else if (zt) - fputs(col.cols[COL_NO], shout); + zcputs(&col, COL_NO); else - fputs(getcolstr(&col, pb, buf.st_mode), shout); - fputs(col.cols[COL_RC], shout); + putcolstr(&col, pb, buf.st_mode); 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); + zcputs(&col, cc >= 0 ? cc : COL_NO); nicezputs(m->str, shout); if (of) putc(' ', shout); @@ -560,13 +577,17 @@ complistmatches(Hookdef dummy, Chdata dat) a = longest - niceztrlen(m->str) - 2 - of; while (a--) putc(' ', shout); - fputs(col.cols[COL_EC], shout); + if (col.cols[COL_EC]) + fputs(col.cols[COL_EC], shout); + else + zcputs(&col, COL_NO); if (i) { - fputs(col.cols[COL_LC], shout); - fputs(col.cols[COL_NO], shout); - fputs(col.cols[COL_RC], shout); + zcputs(&col, COL_NO); fputs(" ", shout); - fputs(col.cols[COL_EC], shout); + if (col.cols[COL_EC]) + fputs(col.cols[COL_EC], shout); + else + zcputs(&col, COL_NO); } if (--n) for (j = nc; j && *q; j--) @@ -574,13 +595,14 @@ complistmatches(Hookdef dummy, Chdata dat) mc++; } if (i > 0) { - fputs(col.cols[COL_LC], shout); - fputs(col.cols[COL_MI], shout); - fputs(col.cols[COL_RC], shout); + zcputs(&col, COL_MI); a = longest - 2; while (a--) putc(' ', shout); - fputs(col.cols[COL_EC], shout); + if (col.cols[COL_EC]) + fputs(col.cols[COL_EC], shout); + else + zcputs(&col, COL_NO); } if (n) { putc('\n', shout); @@ -627,12 +649,12 @@ domenuselect(Hookdef dummy, Chdata dat) Cmgroup *pg; Thingy cmd; Menustack u = NULL; - int i = 0; + int i = 0, acc = 0; char *s; - if (getcols(NULL) || (dummy && (!(s = getsparam("SELECTMIN")) || - (dat && dat->num < atoi(s))))) - return 1; + if (dummy && (!(s = getsparam("SELECTMIN")) || + (dat && dat->num < atoi(s)))) + return 0; selectlocalmap(mskeymap); noselect = 0; @@ -659,10 +681,12 @@ domenuselect(Hookdef dummy, Chdata dat) getk: - if (!(cmd = getkeycmd()) || cmd == Th(z_sendbreak) || - cmd == Th(z_acceptline)) + if (!(cmd = getkeycmd()) || cmd == Th(z_sendbreak)) + break; + else if (cmd == Th(z_acceptline)) { + acc = 1; break; - else if (cmd == Th(z_acceptandhold) || + } else if (cmd == Th(z_acceptandhold) || cmd == Th(z_acceptandmenucomplete)) { Menustack s = (Menustack) zhalloc(sizeof(*s)); @@ -825,11 +849,16 @@ domenuselect(Hookdef dummy, Chdata dat) selectlocalmap(NULL); mselect = -1; inselect = 0; + if (acc) { + menucmp = 0; + lastambig = 0; + do_single(*(minfo.cur)); + } if (!noselect) { showinglist = -2; zrefresh(); } - return noselect; + return (!noselect ^ acc); } /* The widget function. */ diff --git a/Src/Zle/deltochar.c b/Src/Zle/deltochar.c index b9fb34f10..f0df33f95 100644 --- a/Src/Zle/deltochar.c +++ b/Src/Zle/deltochar.c @@ -67,8 +67,6 @@ deltochar(char **args) } } } - 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..e6f469ad0 100644 --- a/Src/Zle/zle.export +++ b/Src/Zle/zle.export @@ -1,10 +1,46 @@ #! +acceptlast addzlefunction backdel backkill +bindkey +clearflag +clearscreen deletezlefunction +do_menucmp +do_single feep foredel forekill getkey +getkeycmd +getzlequery +lastambig +linkkeymap +listshown +menucmp +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 8ab86f042..ff515e7c4 100644 --- a/Src/Zle/zle.h +++ b/Src/Zle/zle.h @@ -143,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 66abbe438..f85fa00a6 100644 --- a/Src/Zle/zle_hist.c +++ b/Src/Zle/zle_hist.c @@ -77,10 +77,8 @@ int uphistory(char **args) { int nodups = isset(HISTIGNOREDUPS); - if (!zle_goto_hist(histline, -zmult, nodups) && isset(HISTBEEP)) { - feep(); + if (!zle_goto_hist(histline, -zmult, nodups) && isset(HISTBEEP)) return 1; - } return 0; } @@ -128,10 +126,8 @@ uplineorhistory(char **args) int m = zmult, ret; cs = ocs; - if (virangeflag || !histallowed) { - feep(); + if (virangeflag || !histallowed) return 1; - } zmult = n; ret = uphistory(args); zmult = m; @@ -160,10 +156,8 @@ uplineorsearch(char **args) int m = zmult, ret; cs = ocs; - if (virangeflag || !histallowed) { - feep(); + if (virangeflag || !histallowed) return 1; - } zmult = n; ret = historysearchbackward(args); zmult = m; @@ -216,10 +210,8 @@ downlineorhistory(char **args) int m = zmult, ret; cs = ocs; - if (virangeflag || !histallowed) { - feep(); + if (virangeflag || !histallowed) return 1; - } zmult = n; ret = downhistory(args); zmult = m; @@ -248,10 +240,8 @@ downlineorsearch(char **args) int m = zmult, ret; cs = ocs; - if (virangeflag || !histallowed) { - feep(); + if (virangeflag || !histallowed) return 1; - } zmult = n; ret = historysearchforward(args); zmult = m; @@ -266,10 +256,8 @@ acceptlineanddownhistory(char **args) { Histent he; - if (!(he = movehistent(quietgethist(histline), 1, HIST_FOREIGN))) { - feep(); + if (!(he = movehistent(quietgethist(histline), 1, HIST_FOREIGN))) return 1; - } pushnode(bufstack, ztrdup(ZLETEXT(he))); done = 1; stackhist = he->histnum; @@ -281,10 +269,8 @@ int downhistory(char **args) { int nodups = isset(HISTIGNOREDUPS); - if (!zle_goto_hist(histline, zmult, nodups) && isset(HISTBEEP)) { - feep(); + if (!zle_goto_hist(histline, zmult, nodups) && isset(HISTBEEP)) return 1; - } return 0; } @@ -336,7 +322,6 @@ historysearchbackward(char **args) } } } - feep(); return 1; } @@ -385,7 +370,6 @@ historysearchforward(char **args) } } } - feep(); return 1; } @@ -404,10 +388,8 @@ beginningofbufferorhistory(char **args) int beginningofhistory(char **args) { - if (!zle_goto_hist(firsthist(), 0, 0) && isset(HISTBEEP)) { - feep(); + if (!zle_goto_hist(firsthist(), 0, 0) && isset(HISTBEEP)) return 1; - } return 0; } @@ -457,19 +439,15 @@ insertlastword(char **args) zsfree(lastinsert); lastinsert = NULL; } - if (!(he = quietgethist(evhist)) || !he->nwords) { - feep(); + 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(); + 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; @@ -591,7 +569,6 @@ getline(char **args) char *s = (char *)getlinknode(bufstack); if (!s) { - feep(); return 1; } else { int cc; @@ -693,7 +670,7 @@ doisearch(char **args, int dir) 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, savekeys = -1; + int hl = histline, savekeys = -1, feep = 0; Thingy cmd; char *okeymap = curkeymapname; static char *previous_search = NULL; @@ -762,7 +739,7 @@ doisearch(char **args, int dir) get_isrch_spot(top_spot, &hl, &pos, &cs, &sbptr, &dir, &nomatch); if (!nomatch) { - feep(); + feep = 1; nomatch = 1; } he = quietgethist(hl); @@ -803,7 +780,7 @@ doisearch(char **args, int dir) 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)) { @@ -811,7 +788,7 @@ doisearch(char **args, int dir) get_isrch_spot(--top_spot, &hl, &pos, &cs, &sbptr, &dir, &nomatch); else - feep(); + feep = 1; if (nomatch) { statusline = ibuf; skip_pos = 1; @@ -878,7 +855,7 @@ doisearch(char **args, int dir) zrefresh(); } if ((c = getkey(0)) == EOF) - feep(); + feep = 1; else goto ins; } else { @@ -896,7 +873,7 @@ doisearch(char **args, int dir) } ins: if (sbptr == PATH_MAX) { - feep(); + feep = 1; continue; } set_isrch_spot(top_spot++, hl, pos, cs, sbptr, dir, nomatch); @@ -907,7 +884,9 @@ doisearch(char **args, int dir) } sbuf[sbptr++] = c; } - handlefeep(); + if (feep) + handlefeep(zlenoargs); + feep = 0; } if (sbptr) { zfree(previous_search, previous_search_len); @@ -957,7 +936,6 @@ infernexthistory(char **args) return 0; } } - feep(); return 1; } @@ -976,7 +954,6 @@ vifetchhistory(char **args) } if (!zle_goto_hist((zmod.flags & MOD_MULT) ? zmult : curhist, 0, 0) && isset(HISTBEEP)) { - feep(); return 1; } return 0; @@ -992,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; @@ -1045,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)) { @@ -1062,9 +1039,11 @@ getvisrchstr(void) } sbuf[sptr++] = c; } else { - feep(); + feep = 1; } - handlefeep(); + if (feep) + handlefeep(zlenoargs); + feep = 0; } statusline = NULL; selectkeymap(okeymap, 1); @@ -1122,10 +1101,8 @@ virepeatsearch(char **args) int n = zmult; char *s; - if (!visrchstr) { - feep(); + if (!visrchstr) return 1; - } if (zmult < 0) { n = -n; visrchsense = -visrchsense; @@ -1145,7 +1122,6 @@ virepeatsearch(char **args) } } } - feep(); return 1; } @@ -1194,7 +1170,6 @@ historybeginningsearchbackward(char **args) } } } - feep(); return 1; } @@ -1231,6 +1206,5 @@ historybeginningsearchforward(char **args) } } } - 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 e2b64cb3c..8f6dfdf75 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -106,13 +106,7 @@ struct modifier zmod; /**/ int prefixflag; -/* != 0 if there is a pending beep (usually indicating an error) */ - -/**/ -int feepflag; - /* Number of characters waiting to be read by the ungetkeys mechanism */ - /**/ int kungetct; @@ -507,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); @@ -535,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, zlenoargs); + if (execzlefunc(bindk, zlenoargs)) + handlefeep(zlenoargs); handleprefixes(); /* for vi mode, make sure the cursor isn't somewhere illegal */ if (invicmdmode() && cs > findbol() && @@ -573,7 +569,6 @@ zleread(char *lp, char *rp, int flags) #endif if (!kungetct) zrefresh(); - handlefeep(); } statusline = NULL; invalidatelist(); @@ -613,7 +608,7 @@ execzlefunc(Thingy func, char **args) zsfree(nm); showmsg(msg); zsfree(msg); - feep(); + ret = 1; } else if((w = func->widget)->flags & (WIDGET_INT|WIDGET_NCOMP)) { int wflags = w->flags; @@ -646,7 +641,7 @@ execzlefunc(Thingy func, char **args) zsfree(nm); showmsg(msg); zsfree(msg); - feep(); + ret = 1; } else { int osc = sfcontext, osi = movefd(0), olv = lastval; LinkList largs = NULL; @@ -953,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, "lDANCLmMgGcR", 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), }; /**/ @@ -999,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; } @@ -1014,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; } diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c index 4d731a21c..a51cdf92e 100644 --- a/Src/Zle/zle_misc.c +++ b/Src/Zle/zle_misc.c @@ -98,7 +98,6 @@ deletechar(char **args) backdel(zmult); return 0; } - feep(); return 1; } @@ -182,7 +181,6 @@ gosmacstransposechars(char **args) if (cs == ll || line[cs] == '\n' || ((cs + 1 == ll || line[cs + 1] == '\n') && (!cs || line[cs - 1] == '\n'))) { - feep(); return 1; } cs += (cs == 0 || line[cs - 1] == '\n') ? 2 : 1; @@ -205,10 +203,8 @@ transposechars(char **args) n = -n; while (n--) { if (!(ct = cs) || line[cs - 1] == '\n') { - if (ll == cs || line[cs] == '\n') { - feep(); + if (ll == cs || line[cs] == '\n') return 1; - } if (!neg) cs++; ct++; @@ -225,10 +221,8 @@ transposechars(char **args) } if (ct == ll || line[ct] == '\n') ct--; - if (ct < 1 || line[ct - 1] == '\n') { - feep(); + if (ct < 1 || line[ct - 1] == '\n') return 1; - } cc = line[ct - 1]; line[ct - 1] = line[ct]; line[ct] = cc; @@ -350,10 +344,8 @@ yank(char **args) return 1; if (zmod.flags & MOD_VIBUF) buf = &vibuf[zmod.vibuf]; - if (!buf->buf) { - feep(); + if (!buf->buf) return 1; - } mark = cs; yankb = cs; while (n--) { @@ -372,10 +364,8 @@ yankpop(char **args) { int cc; - if (!(lastcmd & ZLE_YANK) || !kring[kct].buf) { - feep(); + if (!(lastcmd & ZLE_YANK) || !kring[kct].buf) return 1; - } cs = yankb; foredel(yanke - yankb); cc = kring[kct].len; @@ -438,7 +428,6 @@ whatcursorposition(char **args) int undefinedkey(char **args) { - feep(); return 1; } @@ -457,10 +446,9 @@ quotedinsert(char **args) #ifndef HAS_TIO zsetterm(); #endif - if (c < 0) { - feep(); + if (c < 0) return 1; - } else + else return selfinsert(args); } @@ -470,10 +458,8 @@ digitargument(char **args) { int sign = (zmult < 0) ? -1 : 1; - if (c < '0' || c > '9') { - feep(); + if (c < '0' || c > '9') return 1; - } if (!(zmod.flags & MOD_TMULT)) zmod.tmult = 0; @@ -493,10 +479,8 @@ digitargument(char **args) int negargument(char **args) { - if (zmod.flags & MOD_TMULT) { - feep(); + if (zmod.flags & MOD_TMULT) return 1; - } zmod.tmult = -1; zmod.flags |= MOD_TMULT|MOD_NEG; prefixflag = 1; @@ -655,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; @@ -688,12 +672,12 @@ executenamedcommand(char *prmt) 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) || @@ -744,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; @@ -766,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); @@ -776,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 e2096f6cf..9189218f1 100644 --- a/Src/Zle/zle_move.c +++ b/Src/Zle/zle_move.c @@ -228,7 +228,6 @@ vimatchbracket(char **args) otog: if (cs == ll || line[cs] == '\n') { - feep(); cs = ocs; return 1; } @@ -273,7 +272,6 @@ vimatchbracket(char **args) ct++; } if (cs < 0 || cs >= ll) { - feep(); cs = ocs; return 1; } else if(dir > 0 && virangeflag) @@ -295,10 +293,8 @@ viforwardchar(char **args) zmult = n; return ret; } - if (cs >= lim) { - feep(); + if (cs >= lim) return 1; - } while (n-- && cs < lim) cs++; return 0; @@ -317,10 +313,8 @@ vibackwardchar(char **args) zmult = n; return ret; } - if (cs == findbol()) { - feep(); + if (cs == findbol()) return 1; - } while (n--) { cs--; if (cs < 0 || line[cs] == '\n') { @@ -337,14 +331,11 @@ viendofline(char **args) { int oldcs = cs, n = zmult; - if (n < 1) { - feep(); + if (n < 1) return 1; - } while(n--) { if (cs > ll) { cs = oldcs; - feep(); return 1; } cs = findeol() + 1; @@ -385,7 +376,7 @@ vifindprevchar(char **args) tailadd = 0; return virepeatfind(args); } - return 0; + return 1; } /**/ @@ -418,10 +409,8 @@ virepeatfind(char **args) { int ocs = cs, n = zmult; - if (!vfinddir) { - feep(); + if (!vfinddir) return 1; - } if (n < 0) { int ret; zmult = -n; @@ -434,7 +423,6 @@ virepeatfind(char **args) 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 1; } @@ -480,10 +468,8 @@ visetmark(char **args) int ch; ch = getkey(0); - if (ch < 'a' || ch > 'z') { - feep(); + if (ch < 'a' || ch > 'z') return 1; - } ch -= 'a'; vimarkcs[ch] = cs; vimarkline[ch] = histline; @@ -500,19 +486,14 @@ vigotomark(char **args) if (ch == c) ch = 26; else { - if (ch < 'a' || ch > 'z') { - feep(); + if (ch < 'a' || ch > 'z') return 1; - } ch -= 'a'; } - if (!vimarkline[ch]) { - feep(); + if (!vimarkline[ch]) return 1; - } if (curhist != vimarkline[ch] && !zle_goto_hist(vimarkline[ch], 0, 0)) { vimarkline[ch] = 0; - feep(); return 1; } cs = vimarkcs[ch]; diff --git a/Src/Zle/zle_params.c b/Src/Zle/zle_params.c index 221440a46..bac399e7d 100644 --- a/Src/Zle/zle_params.c +++ b/Src/Zle/zle_params.c @@ -84,7 +84,7 @@ 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"); diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c index da0b38bfe..dd4310078 100644 --- a/Src/Zle/zle_refresh.c +++ b/Src/Zle/zle_refresh.c @@ -495,7 +495,7 @@ zrefresh(void) /* if old line and new line are different, see if we can insert/delete a line to speed up update */ - if (ln < olnct - 1 && !(hasam && vcs == winw) && + if (ln > 0 && ln < olnct - 1 && !(hasam && vcs == winw) && nbuf[ln] && obuf[ln] && strncmp(nbuf[ln], obuf[ln], 16)) { if (tccan(TCDELLINE) && obuf[ln + 1] && obuf[ln + 1][0] && diff --git a/Src/Zle/zle_thingy.c b/Src/Zle/zle_thingy.c index 2950d55d9..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,7 +335,7 @@ 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 }, @@ -373,8 +374,21 @@ 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']); - return 0; + 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; + } } /**/ @@ -405,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) { @@ -536,6 +554,7 @@ 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", @@ -543,6 +562,12 @@ bin_zle_call(char *name, char **args, char *ops, char func) return 1; } + 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] == '-') { @@ -577,14 +602,8 @@ bin_zle_call(char *name, char **args, char *ops, char func) } args++; } - if (!args[0]) { - zwarnnam(name, "wrong number of arguments", NULL, 0); - if (saveflag) - zmod = modsave; - return 1; - } - t = rthingy(*args++); + t = rthingy(wname); PERMALLOC { ret = execzlefunc(t, args); } LASTALLOC; diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c index bb0a3cac0..f7b243d31 100644 --- a/Src/Zle/zle_tricky.c +++ b/Src/Zle/zle_tricky.c @@ -98,7 +98,7 @@ static int showagain = 0; /* The match and group number to insert when starting menucompletion. */ -static int insmnum, insgnum, insgroup; +static int insmnum, insgnum, insgroup, insspace; /* This is used to decide when the cursor should be moved to the end of * * the inserted word: 0 - never, 1 - only when a single match is inserted, * @@ -108,22 +108,13 @@ static int movetoend; /* != 0 if we are in the middle of a menu completion */ -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). */ - -static Cmgroup menugrp; -static Cmatch *menucur; +/**/ +int menucmp; -/* 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. */ +/* Information about menucompletion. */ -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. * @@ -356,7 +347,8 @@ enum { COMP_COMPLETE, * on the second tab, a` la bash, and then automenu kicks in when * * lastambig == 2. */ -static int lastambig; +/**/ +int lastambig; /* This says what of the state the line is in when completion is started * * came from a previous completion. If the FC_LINE bit is set, the * @@ -388,7 +380,8 @@ completecall(char **args) cfargs = args; cfret = 0; compfunc = compwidget->u.comp.func; - compwidget->u.comp.fn(zlenoargs); + if (compwidget->u.comp.fn(zlenoargs) && !cfret) + cfret = 1; compfunc = NULL; return cfret; @@ -446,8 +439,8 @@ spellword(char **args) int deletecharorlist(char **args) { - Cmgroup mg = menugrp; - Cmatch *mc = menucur; + Cmgroup mg = minfo.group; + Cmatch *mc = minfo.cur; int ret; usemenu = !!isset(MENUCOMPLETE); @@ -458,8 +451,8 @@ deletecharorlist(char **args) } else ret = docomplete(COMP_LIST_COMPLETE); - menucur = mc; - menugrp = mg; + minfo.cur = mc; + minfo.group = mg; return ret; } @@ -522,16 +515,16 @@ reversemenucomplete(char **args) 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; @@ -541,7 +534,8 @@ reversemenucomplete(char **args) * 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) { @@ -557,13 +551,13 @@ 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; } } @@ -571,10 +565,8 @@ acceptlast(void) int acceptandmenucomplete(char **args) { - if (!menucmp) { - feep(); + if (!menucmp) return 1; - } acceptlast(); return menucomplete(args); } @@ -807,7 +799,7 @@ static int docomplete(int lst) { char *s, *ol; - int olst = lst, chl = 0, ne = noerrs, ocs, ret = 0;; + int olst = lst, chl = 0, ne = noerrs, ocs, ret = 0, omc = menucmp; if (showagain && validlist) showinglist = -2; @@ -889,7 +881,6 @@ docomplete(int lst) ll = strlen((char *) line); cs = ocs; unmetafy_line(); - feep(); return 1; } ocs = cs; @@ -1062,6 +1053,16 @@ docomplete(int lst) popheap(); zsfree(qword); unmetafy_line(); + + if (menucmp && !omc) { + struct chdata dat; + + dat.matches = amatches; + dat.num = nmatches; + dat.cur = NULL; + if (runhookdef(MENUSTARTHOOK, (void *) &dat)) + menucmp = 0; + } return ret; } @@ -1071,7 +1072,7 @@ docomplete(int lst) * insert the next completion. */ /**/ -static void +void do_menucmp(int lst) { /* Just list the matches if the list was requested. */ @@ -1081,16 +1082,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; } @@ -1444,7 +1445,6 @@ get_comp_string(void) lexrestore(); goto start; } - feep(); noaliases = 0; lexrestore(); LASTALLOC_RETURN NULL; @@ -1757,11 +1757,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 && @@ -1771,8 +1768,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) { @@ -3824,6 +3819,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++) { @@ -3849,8 +3848,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, @@ -4358,7 +4359,6 @@ docompletion(char *s, int lst, int incmd) foredel(ll); inststr(origline); cs = origcs; - feep(); clearlist = 1; ret = 1; goto compend; @@ -4370,17 +4370,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(); } @@ -4394,7 +4394,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)) @@ -4636,8 +4636,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 @@ -4704,6 +4704,7 @@ callcompfunc(char *s, char *fn) insgroup = 1; insgnum = atoi(m + 1); } + insspace = (compinsert[strlen(compinsert) - 1] == ' '); } else useline = usemenu = 0; useexact = (compexact && !strcmp(compexact, "accept")); @@ -4718,7 +4719,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)); @@ -5635,7 +5636,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]); @@ -6365,20 +6366,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))) @@ -6625,7 +6620,8 @@ invalidatelist(void) if (validlist) freematches(); lastambig = menucmp = validlist = showinglist = fromcomp = 0; - menucur = NULL; + minfo.cur = NULL; + minfo.asked = 0; compwidget = NULL; } @@ -7392,19 +7388,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, * @@ -7424,7 +7421,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); @@ -7473,19 +7471,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' * @@ -7495,7 +7495,7 @@ do_ambiguous(void) * (l)stat(). */ /**/ -static int +int ztat(char *nam, struct stat *buf, int ls) { char b[PATH_MAX], *p; @@ -7513,7 +7513,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; @@ -7526,39 +7526,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; } } @@ -7574,11 +7574,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 * @@ -7614,10 +7614,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)) { @@ -7627,8 +7627,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) { @@ -7644,9 +7644,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)) { @@ -7655,20 +7655,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 || insspace)) { 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 && !minfo.we) || !movetoend) + cs = minfo.end; + { + Cmatch *om = minfo.cur; + struct chdata dat; - if ((menucmp && !menuwe) || !movetoend) - cs = menuend; + 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 @@ -7698,40 +7711,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. */ @@ -7770,7 +7785,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]; @@ -7853,7 +7868,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)) @@ -7868,11 +7884,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 */ @@ -7882,6 +7894,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; @@ -7966,8 +7994,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); @@ -7981,7 +8010,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); @@ -7991,6 +8022,8 @@ listmatches(void) } else putc('\n', shout); settyinfo(&shttyinfo); + if (minfo.cur) + minfo.asked = 1; } /* Now print the matches. */ @@ -8110,6 +8143,7 @@ listmatches(void) clearflag = 0, putc('\n', shout); } else putc('\n', shout); + return 0; } /* This is used to print expansions. */ @@ -8119,9 +8153,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; @@ -8129,12 +8163,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; @@ -8213,18 +8247,17 @@ magicspace(char **args) { int ret; c = ' '; - ret = selfinsert(args); - return !doexpandhist(); + if (!(ret = selfinsert(args))) + doexpandhist(); + return ret; } /**/ int expandhistory(char **args) { - if (!doexpandhist()) { - feep(); + if (!doexpandhist()) return 1; - } return 0; } @@ -8276,10 +8309,8 @@ processcmd(char **args) int m = zmult; s = getcurcmd(); - if (!s) { - feep(); + if (!s) return 1; - } zmult = 1; pushline(zlenoargs); zmult = m; @@ -8304,16 +8335,12 @@ expandcmdpath(char **args) noaliases = 1; s = getcurcmd(); noaliases = na; - if (!s || cmdwb < 0 || cmdwe < cmdwb) { - feep(); + if (!s || cmdwb < 0 || cmdwe < cmdwb) return 1; - } str = findcmd(s, 1); zsfree(s); - if (!str) { - feep(); + if (!str) return 1; - } cs = cmdwb; foredel(cmdwe - cmdwb); spaceinline(strlen(str)); diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c index cc9c9bf37..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; } /***************/ @@ -559,10 +551,8 @@ undo(char **args) { handleundo(); do { - if(!curchange->prev) { - feep(); + if(!curchange->prev) return 1; - } unapplychange(curchange = curchange->prev); } while(curchange->flags & CH_PREV); setlastline(); @@ -598,10 +588,8 @@ redo(char **args) { handleundo(); do { - if(!curchange->next) { - feep(); + if(!curchange->next) return 1; - } applychange(curchange); curchange = curchange->next; } while(curchange->prev->flags & CH_NEXT); diff --git a/Src/Zle/zle_vi.c b/Src/Zle/zle_vi.c index 08de69c19..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, zlenoargs); + /* + * 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,12 +249,12 @@ dovilinerange(void) cs = findbol() - 1; if (n != 1) { cs = pos; - feep(); - return; + return 1; } cs++; } virangeflag = 2; + return 0; } /**/ @@ -309,11 +297,12 @@ viinsertbol(char **args) 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--; @@ -322,7 +311,7 @@ videlete(char **args) } } vichgflag = 0; - return 0; + return ret; } /**/ @@ -341,10 +330,8 @@ videletechar(char **args) return ret; } /* it is an error to be on the end of line */ - if (cs == ll || line[cs] == '\n') { - feep(); + 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) @@ -358,16 +345,17 @@ videletechar(char **args) 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 0; + return ret; } /**/ @@ -377,15 +365,11 @@ visubstitute(char **args) int n = zmult; startvichange(1); - if (n < 0) { - feep(); + if (n < 0) return 1; - } /* it is an error to be on the end of line */ - if (cs == ll || line[cs] == '\n') { - feep(); + 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) @@ -436,10 +420,8 @@ viyankeol(char **args) int x = findeol(); startvichange(-1); - if (x == cs) { - feep(); + if (x == cs) return 1; - } cut(cs, x - cs, 0); return 0; } @@ -456,7 +438,6 @@ viyankwholeline(char **args) return 1; while(n--) { if (cs > ll) { - feep(); cs = oldcs; return 1; } @@ -498,23 +479,18 @@ vireplacechars(char **args) 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 1; } /* get key */ if((ch = vigetkey()) == -1) { vichgflag = 0; - feep(); return 1; } /* do change */ @@ -537,7 +513,7 @@ int vicmdmode(char **args) { if (invicmdmode() || selectkeymap("vicmd", 0)) - feep(); + return 1; undoing = 1; vichgflag = 0; if (cs != findbol()) @@ -573,7 +549,7 @@ viopenlineabove(char **args) int vioperswapcase(char **args) { - int oldcs, c2; + int oldcs, c2, ret = 1; /* get the range */ startvichange(1); @@ -589,12 +565,13 @@ vioperswapcase(char **args) } /* go back to the first line of the range */ cs = oldcs; + ret = 0; #if 0 vifirstnonblank(); #endif } vichgflag = 0; - return 0; + return ret; } /**/ @@ -602,10 +579,8 @@ int virepeatchange(char **args) { /* make sure we have a change to repeat */ - if (!vichgbuf || vichgflag) { - feep(); + if (!vichgbuf || vichgflag) return 1; - } /* restore or update the saved count and buffer */ if (zmod.flags & MOD_MULT) { lastmod.mult = zmod.mult; @@ -637,7 +612,6 @@ viindent(char **args) vichgflag = 0; /* must be a line range */ if (!vilinerange) { - feep(); cs = oldcs; return 1; } @@ -669,7 +643,6 @@ viunindent(char **args) vichgflag = 0; /* must be a line range */ if (!vilinerange) { - feep(); cs = oldcs; return 1; } @@ -705,7 +678,6 @@ vibackwarddeletechar(char **args) /* 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 1; } /* Put argument into the acceptable range -- it is not an error to * @@ -721,10 +693,8 @@ vibackwarddeletechar(char **args) int vikillline(char **args) { - if (viinsbegin > cs) { - feep(); + if (viinsbegin > cs) return 1; - } backdel(cs - viinsbegin); return 0; } @@ -741,10 +711,8 @@ viputbefore(char **args) return 1; if (zmod.flags & MOD_VIBUF) buf = &vibuf[zmod.vibuf]; - if (!buf->buf) { - feep(); + if (!buf->buf) return 1; - } if(buf->flags & CUTBUFFER_LINE) { cs = findbol(); spaceinline(buf->len + 1); @@ -775,10 +743,8 @@ viputafter(char **args) return 1; if (zmod.flags & MOD_VIBUF) buf = &vibuf[zmod.vibuf]; - if (!buf->buf) { - feep(); + if (!buf->buf) return 1; - } if(buf->flags & CUTBUFFER_LINE) { cs = findeol(); spaceinline(buf->len + 1); @@ -806,10 +772,8 @@ vijoin(char **args) int x; startvichange(-1); - if ((x = findeol()) == ll) { - feep(); + if ((x = findeol()) == ll) return 1; - } cs = x + 1; for (x = 1; cs != ll && iblank(line[cs]); cs++, x++); backdel(x); @@ -866,10 +830,8 @@ visetbuffer(char **args) if ((zmod.flags & MOD_VIBUF) || (((ch = getkey(0)) < '1' || ch > '9') && - (ch < 'a' || ch > 'z') && (ch < 'A' || ch > 'Z'))) { - feep(); + (ch < 'a' || ch > 'z') && (ch < 'A' || ch > 'Z'))) return 1; - } if (ch >= 'A' && ch <= 'Z') /* needed in cut() */ zmod.flags |= MOD_VIAPP; else @@ -889,7 +851,6 @@ vikilleol(char **args) startvichange(-1); if (!n) { /* error -- line already empty */ - feep(); return 1; } /* delete to end of line */ @@ -941,10 +902,9 @@ viquotedinsert(char **args) zsetterm(); #endif foredel(1); - if(c < 0) { - feep(); + if(c < 0) return 1; - } else + else return selfinsert(args); } diff --git a/Src/Zle/zle_word.c b/Src/Zle/zle_word.c index e768cbefa..31f83a2df 100644 --- a/Src/Zle/zle_word.c +++ b/Src/Zle/zle_word.c @@ -300,10 +300,8 @@ vibackwardkillword(char **args) int x = cs, lim = (viinsbegin > findbol()) ? viinsbegin : findbol(); int n = zmult; - if (n < 0) { - feep(); + if (n < 0) return 1; - } /* this taken from "vibackwardword" */ while (n--) { while ((x > lim) && iblank(line[x - 1])) @@ -479,22 +477,16 @@ transposewords(char **args) x = cs; while (x && line[x - 1] != '\n' && !iword(line[x])) x--; - if (!x || line[x - 1] == '\n') { - feep(); + 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(); + if (!p3) return 1; - } for (p2 = p3; p2 && !iword(line[p2 - 1]); p2--); - if (!p2) { - feep(); + 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); diff --git a/Src/builtin.c b/Src/builtin.c index 26bd9d74f..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 }; @@ -1492,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) @@ -1502,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", @@ -1519,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; @@ -1605,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)); @@ -1678,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; @@ -3074,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; } diff --git a/Src/exec.c b/Src/exec.c index 768706f4c..bc5548f1e 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -302,7 +302,7 @@ static char list_pipe_text[JOBTEXTSIZE]; static int execcursh(Cmd cmd, LinkList args, int flags) { - if (!list_pipe) + if (!list_pipe && thisjob != list_pipe_job) deletejob(jobtab + thisjob); cmdpush(CS_CURSH); execlist(cmd->u.list, 1, flags & CFLAG_EXEC); @@ -828,7 +828,7 @@ execpline(Sublist l, int how, int last1) int ipipe[2], opipe[2]; int pj, newjob; int old_simple_pline = simple_pline; - static int lastwj; + static int lastwj, lpforked; if (!l->left) return lastval = (l->flags & PFLAG_NOT) != 0; @@ -865,7 +865,7 @@ execpline(Sublist l, int how, int last1) nowait = 0; simple_pline = (l->left->type == END); } - lastwj = 0; + lastwj = lpforked = 0; execpline2(l->left, how, opipe[0], ipipe[1], last1); pline_level--; if (how & Z_ASYNC) { @@ -890,7 +890,7 @@ execpline(Sublist l, int how, int last1) lastwj = thisjob = newjob; - if (list_pipe) + if (list_pipe || (pline_level && !(how & Z_TIMED))) jn->stat |= STAT_NOPRINT; if (nowait) { @@ -901,6 +901,11 @@ execpline(Sublist l, int how, int last1) DPUTS(!list_pipe_pid, "invalid list_pipe_pid"); addproc(list_pipe_pid, list_pipe_text); + /* If the super-job contains only the sub-shell, the + sub-shell is the group leader. */ + if (!jn->procs->next || lpforked == 2) + jn->gleader = list_pipe_pid; + for (pn = jobtab[jn->other].procs; pn; pn = pn->next) if (WIFSTOPPED(pn->status)) break; @@ -914,12 +919,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 || pline_level) { + if (list_pipe_child) { jn->stat |= STAT_NOPRINT; makerunning(jn); } @@ -930,8 +937,11 @@ execpline(Sublist l, int how, int last1) jn->stat & STAT_DONE && lastval2 & 0200) killpg(mypgrp, lastval2 & ~0200); - if ((list_pipe || last1 || pline_level) && - !list_pipe_child && jn->stat & STAT_STOPPED) { + if (!list_pipe_child && !lpforked && !subsh && + (list_pipe || last1 || pline_level) && + ((jn->stat & STAT_STOPPED) || + (list_pipe_job && pline_level && + (jobtab[list_pipe_job].stat & STAT_STOPPED)))) { pid_t pid; int synch[2]; @@ -951,28 +961,41 @@ execpline(Sublist l, int how, int last1) else if (pid) { char dummy; + lpforked = + (killpg(jobtab[list_pipe_job].gleader, 0) == -1 ? 2 : 1); list_pipe_pid = pid; nowait = errflag = 1; breaks = loops; 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; - if (list_pipe || last1) + /* 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) { + if (setpgrp(0L, mypgrp = jobtab[list_pipe_job].gleader) + == -1) { + setpgrp(0L, mypgrp = getpid()); + } + } else + setpgrp(0L, mypgrp = getpid()); close(synch[1]); kill(getpid(), SIGSTOP); list_pipe = 0; list_pipe_child = 1; + opts[INTERACTIVE] = 0; break; } } @@ -985,12 +1008,11 @@ execpline(Sublist l, int how, int last1) if (list_pipe && (lastval & 0200) && pj >= 0 && (!(jn->stat & STAT_INUSE) || (jn->stat & STAT_DONE))) { + deletejob(jn); jn = jobtab + pj; - jn->stat |= STAT_NOPRINT; - killjb(jobtab + pj, lastval & ~0200); + killjb(jn, lastval & ~0200); } - if (list_pipe_child || ((list_pipe || pline_level) && - (jn->stat & STAT_DONE))) + if (list_pipe_child || (list_pipe && (jn->stat & STAT_DONE))) deletejob(jn); thisjob = pj; @@ -1117,7 +1139,8 @@ void untokenize(char *s) { if (*s) { - char *p = s, c; + char *p = s; + int c; while ((c = *s++)) if (itok(c)) { @@ -1569,8 +1592,10 @@ execcmd(Cmd cmd, int input, int output, int how, int last1) is_builtin = 1; #ifdef DYNAMIC /* autoload the builtin if necessary */ - if (!((Builtin) hn)->handlerfunc) + if (!((Builtin) hn)->handlerfunc) { load_module(((Builtin) hn)->optstr); + hn = builtintab->getnode(builtintab, cmdarg); + } #endif break; } @@ -2187,15 +2212,14 @@ entersubsh(int how, int cl, int fake) if (kill(jobtab[list_pipe_job].gleader, 0) == -1 || setpgrp(0L, jobtab[list_pipe_job].gleader) == -1) { jobtab[list_pipe_job].gleader = - jobtab[thisjob].gleader = mypgrp; - setpgrp(0L, mypgrp); - + jobtab[thisjob].gleader = (list_pipe_child ? mypgrp : getpid()); + setpgrp(0L, jobtab[list_pipe_job].gleader); if (how & Z_SYNC) attachtty(jobtab[thisjob].gleader); } } else if (!jobtab[thisjob].gleader || - (setpgrp(0L, jobtab[thisjob].gleader) == -1)) { + setpgrp(0L, jobtab[thisjob].gleader) == -1) { jobtab[thisjob].gleader = getpid(); if (list_pipe_job != thisjob && !jobtab[list_pipe_job].gleader) @@ -2783,14 +2807,13 @@ execshfunc(Cmd cmd, Shfunc shf, LinkList args) 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; printprompt4(); @@ -2869,7 +2892,7 @@ doshfunc(char *name, List list, LinkList doshargs, int flags, int noreturnval) { char **tab, **x, *oargv0 = NULL; int oldzoptind, oldlastval; - char saveopts[OPT_SIZE]; + char saveopts[OPT_SIZE], *oldscriptname; int obreaks = breaks; HEAPALLOC { @@ -2881,6 +2904,8 @@ doshfunc(char *name, List list, LinkList doshargs, int flags, int noreturnval) starttrapscope(); tab = pparams; + oldscriptname = scriptname; + scriptname = name; oldzoptind = zoptind; zoptind = 1; @@ -2923,6 +2948,7 @@ doshfunc(char *name, List list, LinkList doshargs, int flags, int noreturnval) argzero = oargv0; } zoptind = oldzoptind; + scriptname = oldscriptname; pparams = tab; if (isset(LOCALOPTIONS)) { 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/init.c b/Src/init.c index 10286ea87..2da409415 100644 --- a/Src/init.c +++ b/Src/init.c @@ -235,10 +235,10 @@ parseargs(char **argv) else dosetopt(optno, action, 1); break; - } else if (isspace(**argv)) { + } else if (isspace(STOUC(**argv))) { /* zsh's typtab not yet set, have to use ctype */ while (*++*argv) - if (!isspace(**argv)) { + if (!isspace(STOUC(**argv))) { zerr("bad option string: `%s'", args, 0); exit(1); } @@ -615,7 +615,8 @@ setupvals(void) prompt2 = ztrdup("%_> "); } prompt3 = ztrdup("?# "); - prompt4 = ztrdup("+ "); + prompt4 = (emulation == EMULATE_KSH || emulation == EMULATE_SH) + ? ztrdup("+ ") : ztrdup("+%N:%i> "); sprompt = ztrdup("zsh: correct '%R' to '%r' [nyae]? "); ifs = ztrdup(DEFAULT_IFS); diff --git a/Src/jobs.c b/Src/jobs.c index 31861e284..b2d7e9af1 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); @@ -176,13 +180,14 @@ update_job(Job jn) /* If we have `cat foo|while read a; grep $a bar;done' * and have hit ^Z, the sub-job is stopped, but the * super-job may still be running, waiting to be stopped - * or to exit. So we have to send it a SIGSTOP. */ + * or to exit. So we have to send it a SIGTSTP. */ int i; 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; } } @@ -667,6 +672,8 @@ deletejob(Job jn) if (jn->ty) zfree(jn->ty, sizeof(struct ttyinfo)); + if (jn->stat & STAT_WASSUPER) + deletejob(jobtab + jn->other); jn->gleader = jn->other = 0; jn->stat = jn->stty_in_env = 0; jn->procs = NULL; @@ -780,22 +787,38 @@ waitjob(int job, int sig) what this might be. --oberon errflag = 0; */ + if (subsh) { + killjb(jn, SIGCONT); + jn->stat &= ~STAT_STOPPED; + } if (jn->stat & STAT_SUPERJOB) { Job sj = jobtab + jn->other; - if (sj->stat & STAT_DONE) { + if ((sj->stat & STAT_DONE) || !sj->procs) { struct process *p; for (p = sj->procs; p; p = p->next) if (WIFSIGNALED(p->status)) { - killpg(jn->gleader, WTERMSIG(p->status)); + if (jn->gleader != mypgrp && jn->procs->next) + killpg(jn->gleader, WTERMSIG(p->status)); + else + kill(jn->procs->pid, WTERMSIG(p->status)); kill(sj->other, SIGCONT); kill(sj->other, WTERMSIG(p->status)); break; } if (!p) { + int cp; + jn->stat &= ~STAT_SUPERJOB; - if (WIFEXITED(jn->procs->status)) - jn->gleader = mypgrp; + jn->stat |= STAT_WASSUPER; + + if ((cp = ((WIFEXITED(jn->procs->status) || + WIFSIGNALED(jn->procs->status)) && + killpg(jn->gleader, 0) == -1))) { + Process p; + for (p = jn->procs; p->next; p = p->next); + jn->gleader = p->pid; + } /* This deleted the job too early if the parent shell waited for a command in a list that will be executed by the sub-shell (e.g.: if we have @@ -804,6 +827,11 @@ waitjob(int job, int sig) but the parent shell gets notified for the sleep. deletejob(sj); */ + /* If this super-job contains only the sub-shell, + we have to attach the tty to our process group + (which is shared by the sub-shell) now. */ + if (!jn->procs->next || cp || jn->procs->pid != jn->gleader) + attachtty(jn->gleader); kill(sj->other, SIGCONT); } curjob = jn - jobtab; @@ -813,7 +841,9 @@ waitjob(int job, int sig) jn->stat |= STAT_STOPPED; for (p = jn->procs; p; p = p->next) - p->status = sj->procs->status; + if (p->status == SP_RUNNING || + (!WIFEXITED(p->status) && !WIFSIGNALED(p->status))) + p->status = sj->procs->status; curjob = jn - jobtab; printjob(jn, !!isset(LONGLISTJOBS), 1); break; @@ -1232,7 +1262,14 @@ bin_fg(char *name, char **argv, char *ops, int func) fflush(shout); if (func != BIN_WAIT) { /* fg */ thisjob = job; - attachtty(jobtab[job].gleader); + if ((jobtab[job].stat & STAT_SUPERJOB) && + ((!jobtab[job].procs->next || + WIFEXITED(jobtab[job].procs->status) || + WIFSIGNALED(jobtab[job].procs->status))) && + jobtab[jobtab[job].other].gleader) + attachtty(jobtab[jobtab[job].other].gleader); + else + attachtty(jobtab[job].gleader); } } if (stopped) { diff --git a/Src/loop.c b/Src/loop.c index b35024d6b..16e4ff314 100644 --- a/Src/loop.c +++ b/Src/loop.c @@ -378,7 +378,7 @@ execif(Cmd cmd, LinkList args, int flags) noerrexit = olderrexit; if (*t) { - cmdpush(s ? CS_ELIFTHEN : CS_IFTHEN); + cmdpush(*i ? (s ? CS_ELIFTHEN : CS_IFTHEN) : CS_ELSE); execlist(*t, 1, flags & CFLAG_EXEC); cmdpop(); } else 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); @@ -725,6 +732,46 @@ bin_zmodload(char *nam, char **args, char *ops, int func) return 1; } +/**/ +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) @@ -1115,6 +1162,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 */ @@ -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/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/prompt.c b/Src/prompt.c index ad7cdbc31..89407694e 100644 --- a/Src/prompt.c +++ b/Src/prompt.c @@ -531,6 +531,14 @@ putpromptchar(int doprint, int endchar) if(Rstring) stradd(Rstring); break; + case 'i': + addbufspc(DIGBUFSIZE); + sprintf(bp, "%ld", (long)lineno); + bp += strlen(bp); + break; + case 'N': + stradd(scriptname ? scriptname : argzero); + break; case '\0': return 0; case Meta: diff --git a/Src/signals.c b/Src/signals.c index e9851b57a..d29bdd4b0 100644 --- a/Src/signals.c +++ b/Src/signals.c @@ -586,7 +586,10 @@ killjb(Job jn, int sig) for (pn = jn->procs; pn->next; pn = pn->next) err = kill(pn->pid, sig); - + + if (!jobtab[jn->other].procs && pn) + err = kill(pn->pid, sig); + return err; } diff --git a/Src/subst.c b/Src/subst.c index ab6bf84fb..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)); diff --git a/Src/utils.c b/Src/utils.c index 16dbe9229..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); @@ -2133,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); } 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 9cb186ffa..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 @@ -207,6 +211,7 @@ resetneeded restoredir reswdtab retflag +runhookdef runshfunc scancountparams scanhashtable diff --git a/Src/zsh.h b/Src/zsh.h index 23e84b2ec..88175eea6 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -278,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; /********************************/ @@ -628,10 +629,12 @@ struct job { #define STAT_INUSE (1<<6) /* this job entry is in use */ #define STAT_SUPERJOB (1<<7) /* job has a subjob */ #define STAT_SUBJOB (1<<8) /* job is a subjob */ -#define STAT_CURSH (1<<9) /* last command is in current shell */ -#define STAT_NOSTTY (1<<10) /* the tty settings are not inherited */ +#define STAT_WASSUPER (1<<9) /* was a super-job, sub-job needs to be */ + /* deleted */ +#define STAT_CURSH (1<<10) /* last command is in current shell */ +#define STAT_NOSTTY (1<<11) /* the tty settings are not inherited */ /* from this job when it exits. */ -#define STAT_ATTACH (1<<11) /* delay reattaching shell to tty */ +#define STAT_ATTACH (1<<12) /* delay reattaching shell to tty */ #define SP_RUNNING -1 /* fake status for jobs currently running */ @@ -887,6 +890,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 { @@ -959,12 +978,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) -- cgit 1.4.1