diff options
Diffstat (limited to 'Src/Zle')
-rw-r--r-- | Src/Zle/compcore.c | 10 | ||||
-rw-r--r-- | Src/Zle/compctl.c | 2 | ||||
-rw-r--r-- | Src/Zle/complete.c | 16 | ||||
-rw-r--r-- | Src/Zle/complist.c | 97 | ||||
-rw-r--r-- | Src/Zle/compresult.c | 83 | ||||
-rw-r--r-- | Src/Zle/computil.c | 2 | ||||
-rw-r--r-- | Src/Zle/iwidgets.list | 4 | ||||
-rw-r--r-- | Src/Zle/zle.h | 6 | ||||
-rw-r--r-- | Src/Zle/zle_bindings.c | 2 | ||||
-rw-r--r-- | Src/Zle/zle_hist.c | 23 | ||||
-rw-r--r-- | Src/Zle/zle_keymap.c | 8 | ||||
-rw-r--r-- | Src/Zle/zle_main.c | 20 | ||||
-rw-r--r-- | Src/Zle/zle_misc.c | 91 | ||||
-rw-r--r-- | Src/Zle/zle_move.c | 43 | ||||
-rw-r--r-- | Src/Zle/zle_params.c | 3 | ||||
-rw-r--r-- | Src/Zle/zle_refresh.c | 15 | ||||
-rw-r--r-- | Src/Zle/zle_tricky.c | 52 | ||||
-rw-r--r-- | Src/Zle/zle_utils.c | 51 |
18 files changed, 343 insertions, 185 deletions
diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c index d4051bda0..ae3a64074 100644 --- a/Src/Zle/compcore.c +++ b/Src/Zle/compcore.c @@ -327,9 +327,7 @@ do_completion(UNUSED(Hookdef dummy), Compldat dat) haspattern = 0; complistmax = getiparam("LISTMAX"); zsfree(complastprompt); - complastprompt = ztrdup(((isset(ALWAYSLASTPROMPT) && zmult == 1) || - (unset(ALWAYSLASTPROMPT) && zmult != 1)) ? - "yes" : ""); + complastprompt = ztrdup(isset(ALWAYSLASTPROMPT) ? "yes" : ""); dolastprompt = 1; zsfree(complist); complist = ztrdup(isset(LISTROWSFIRST) ? @@ -975,7 +973,7 @@ makecomplist(char *s, int incmd, int lst) mnum = 0; unambig_mnum = -1; isuf = NULL; - insmnum = 1; + insmnum = zmult; #if 0 /* group-numbers in compstate[insert] */ insgnum = 1; @@ -2051,7 +2049,7 @@ addmatches(Cadata dat, char **argv) Heap oldheap; SWITCHHEAPS(oldheap, compheap) { - if (dat->dummies) + if (dat->dummies >= 0) dat->aflags = ((dat->aflags | CAF_NOSORT | CAF_UNIQCON) & ~CAF_UNIQALL); @@ -2536,7 +2534,7 @@ addmatches(Cadata dat, char **argv) addmatch("<all>", dat->flags | CMF_ALL, &disp, 1); hasallmatch = 1; } - while (dat->dummies--) + while (dat->dummies-- > 0) addmatch("", dat->flags | CMF_DUMMY, &disp, 0); } SWITCHBACKHEAPS(oldheap); diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c index 189582d22..bac533e7e 100644 --- a/Src/Zle/compctl.c +++ b/Src/Zle/compctl.c @@ -1803,7 +1803,7 @@ ccmakehookfn(UNUSED(Hookdef dummy), struct ccmakedat *dat) mnum = 0; unambig_mnum = -1; isuf = NULL; - insmnum = 1; + insmnum = zmult; #if 0 /* group-numbers in compstate[insert] */ insgnum = 1; diff --git a/Src/Zle/complete.c b/Src/Zle/complete.c index ea5e41f5f..ee4e5b0a5 100644 --- a/Src/Zle/complete.c +++ b/Src/Zle/complete.c @@ -267,8 +267,12 @@ parse_cmatcher(char *name, char *s) s++; if (!*s || !*++s) { - if (name) - zwarnnam(name, "missing line pattern"); + if (name) { + if (both) + zwarnnam(name, "missing right anchor"); + else + zwarnnam(name, "missing line pattern"); + } return pcm_err; } } else @@ -288,6 +292,7 @@ parse_cmatcher(char *name, char *s) if ((fl & CMF_RIGHT) && !fl2 && (!*s || !*++s)) { if (name) zwarnnam(name, "missing right anchor"); + return pcm_err; } else if (!(fl & CMF_RIGHT) || fl2) { if (!*s) { if (name) @@ -313,8 +318,7 @@ parse_cmatcher(char *name, char *s) return pcm_err; } s++; - } else - right = NULL; + } if (*s == '*') { if (!(fl & (CMF_LEFT | CMF_RIGHT))) { @@ -537,7 +541,7 @@ bin_compadd(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) dat.match = NULL; dat.flags = 0; dat.aflags = CAF_MATCH; - dat.dummies = 0; + dat.dummies = -1; for (; *argv && **argv == '-'; argv++) { if (!(*argv)[1]) { @@ -1625,7 +1629,6 @@ boot_(Module m) addhookfunc("before_complete", (Hookfn) before_complete); addhookfunc("after_complete", (Hookfn) after_complete); addhookfunc("accept_completion", (Hookfn) accept_last); - addhookfunc("reverse_menu", (Hookfn) reverse_menu); addhookfunc("list_matches", (Hookfn) list_matches); addhookfunc("invalidate_list", (Hookfn) invalidate_list); (void)addhookdefs(m, comphooks, sizeof(comphooks)/sizeof(*comphooks)); @@ -1640,7 +1643,6 @@ cleanup_(Module m) deletehookfunc("before_complete", (Hookfn) before_complete); deletehookfunc("after_complete", (Hookfn) after_complete); deletehookfunc("accept_completion", (Hookfn) accept_last); - deletehookfunc("reverse_menu", (Hookfn) reverse_menu); deletehookfunc("list_matches", (Hookfn) list_matches); deletehookfunc("invalidate_list", (Hookfn) invalidate_list); (void)deletehookdefs(m, comphooks, diff --git a/Src/Zle/complist.c b/Src/Zle/complist.c index f54206619..fd90ccb31 100644 --- a/Src/Zle/complist.c +++ b/Src/Zle/complist.c @@ -507,8 +507,8 @@ getcols() max_caplen = lr_caplen = 0; mcolors.flags = 0; queue_signals(); - if (!(s = getsparam("ZLS_COLORS")) && - !(s = getsparam("ZLS_COLOURS"))) { + if (!(s = getsparam_u("ZLS_COLORS")) && + !(s = getsparam_u("ZLS_COLOURS"))) { for (i = 0; i < NUM_COLS; i++) mcolors.files[i] = filecol(""); mcolors.pats = NULL; @@ -728,7 +728,7 @@ clnicezputs(int do_colors, char *s, int ml) if (do_colors) initiscol(); - mb_metacharinit(); + mb_charinit(); while (umleft > 0) { size_t cnt = eol ? MB_INVALID : mbrtowc(&cc, uptr, umleft, &mbs); @@ -2071,6 +2071,7 @@ complistmatches(UNUSED(Hookdef dummy), Chdata dat) memset(mgtab, 0, i * sizeof(Cmgroup)); mlastcols = mcols = zterm_columns; mlastlines = mlines = listdat.nlines; + mmtabp = 0; } last_cap = (char *) zhalloc(max_caplen + 1); *last_cap = '\0'; @@ -2269,41 +2270,16 @@ msearchpop(int *backp) } static Cmatch ** -msearch(Cmatch **ptr, int ins, int back, int rep, int *wrapp) +msearch(Cmatch **ptr, char *ins, int back, int rep, int *wrapp) { -#ifdef MULTIBYTE_SUPPORT - /* MB_CUR_MAX may not be constant */ - VARARR(char, s, MB_CUR_MAX+1); -#else - char s[2]; -#endif Cmatch **p, *l = NULL, m; int x = mcol, y = mline; int ex, ey, wrap = 0, owrap = (msearchstate & MS_WRAPPED); msearchpush(ptr, back); - if (ins) { -#ifdef MULTIBYTE_SUPPORT - if (lastchar_wide_valid) - { - mbstate_t mbs; - int len; - - memset(&mbs, 0, sizeof(mbs)); - len = wcrtomb(s, lastchar_wide, &mbs); - if (len < 0) - len = 0; - s[len] = '\0'; - } else -#endif - { - s[0] = lastchar; - s[1] = '\0'; - } - - msearchstr = dyncat(msearchstr, s); - } + if (ins) + msearchstr = dyncat(msearchstr, ins); if (back) { ex = mcols - 1; ey = -1; @@ -2587,6 +2563,8 @@ domenuselect(Hookdef dummy, Chdata dat) } p = mmtabp; pg = mgtabp; + if (!p) /* selected match not in display, find line */ + continue; minfo.cur = *p; minfo.group = *pg; if (setwish) @@ -2603,6 +2581,7 @@ domenuselect(Hookdef dummy, Chdata dat) getk: if (!do_last_key) { + zmult = 1; cmd = getkeycmd(); if (mtab_been_reallocated) { do_last_key = 1; @@ -2680,7 +2659,7 @@ domenuselect(Hookdef dummy, Chdata dat) s->nbrbeg = nbrbeg; s->nbrend = nbrend; s->nmatches = nmatches; - s->origline = origline; + s->origline = dupstring(origline); s->origcs = origcs; s->origll = origll; s->status = dupstring(status); @@ -2811,7 +2790,7 @@ domenuselect(Hookdef dummy, Chdata dat) s->nbrbeg = nbrbeg; s->nbrend = nbrend; s->nmatches = nmatches; - s->origline = origline; + s->origline = dupstring(origline); s->origcs = origcs; s->origll = origll; s->status = dupstring(status); @@ -3273,38 +3252,74 @@ domenuselect(Hookdef dummy, Chdata dat) cmd == Th(z_historyincrementalsearchbackward) || ((mode == MM_FSEARCH || mode == MM_BSEARCH) && (cmd == Th(z_selfinsert) || - cmd == Th(z_selfinsertunmeta)))) { + cmd == Th(z_selfinsertunmeta) || + cmd == Th(z_bracketedpaste)))) { Cmatch **np, **op = p; int was = (mode == MM_FSEARCH || mode == MM_BSEARCH); - int ins = (cmd == Th(z_selfinsert) || cmd == Th(z_selfinsertunmeta)); + int ins = (cmd == Th(z_selfinsert) || cmd == Th(z_selfinsertunmeta) || + cmd == Th(z_bracketedpaste)); int back = (cmd == Th(z_historyincrementalsearchbackward)); int wrap; do { + char *toins = NULL; +#ifdef MULTIBYTE_SUPPORT + /* MB_CUR_MAX may not be constant */ + VARARR(char, insert, MB_CUR_MAX+1); +#else + char insert[2]; +#endif if (was) { p += wishcol - mcol; mcol = wishcol; } if (!ins) { if (was) { - if (!*msearchstr && lastsearch) { + if (!*msearchstr && lastsearch && + back == (mode == MM_BSEARCH)) { msearchstr = dupstring(lastsearch); mode = 0; } } else { msearchstr = ""; msearchstack = NULL; + msearchstate = MS_OK; } - } - if (cmd == Th(z_selfinsertunmeta)) { - fixunmeta(); - } + } else { + if (cmd == Th(z_selfinsertunmeta)) { + fixunmeta(); + } + if (cmd == Th(z_bracketedpaste)) { + toins = bracketedstring(); + } else { + toins = insert; +#ifdef MULTIBYTE_SUPPORT + if (lastchar_wide_valid) + { + mbstate_t mbs; + int len; + + memset(&mbs, 0, sizeof(mbs)); + len = wcrtomb(s, lastchar_wide, &mbs); + if (len < 0) + len = 0; + insert[len] = '\0'; + } else +#endif + { + insert[0] = lastchar; + insert[1] = '\0'; + } + } + } wrap = 0; - np = msearch(p, ins, (ins ? (mode == MM_BSEARCH) : back), + np = msearch(p, toins, (ins ? (mode == MM_BSEARCH) : back), (was && !ins), &wrap); if (!ins) mode = (back ? MM_BSEARCH : MM_FSEARCH); + else if (cmd == Th(z_bracketedpaste)) + free(toins); if (*msearchstr) { zsfree(lastsearch); diff --git a/Src/Zle/compresult.c b/Src/Zle/compresult.c index 9f383f4b8..7fec7c804 100644 --- a/Src/Zle/compresult.c +++ b/Src/Zle/compresult.c @@ -1220,25 +1220,39 @@ do_menucmp(int lst) was_meta = 1; /* Otherwise go to the next match in the array... */ - do { - if (!*++(minfo.cur)) { - do { - if (!(minfo.group = (minfo.group)->next)) { - minfo.group = amatches; + while (zmult) { + do { + if (zmult > 0) { + if (!*++(minfo.cur)) { + do { + if (!(minfo.group = (minfo.group)->next)) { + minfo.group = amatches; #ifdef ZSH_HEAP_DEBUG - if (memory_validate(minfo.group->heap_id)) { - HEAP_ERROR(minfo.group->heap_id); - } + if (memory_validate(minfo.group->heap_id)) { + HEAP_ERROR(minfo.group->heap_id); + } #endif + } + } while (!(minfo.group)->mcount); + minfo.cur = minfo.group->matches; } - } while (!(minfo.group)->mcount); - minfo.cur = minfo.group->matches; - } - } while ((menuacc && - !hasbrpsfx(*(minfo.cur), minfo.prebr, minfo.postbr)) || - ((*minfo.cur)->flags & CMF_DUMMY) || - (((*minfo.cur)->flags & (CMF_NOLIST | CMF_MULT)) && - (!(*minfo.cur)->str || !*(*minfo.cur)->str))); + } else { + if (minfo.cur == (minfo.group)->matches) { + do { + if (!(minfo.group = (minfo.group)->prev)) + minfo.group = lmatches; + } while (!(minfo.group)->mcount); + minfo.cur = (minfo.group)->matches + (minfo.group)->mcount - 1; + } else + minfo.cur--; + } + } while ((menuacc && + !hasbrpsfx(*(minfo.cur), minfo.prebr, minfo.postbr)) || + ((*minfo.cur)->flags & CMF_DUMMY) || + (((*minfo.cur)->flags & (CMF_NOLIST | CMF_MULT)) && + (!(*minfo.cur)->str || !*(*minfo.cur)->str))); + zmult -= (0 < zmult) - (zmult < 0); + } /* ... and insert it into the command line. */ do_single(*minfo.cur); @@ -1246,43 +1260,6 @@ do_menucmp(int lst) unmetafy_line(); } -/**/ -int -reverse_menu(UNUSED(Hookdef dummy), UNUSED(void *dummy2)) -{ - int was_meta; - - if (minfo.cur == NULL) - return 1; - - do { - if (minfo.cur == (minfo.group)->matches) { - do { - if (!(minfo.group = (minfo.group)->prev)) - minfo.group = lmatches; - } while (!(minfo.group)->mcount); - minfo.cur = (minfo.group)->matches + (minfo.group)->mcount - 1; - } else - minfo.cur--; - } while ((menuacc && - !hasbrpsfx(*(minfo.cur), minfo.prebr, minfo.postbr)) || - ((*minfo.cur)->flags & CMF_DUMMY) || - (((*minfo.cur)->flags & (CMF_NOLIST | CMF_MULT)) && - (!(*minfo.cur)->str || !*(*minfo.cur)->str))); - /* May already be metafied if called from within a selection */ - if (zlemetaline == NULL) { - metafy_line(); - was_meta = 0; - } - else - was_meta = 1; - do_single(*(minfo.cur)); - if (!was_meta) - unmetafy_line(); - - return 0; -} - /* Accepts the current completion and starts a new arg, * * with the next completions. This gives you a way to * * accept several selections from the list of matches. */ diff --git a/Src/Zle/computil.c b/Src/Zle/computil.c index 27938c17f..e5db0867b 100644 --- a/Src/Zle/computil.c +++ b/Src/Zle/computil.c @@ -4196,7 +4196,7 @@ cfp_matcher_range(Cmatcher *ms, char *add) addlen = MB_METACHARLENCONV(add, &addc); #ifdef MULTIBYTE_SUPPORT if (addc == WEOF) - addc = (wchar_t)(*p == Meta ? p[1] ^ 32 : *p); + addc = (wchar_t)(*add == Meta ? add[1] ^ 32 : *add); #endif if (!(m = *mp)) { diff --git a/Src/Zle/iwidgets.list b/Src/Zle/iwidgets.list index b41661a7d..2b2654c5d 100644 --- a/Src/Zle/iwidgets.list +++ b/Src/Zle/iwidgets.list @@ -28,12 +28,14 @@ "beginning-of-history", beginningofhistory, 0 "beginning-of-line", beginningofline, 0 "beginning-of-line-hist", beginningoflinehist, 0 +"bracketed-paste", bracketedpaste, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_YANKBEFORE "capitalize-word", capitalizeword, 0 "clear-screen", clearscreen, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL | ZLE_NOTCOMMAND "complete-word", completeword, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_ISCOMP "copy-prev-word", copyprevword, ZLE_KEEPSUFFIX "copy-prev-shell-word", copyprevshellword, ZLE_KEEPSUFFIX "copy-region-as-kill", copyregionaskill, ZLE_KEEPSUFFIX +"deactivate-region", deactivateregion, 0 "delete-char", deletechar, ZLE_KEEPSUFFIX "delete-char-or-list", deletecharorlist, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_ISCOMP "delete-word", deleteword, ZLE_KEEPSUFFIX @@ -93,7 +95,7 @@ "quoted-insert", quotedinsert, ZLE_MENUCMP | ZLE_KEEPSUFFIX "quote-line", quoteline, 0 "quote-region", quoteregion, 0 -"read-command", readcommand, 0 +"read-command", readcommand, ZLE_NOTCOMMAND "recursive-edit", recursiveedit, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL "redisplay", redisplay, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL "redo", redo, ZLE_KEEPSUFFIX diff --git a/Src/Zle/zle.h b/Src/Zle/zle.h index 3c652909e..59f459185 100644 --- a/Src/Zle/zle.h +++ b/Src/Zle/zle.h @@ -352,8 +352,7 @@ struct brinfo { #define BEFORECOMPLETEHOOK (zlehooks + 2) #define AFTERCOMPLETEHOOK (zlehooks + 3) #define ACCEPTCOMPHOOK (zlehooks + 4) -#define REVERSEMENUHOOK (zlehooks + 5) -#define INVALIDATELISTHOOK (zlehooks + 6) +#define INVALIDATELISTHOOK (zlehooks + 5) /* complete hook data struct */ @@ -430,8 +429,9 @@ struct region_highlight { * 0: region between point and mark * 1: isearch region * 2: suffix + * 3: pasted text */ -#define N_SPECIAL_HIGHLIGHTS (3) +#define N_SPECIAL_HIGHLIGHTS (4) #ifdef MULTIBYTE_SUPPORT diff --git a/Src/Zle/zle_bindings.c b/Src/Zle/zle_bindings.c index 2ae8c8764..55863db1b 100644 --- a/Src/Zle/zle_bindings.c +++ b/Src/Zle/zle_bindings.c @@ -317,7 +317,7 @@ int vicmdbind[128] = { /* ^X */ z_undefinedkey, /* ^Y */ z_undefinedkey, /* ^Z */ z_undefinedkey, - /* ^[ */ z_undefinedkey, + /* ^[ */ z_beep, /* ^\ */ z_undefinedkey, /* ^] */ z_undefinedkey, /* ^^ */ z_undefinedkey, diff --git a/Src/Zle/zle_hist.c b/Src/Zle/zle_hist.c index cc66f99ae..c61b4ef0e 100644 --- a/Src/Zle/zle_hist.c +++ b/Src/Zle/zle_hist.c @@ -894,10 +894,8 @@ zgetline(UNUSED(char **args)) free(s); free(lineadd); clearlist = 1; - if (stackhist != -1) { - histline = stackhist; - stackhist = -1; - } + /* not restoring stackhist as we're inserting into current line */ + stackhist = -1; } return 0; } @@ -1598,7 +1596,7 @@ doisearch(char **args, int dir, int pattern) dir = odir; skip_pos = 1; rpt: - if (!sbptr && previous_search_len) { + if (!sbptr && previous_search_len && dir == odir) { if (previous_search_len > sibuf - FIRST_SEARCH_CHAR - 2) { ibuf = hrealloc((char *)ibuf, sibuf, (sibuf + previous_search_len)); @@ -1620,6 +1618,21 @@ doisearch(char **args, int dir, int pattern) feep = 1; else goto ins; + } else if (cmd == Th(z_bracketedpaste)) { + char *paste = bracketedstring(); + set_isrch_spot(top_spot++, hl, pos, pat_hl, pat_pos, end_pos, + zlemetacs, sbptr, dir, nomatch); + size_t pastelen = strlen(paste); + if (sbptr + pastelen >= sibuf - FIRST_SEARCH_CHAR - 2) { + int oldsize = sibuf; + sibuf += (pastelen >= sibuf) ? pastelen + 1 : sibuf; + ibuf = hrealloc(ibuf, oldsize, sibuf); + sbuf = ibuf + FIRST_SEARCH_CHAR; + } + strcpy(sbuf + sbptr, paste); + sbptr += pastelen; + patprog = NULL; + free(paste); } else if (cmd == Th(z_acceptsearch)) { break; } else { diff --git a/Src/Zle/zle_keymap.c b/Src/Zle/zle_keymap.c index c6fae251d..5b4189faa 100644 --- a/Src/Zle/zle_keymap.c +++ b/Src/Zle/zle_keymap.c @@ -540,7 +540,7 @@ reselectkeymap(void) /**/ mod_export int -bindkey(Keymap km, char *seq, Thingy bind, char *str) +bindkey(Keymap km, const char *seq, Thingy bind, char *str) { Key k; int f = seq[0] == Meta ? STOUC(seq[1])^32 : STOUC(seq[0]); @@ -1363,6 +1363,7 @@ default_bindings(void) } /* escape in operator pending cancels the operation */ bindkey(oppmap, "\33", refthingy(t_vicmdmode), NULL); + bindkey(vismap, "\33", refthingy(t_deactivateregion), NULL); bindkey(vismap, "o", refthingy(t_exchangepointandmark), NULL); bindkey(vismap, "p", refthingy(t_putreplaceselection), NULL); bindkey(vismap, "x", refthingy(t_videlete), NULL); @@ -1400,6 +1401,11 @@ default_bindings(void) bindkey(emap, "\30\30", refthingy(t_exchangepointandmark), NULL); bindkey(emap, "\30=", refthingy(t_whatcursorposition), NULL); + /* bracketed paste applicable to all keymaps */ + bindkey(emap, "\33[200~", refthingy(t_bracketedpaste), NULL); + bindkey(vmap, "\33[200~", refthingy(t_bracketedpaste), NULL); + bindkey(amap, "\33[200~", refthingy(t_bracketedpaste), NULL); + /* emacs mode: ESC sequences, all taken from the meta binding table */ buf[0] = '\33'; buf[2] = 0; diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index cec44c0ed..e610ae1f3 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -1119,7 +1119,7 @@ zlecore(void) char * zleread(char **lp, char **rp, int flags, int context, char *init, char *finish) { - char *s; + char *s, **bracket; int old_errno = errno; int tmout = getiparam("TMOUT"); @@ -1206,6 +1206,7 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish) histline = stackhist; stackhist = -1; } + handleundo(); } /* * If main is linked to the viins keymap, we need to register @@ -1248,6 +1249,9 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish) zlecallhook(init, NULL); + if ((bracket = getaparam("zle_bracketed_paste")) && arrlen(bracket) == 2) + fputs(*bracket, shout); + zrefresh(); zlecore(); @@ -1257,6 +1261,9 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish) "ZLE_VARED_ABORTED" : "ZLE_LINE_ABORTED", zlegetline(NULL, NULL)); + if ((bracket = getaparam("zle_bracketed_paste")) && arrlen(bracket) == 2) + fputs(bracket[1], shout); + if (done && !exit_pending && !errflag) zlecallhook(finish, NULL); @@ -1858,7 +1865,7 @@ trashzle(void) clearflag = listshown = 0; } if (postedit) - fprintf(shout, "%s", postedit); + fprintf(shout, "%s", unmeta(postedit)); fflush(shout); resetneeded = 1; if (!(zlereadflags & ZLRF_NOSETTY)) @@ -1986,8 +1993,6 @@ mod_export struct hookdef zlehooks[] = { HOOKDEF("after_complete", NULL, 0), /* ACCEPTCOMPHOOK */ HOOKDEF("accept_completion", NULL, 0), - /* REVERSEMENUHOOK */ - HOOKDEF("reverse_menu", NULL, 0), /* INVALIDATELISTHOOK */ HOOKDEF("invalidate_list", NULL, 0), }; @@ -2004,6 +2009,8 @@ static struct features module_features = { int setup_(UNUSED(Module m)) { + char **bpaste; + /* Set up editor entry points */ zle_entry_ptr = zle_main_entry; zle_load_state = 1; @@ -2028,6 +2035,11 @@ setup_(UNUSED(Module m)) clwords = (char **) zshcalloc((clwsize = 16) * sizeof(char *)); + bpaste = zshcalloc(3*sizeof(char *)); + bpaste[0] = ztrdup("\033[?2004h"); + bpaste[1] = ztrdup("\033[?2004l"); + setaparam("zle_bracketed_paste", bpaste); + return 0; } diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c index 4669ef2ad..2d1862813 100644 --- a/Src/Zle/zle_misc.c +++ b/Src/Zle/zle_misc.c @@ -517,10 +517,12 @@ copyregionaskill(char **args) /* * kct: index into kill ring, or -1 for original cutbuffer of yank. - * yankb, yanke: mark the start and end of last yank in editing buffer. * yankcs marks the cursor position preceding the last yank */ -static int kct, yankb, yanke, yankcs; +static int kct, yankcs; + +/**/ +int yankb, yanke; /* mark the start and end of last yank in editing buffer. */ /* The original cutbuffer, either cutbuf or one of the vi buffers. */ static Cutbuffer kctbuf; @@ -736,6 +738,71 @@ yankpop(UNUSED(char **args)) } /**/ +mod_export char * +bracketedstring(void) +{ + static const char endesc[] = "\033[201~"; + int endpos = 0; + size_t psize = 64; + char *pbuf = zalloc(psize); + size_t current = 0; + int next, timeout; + + while (endesc[endpos]) { + if (current + 1 >= psize) + pbuf = zrealloc(pbuf, psize *= 2); + if ((next = getbyte(1L, &timeout)) == EOF) + break; + if (!endpos || next != endesc[endpos++]) + endpos = (next == *endesc); + if (imeta(next)) { + pbuf[current++] = Meta; + pbuf[current++] = next ^ 32; + } else if (next == '\r') + pbuf[current++] = '\n'; + else + pbuf[current++] = next; + } + pbuf[current-endpos] = '\0'; + return pbuf; +} + +/**/ +int +bracketedpaste(char **args) +{ + char *pbuf = bracketedstring(); + + if (*args) { + setsparam(*args, pbuf); + } else { + int n; + ZLE_STRING_T wpaste; + wpaste = stringaszleline((zmult == 1) ? pbuf : + quotestring(pbuf, NULL, QT_SINGLE_OPTIONAL), 0, &n, NULL, NULL); + cuttext(wpaste, n, CUT_REPLACE); + if (!(zmod.flags & MOD_VIBUF)) { + kct = -1; + kctbuf = &cutbuf; + zmult = 1; + if (region_active) + killregion(zlenoargs); + /* Chop a final newline if its insertion would be hard to + * distinguish by the user from the line being accepted. */ + else if (n > 1 && zlecontext != ZLCON_VARED && + (zlecs + (insmode ? 0 : n - 1)) >= zlell && + wpaste[n-1] == ZWC('\n')) + n--; + yankcs = yankb = zlecs; + doinsert(wpaste, n); + yanke = zlecs; + } + free(pbuf); free(wpaste); + } + return 0; +} + +/**/ int overwritemode(UNUSED(char **args)) { @@ -1264,6 +1331,22 @@ executenamedcommand(char *prmt) if (listed) clearlist = listshown = 1; curlist = 0; + } else if (cmd == Th(z_bracketedpaste)) { + char *insert = bracketedstring(); + size_t inslen = strlen(insert); + if (len + inslen > NAMLEN) + feep = 1; + else { + strcpy(ptr, insert); + len += inslen; + ptr += inslen; + if (listed) { + clearlist = listshown = 1; + listed = 0; + } else + curlist = 0; + } + free(insert); } else { if(cmd == Th(z_acceptline) || cmd == Th(z_vicmdmode)) { Thingy r; @@ -1484,13 +1567,13 @@ makesuffix(int n) { char *suffixchars; - if (!(suffixchars = getsparam("ZLE_REMOVE_SUFFIX_CHARS"))) + if (!(suffixchars = getsparam_u("ZLE_REMOVE_SUFFIX_CHARS"))) suffixchars = " \t\n;&|"; addsuffixstring(SUFTYP_POSSTR, 0, suffixchars, n); /* Do this second so it takes precedence */ - if ((suffixchars = getsparam("ZLE_SPACE_SUFFIX_CHARS")) && *suffixchars) + if ((suffixchars = getsparam_u("ZLE_SPACE_SUFFIX_CHARS")) && *suffixchars) addsuffixstring(SUFTYP_POSSTR, SUFFLAGS_SPACE, suffixchars, n); suffixlen = n; diff --git a/Src/Zle/zle_move.c b/Src/Zle/zle_move.c index d751c4333..f49df8647 100644 --- a/Src/Zle/zle_move.c +++ b/Src/Zle/zle_move.c @@ -555,6 +555,13 @@ visuallinemode(UNUSED(char **args)) return 0; } +/**/ +int +deactivateregion(UNUSED(char **args)) +{ + region_active = 0; + return 0; +} /**/ int @@ -876,24 +883,36 @@ int vigotomark(UNUSED(char **args)) { ZLE_INT_T ch; + int *markcs, *markhist = 0; int oldcs = zlecs; int oldline = histline; + int tmpcs, tmphist; ch = getfullchar(0); - if (ch == ZWC('\'') || ch == ZWC('`')) - ch = 26; - else { - if (ch < ZWC('a') || ch > ZWC('z')) - return 1; - ch -= ZWC('a'); - } - if (!vimarkline[ch]) - return 1; - if (curhist != vimarkline[ch] && !zle_goto_hist(vimarkline[ch], 0, 0)) { - vimarkline[ch] = 0; + if (ch == ZWC('\'') || ch == ZWC('`')) { + markhist = vimarkline + 26; + markcs = vimarkcs + 26; + } else if (ch == ZWC('.') && curchange->prev) { + /* position cursor where it was after the last change. not exactly + * what vim does but close enough */ + tmpcs = curchange->prev->new_cs; + tmphist = curchange->prev->hist; + markcs = &tmpcs; + markhist = &tmphist; + } else if (ch >= ZWC('a') && ch <= ZWC('z')) { + markhist = vimarkline + (ch - ZWC('a')); + markcs = vimarkcs + (ch - ZWC('a')); + } else return 1; + if (markhist) { + if (!*markhist) + return 1; + if (histline != *markhist && !zle_goto_hist(*markhist, 0, 0)) { + *markhist = 0; + return 1; + } } - zlecs = vimarkcs[ch]; + zlecs = *markcs; vimarkcs[26] = oldcs; vimarkline[26] = oldline; if (zlecs > zlell) diff --git a/Src/Zle/zle_params.c b/Src/Zle/zle_params.c index ce4b0724d..b84e72088 100644 --- a/Src/Zle/zle_params.c +++ b/Src/Zle/zle_params.c @@ -95,6 +95,8 @@ static const struct gsu_integer region_active_gsu = { get_region_active, set_region_active, zleunsetfn }; static const struct gsu_integer undo_change_no_gsu = { get_undo_current_change, NULL, zleunsetfn }; +static const struct gsu_integer undo_limit_no_gsu = +{ get_undo_limit_change, set_undo_limit_change, zleunsetfn }; static const struct gsu_array killring_gsu = { get_killring, set_killring, unset_killring }; @@ -137,6 +139,7 @@ static struct zleparam { { "region_highlight", PM_ARRAY, GSU(region_highlight_gsu), NULL }, { "UNDO_CHANGE_NO", PM_INTEGER | PM_READONLY, GSU(undo_change_no_gsu), NULL }, + { "UNDO_LIMIT_NO", PM_INTEGER, GSU(undo_limit_no_gsu), NULL }, { "WIDGET", PM_SCALAR | PM_READONLY, GSU(widget_gsu), NULL }, { "WIDGETFUNC", PM_SCALAR | PM_READONLY, GSU(widgetfunc_gsu), NULL }, { "WIDGETSTYLE", PM_SCALAR | PM_READONLY, GSU(widgetstyle_gsu), NULL }, diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c index fe337993f..78046fb7b 100644 --- a/Src/Zle/zle_refresh.c +++ b/Src/Zle/zle_refresh.c @@ -318,6 +318,7 @@ zle_set_highlight(void) int region_atr_on_set = 0; int isearch_atr_on_set = 0; int suffix_atr_on_set = 0; + int paste_atr_on_set = 0; struct region_highlight *rhp; special_atr_on = default_atr_on = 0; @@ -337,7 +338,8 @@ zle_set_highlight(void) for (; *atrs; atrs++) { if (!strcmp(*atrs, "none")) { /* reset attributes for consistency... usually unnecessary */ - special_atr_on = default_atr_on = 0; + special_atr_on = default_atr_on = + paste_atr_on_set = 0; special_atr_on_set = region_atr_on_set = isearch_atr_on_set = suffix_atr_on_set = 1; } else if (strpfx("default:", *atrs)) { @@ -354,6 +356,9 @@ zle_set_highlight(void) } else if (strpfx("suffix:", *atrs)) { match_highlight(*atrs + 7, &(region_highlights[2].atr)); suffix_atr_on_set = 1; + } else if (strpfx("paste:", *atrs)) { + match_highlight(*atrs + 6, &(region_highlights[3].atr)); + paste_atr_on_set = 1; } } } @@ -367,6 +372,7 @@ zle_set_highlight(void) region_highlights[1].atr = TXTUNDERLINE; if (!suffix_atr_on_set) region_highlights[2].atr = TXTBOLDFACE; + /* paste defaults to 0 */ allocate_colour_buffer(); } @@ -1073,6 +1079,13 @@ zrefresh(void) region_highlights[2].start = region_highlights[2].end = -1; } + if (lastcmd & ZLE_YANK) { + region_highlights[3].start = yankb; + region_highlights[3].end = yanke; + } else { + region_highlights[3].start = region_highlights[3].end = -1; + } + if (clearlist && listshown > 0) { if (tccan(TCCLEAREOD)) { int ovln = vln, ovcs = vcs; diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c index f18ad170e..b87b99b00 100644 --- a/Src/Zle/zle_tricky.c +++ b/Src/Zle/zle_tricky.c @@ -345,17 +345,8 @@ mod_export int reversemenucomplete(char **args) { wouldinstab = 0; - if (!menucmp) { - menucomplete(args); - /* - * Drop through, since we are now on the first item instead of - * the last. We've already updated the display, so this is a - * bit inefficient, but it's simple and it works. - */ - } - - runhookdef(REVERSEMENUHOOK, NULL); - return 0; + zmult = -zmult; + return menucomplete(args); } /**/ @@ -730,11 +721,12 @@ docomplete(int lst) } } } - if (lst == COMP_EXPAND_COMPLETE) + if (lst == COMP_EXPAND_COMPLETE) { do { /* Check if there is a parameter expression. */ for (; *q && *q != String; q++); - if (*q == String && q[1] != Inpar && q[1] != Inbrack) { + if (*q == String && q[1] != Inpar && q[1] != Inparmath && + q[1] != Inbrack) { if (*++q == Inbrace) { if (! skipparens(Inbrace, Outbrace, &q) && q == s + zlemetacs - wb) @@ -778,6 +770,7 @@ docomplete(int lst) } else break; } while (q < s + zlemetacs - wb); + } if (lst == COMP_EXPAND_COMPLETE) { /* If it is still not clear if we should use expansion or * * completion and there is a `$' or a backtick in the word, * @@ -1182,14 +1175,30 @@ get_comp_string(void) do { qsub = noword = 0; - lincmd = ((incmdpos && !ins && !incond) || - (oins == 2 && wordpos == 2) || - (ins == 3 && wordpos == 1)); + /* + * pws: added cmdtok == NULLTOK test as fallback for detecting + * we haven't had a command yet. This is a cop out: it's needed + * after SEPER because of bizarre and incomprehensible dance + * that we otherwise do involving the "ins" flag when you might + * have thought we'd just reset everything because we're now + * considering a new command. Consequently, although this looks + * relatively harmless by itself, it's probably incomplete. + */ + lincmd = (incmdpos && !ins && !incond) || + (oins == 2 && wordpos == 2) || + (ins == 3 && wordpos == 1) || + (cmdtok == NULLTOK && !incond); linredir = (inredir && !ins); oins = ins; /* Get the next token. */ if (linarr) incmdpos = 0; + /* + * Arrange to parse assignments after typeset etc... + * but not if we're already in an array. + */ + if (cmdtok == TYPESET) + intypeset = !linarr; ctxtlex(); if (tok == LEXERR) { @@ -1272,10 +1281,11 @@ get_comp_string(void) tt0 = NULLTOK; } if (lincmd && (tok == STRING || tok == FOR || tok == FOREACH || - tok == SELECT || tok == REPEAT || tok == CASE)) { + tok == SELECT || tok == REPEAT || tok == CASE || + tok == TYPESET)) { /* The lexer says, this token is in command position, so * * store the token string (to find the right compctl). */ - ins = (tok == REPEAT ? 2 : (tok != STRING)); + ins = (tok == REPEAT ? 2 : (tok != STRING && tok != TYPESET)); zsfree(cmdstr); cmdstr = ztrdup(tokstr); cmdtok = tok; @@ -1290,7 +1300,7 @@ get_comp_string(void) * handle completing multiple SEPER-ated command positions on * the same command line, e.g., pipelines. */ - ins = (cmdtok != STRING); + ins = (cmdtok != STRING && cmdtok != TYPESET); } if (!lexflags && tt0 == NULLTOK) { /* This is done when the lexer reached the word the cursor is on. */ @@ -1436,7 +1446,7 @@ get_comp_string(void) we = wb = zlemetacs; clwpos = clwnum; t0 = STRING; - } else if (t0 == STRING) { + } else if (t0 == STRING || t0 == TYPESET) { /* We found a simple string. */ s = ztrdup(clwords[clwpos]); } else if (t0 == ENVSTRING) { @@ -1492,7 +1502,7 @@ get_comp_string(void) zlemetaline = tmp; zlemetall = strlen(zlemetaline); } - if (t0 != STRING && inwhat != IN_MATH) { + if (t0 != STRING && t0 != TYPESET && inwhat != IN_MATH) { if (tmp) { tmp = NULL; linptr = zlemetaline; diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c index e4ab97a54..d1d320613 100644 --- a/Src/Zle/zle_utils.c +++ b/Src/Zle/zle_utils.c @@ -1288,7 +1288,7 @@ showmsg(char const *msg) p = unmetafy(umsg, &ulen); memset(&mbs, 0, sizeof mbs); - mb_metacharinit(); + mb_charinit(); while (ulen > 0) { char const *n; if (*p == '\n') { @@ -1405,9 +1405,9 @@ static struct change *nextchanges, *endnextchanges; /**/ zlong undo_changeno; -/* If non-zero, the last increment to undo_changeno was for the variable */ +/* If positive, don't undo beyond this point */ -static int undo_set_by_variable; +zlong undo_limitno; /**/ void @@ -1418,8 +1418,7 @@ initundo(void) curchange->prev = curchange->next = NULL; curchange->del = curchange->ins = NULL; curchange->dell = curchange->insl = 0; - curchange->changeno = undo_changeno = 0; - undo_set_by_variable = 0; + curchange->changeno = undo_changeno = undo_limitno = 0; lastline = zalloc((lastlinesz = linesz) * ZLE_CHAR_SIZE); ZS_memcpy(lastline, zleline, (lastll = zlell)); lastcs = zlecs; @@ -1545,7 +1544,6 @@ mkundoent(void) ch->prev = NULL; } ch->changeno = ++undo_changeno; - undo_set_by_variable = 0; endnextchanges = ch; } @@ -1580,12 +1578,13 @@ undo(char **args) struct change *prev = curchange->prev; if(!prev) return 1; - if (prev->changeno < last_change) - break; - if (unapplychange(prev)) - curchange = prev; - else + if (prev->changeno <= last_change) break; + if (prev->changeno <= undo_limitno && !*args) + return 1; + if (!unapplychange(prev) && last_change >= 0) + unapplychange(prev); + curchange = prev; } while (last_change >= (zlong)0 || (curchange->flags & CH_PREV)); setlastline(); return 0; @@ -1735,16 +1734,22 @@ zlecallhook(char *name, char *arg) zlong get_undo_current_change(UNUSED(Param pm)) { - if (undo_set_by_variable) { - /* We were the last to increment this, doesn't need another one. */ - return undo_changeno; - } - undo_set_by_variable = 1; - /* - * Increment the number in case a change is in progress; - * we don't want to back off what's already been done when - * we return to this change number. This eliminates any - * problem about the point where a change is numbered. - */ - return ++undo_changeno; + /* add entry for any pending changes */ + mkundoent(); + setlastline(); + return undo_changeno; +} + +/**/ +zlong +get_undo_limit_change(UNUSED(Param pm)) +{ + return undo_limitno; +} + +/**/ +void +set_undo_limit_change(UNUSED(Param pm), zlong value) +{ + undo_limitno = value; } |