summaryrefslogtreecommitdiff
path: root/Src/Zle
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Zle')
-rw-r--r--Src/Zle/compcore.c10
-rw-r--r--Src/Zle/compctl.c2
-rw-r--r--Src/Zle/complete.c16
-rw-r--r--Src/Zle/complist.c97
-rw-r--r--Src/Zle/compresult.c83
-rw-r--r--Src/Zle/computil.c2
-rw-r--r--Src/Zle/iwidgets.list4
-rw-r--r--Src/Zle/zle.h6
-rw-r--r--Src/Zle/zle_bindings.c2
-rw-r--r--Src/Zle/zle_hist.c23
-rw-r--r--Src/Zle/zle_keymap.c8
-rw-r--r--Src/Zle/zle_main.c20
-rw-r--r--Src/Zle/zle_misc.c91
-rw-r--r--Src/Zle/zle_move.c43
-rw-r--r--Src/Zle/zle_params.c3
-rw-r--r--Src/Zle/zle_refresh.c15
-rw-r--r--Src/Zle/zle_tricky.c52
-rw-r--r--Src/Zle/zle_utils.c51
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;
}