mirror of
git://git.code.sf.net/p/zsh/code
synced 2024-11-20 05:53:52 +01:00
1140 lines
21 KiB
C
1140 lines
21 KiB
C
/*
|
|
* zle_hist.c - history editing
|
|
*
|
|
* This file is part of zsh, the Z shell.
|
|
*
|
|
* Copyright (c) 1992-1997 Paul Falstad
|
|
* All rights reserved.
|
|
*
|
|
* Permission is hereby granted, without written agreement and without
|
|
* license or royalty fees, to use, copy, modify, and distribute this
|
|
* software and to distribute modified versions of this software for any
|
|
* purpose, provided that the above copyright notice and the following
|
|
* two paragraphs appear in all copies of this software.
|
|
*
|
|
* In no event shall Paul Falstad or the Zsh Development Group be liable
|
|
* to any party for direct, indirect, special, incidental, or consequential
|
|
* damages arising out of the use of this software and its documentation,
|
|
* even if Paul Falstad and the Zsh Development Group have been advised of
|
|
* the possibility of such damage.
|
|
*
|
|
* Paul Falstad and the Zsh Development Group specifically disclaim any
|
|
* warranties, including, but not limited to, the implied warranties of
|
|
* merchantability and fitness for a particular purpose. The software
|
|
* provided hereunder is on an "as is" basis, and Paul Falstad and the
|
|
* Zsh Development Group have no obligation to provide maintenance,
|
|
* support, updates, enhancements, or modifications.
|
|
*
|
|
*/
|
|
|
|
#include "zle.mdh"
|
|
#include "zle_hist.pro"
|
|
|
|
/* Are references to earlier history lines permitted? == 0 if *
|
|
* editing or reading a standalone line, such as in vared or select. */
|
|
|
|
/**/
|
|
int histallowed;
|
|
|
|
/* Column position of vi ideal cursor. -1 if it is unknown -- most *
|
|
* movements and changes do this. */
|
|
|
|
/**/
|
|
int lastcol;
|
|
|
|
/* current history line number */
|
|
|
|
/**/
|
|
int histline;
|
|
|
|
/* the last line in the history (the current one), metafied */
|
|
|
|
/**/
|
|
char *curhistline;
|
|
|
|
/**/
|
|
void
|
|
remember_edits(void)
|
|
{
|
|
if (histline == curhist) {
|
|
zsfree(curhistline);
|
|
curhistline = metafy((char *) line, ll, META_DUP);
|
|
}
|
|
else {
|
|
Histent ent = gethistent(histline);
|
|
|
|
if (metadiffer(ent->zle_text ? ent->zle_text : ent->text,
|
|
(char *) line, ll)) {
|
|
zsfree(ent->zle_text);
|
|
ent->zle_text = metafy((char *) line, ll, META_DUP);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**/
|
|
void
|
|
forget_edits(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < histentct; i++) {
|
|
zsfree(histentarr[i].zle_text);
|
|
histentarr[i].zle_text = NULL;
|
|
}
|
|
}
|
|
|
|
/**/
|
|
void
|
|
uphistory(void)
|
|
{
|
|
if (zmult < 0) {
|
|
zmult = -zmult;
|
|
downhistory();
|
|
zmult = -zmult;
|
|
} else if(!zle_goto_hist(histline - zmult) && isset(HISTBEEP))
|
|
feep();
|
|
}
|
|
|
|
/**/
|
|
int
|
|
upline(void)
|
|
{
|
|
int n = zmult;
|
|
|
|
if (n < 0) {
|
|
zmult = -zmult;
|
|
n = downline();
|
|
zmult = -zmult;
|
|
return n;
|
|
}
|
|
if (lastcol == -1)
|
|
lastcol = cs - findbol();
|
|
cs = findbol();
|
|
while (n) {
|
|
if (!cs)
|
|
break;
|
|
cs--;
|
|
cs = findbol();
|
|
n--;
|
|
}
|
|
if (!n) {
|
|
int x = findeol();
|
|
|
|
if ((cs += lastcol) >= x) {
|
|
cs = x;
|
|
if (cs > findbol() && invicmdmode())
|
|
cs--;
|
|
}
|
|
}
|
|
return n;
|
|
}
|
|
|
|
/**/
|
|
void
|
|
uplineorhistory(void)
|
|
{
|
|
int ocs = cs;
|
|
int n = upline();
|
|
if (n) {
|
|
int m = zmult;
|
|
|
|
cs = ocs;
|
|
if (virangeflag || !histallowed) {
|
|
feep();
|
|
return;
|
|
}
|
|
zmult = n;
|
|
uphistory();
|
|
zmult = m;
|
|
}
|
|
}
|
|
|
|
/**/
|
|
void
|
|
viuplineorhistory(void)
|
|
{
|
|
int col = lastcol;
|
|
uplineorhistory();
|
|
lastcol = col;
|
|
vifirstnonblank();
|
|
}
|
|
|
|
|
|
/**/
|
|
void
|
|
uplineorsearch(void)
|
|
{
|
|
int ocs = cs;
|
|
int n = upline();
|
|
if (n) {
|
|
int m = zmult;
|
|
|
|
cs = ocs;
|
|
if (virangeflag || !histallowed) {
|
|
feep();
|
|
return;
|
|
}
|
|
zmult = n;
|
|
historysearchbackward();
|
|
zmult = m;
|
|
}
|
|
}
|
|
|
|
/**/
|
|
int
|
|
downline(void)
|
|
{
|
|
int n = zmult;
|
|
|
|
if (n < 0) {
|
|
zmult = -zmult;
|
|
n = upline();
|
|
zmult = -zmult;
|
|
return n;
|
|
}
|
|
if (lastcol == -1)
|
|
lastcol = cs - findbol();
|
|
while (n) {
|
|
int x = findeol();
|
|
|
|
if (x == ll)
|
|
break;
|
|
cs = x + 1;
|
|
n--;
|
|
}
|
|
if (!n) {
|
|
int x = findeol();
|
|
|
|
if ((cs += lastcol) >= x) {
|
|
cs = x;
|
|
if (cs > findbol() && invicmdmode())
|
|
cs--;
|
|
}
|
|
}
|
|
return n;
|
|
}
|
|
|
|
/**/
|
|
void
|
|
downlineorhistory(void)
|
|
{
|
|
int ocs = cs;
|
|
int n = downline();
|
|
if (n) {
|
|
int m = zmult;
|
|
|
|
cs = ocs;
|
|
if (virangeflag || !histallowed) {
|
|
feep();
|
|
return;
|
|
}
|
|
zmult = n;
|
|
downhistory();
|
|
zmult = m;
|
|
}
|
|
}
|
|
|
|
/**/
|
|
void
|
|
vidownlineorhistory(void)
|
|
{
|
|
int col = lastcol;
|
|
downlineorhistory();
|
|
lastcol = col;
|
|
vifirstnonblank();
|
|
}
|
|
|
|
/**/
|
|
void
|
|
downlineorsearch(void)
|
|
{
|
|
int ocs = cs;
|
|
int n = downline();
|
|
if (n) {
|
|
int m = zmult;
|
|
|
|
cs = ocs;
|
|
if (virangeflag || !histallowed) {
|
|
feep();
|
|
return;
|
|
}
|
|
zmult = n;
|
|
historysearchforward();
|
|
zmult = m;
|
|
}
|
|
}
|
|
|
|
/**/
|
|
void
|
|
acceptlineanddownhistory(void)
|
|
{
|
|
char *s;
|
|
|
|
if (!(s = zle_get_event(histline + 1))) {
|
|
feep();
|
|
return;
|
|
}
|
|
pushnode(bufstack, ztrdup(s));
|
|
done = 1;
|
|
stackhist = histline + 1;
|
|
}
|
|
|
|
/**/
|
|
void
|
|
downhistory(void)
|
|
{
|
|
if (zmult < 0) {
|
|
zmult = -zmult;
|
|
uphistory();
|
|
zmult = -zmult;
|
|
} else if(!zle_goto_hist(histline + zmult) && isset(HISTBEEP))
|
|
feep();
|
|
}
|
|
|
|
/**/
|
|
void
|
|
historysearchbackward(void)
|
|
{
|
|
int histpos, histmpos, hl = histline;
|
|
int n = zmult;
|
|
char *s;
|
|
|
|
if (!n)
|
|
return;
|
|
if (n < 0) {
|
|
zmult = -n;
|
|
historysearchforward();
|
|
zmult = n;
|
|
return;
|
|
}
|
|
for (histpos = histmpos = 0; histpos < ll && !iblank(line[histpos]);
|
|
histpos++, histmpos++)
|
|
if(imeta(line[histpos]))
|
|
histmpos++;
|
|
for (;;) {
|
|
hl--;
|
|
if (!(s = zle_get_event(hl))) {
|
|
feep();
|
|
return;
|
|
}
|
|
if (metadiffer(s, (char *) line, histpos) < 0 &&
|
|
iblank(s[histmpos] == Meta ? s[histmpos+1]^32 : s[histmpos]) &&
|
|
metadiffer(s, (char *) line, ll) && !--n)
|
|
break;
|
|
}
|
|
zle_goto_hist(hl);
|
|
}
|
|
|
|
/**/
|
|
void
|
|
historysearchforward(void)
|
|
{
|
|
int histpos, histmpos, hl = histline;
|
|
int n = zmult;
|
|
char *s;
|
|
|
|
if (!n)
|
|
return;
|
|
if (n < 0) {
|
|
zmult = -n;
|
|
historysearchbackward();
|
|
zmult = n;
|
|
return;
|
|
}
|
|
for (histpos = histmpos = 0; histpos < ll && !iblank(line[histpos]);
|
|
histpos++, histmpos++)
|
|
if(imeta(line[histpos]))
|
|
histmpos++;
|
|
for (;;) {
|
|
hl++;
|
|
if (!(s = zle_get_event(hl))) {
|
|
feep();
|
|
return;
|
|
}
|
|
if (metadiffer(s, (char *) line, histpos) < (histline == curhist) &&
|
|
(!s[histmpos] ||
|
|
iblank(s[histmpos] == Meta ? s[histmpos+1]^32 : s[histmpos])) &&
|
|
metadiffer(s, (char *) line, ll) && !--n)
|
|
break;
|
|
}
|
|
zle_goto_hist(hl);
|
|
}
|
|
|
|
/**/
|
|
void
|
|
beginningofbufferorhistory(void)
|
|
{
|
|
if (findbol())
|
|
cs = 0;
|
|
else
|
|
beginningofhistory();
|
|
}
|
|
|
|
/**/
|
|
void
|
|
beginningofhistory(void)
|
|
{
|
|
if (!zle_goto_hist(firsthist()) && isset(HISTBEEP))
|
|
feep();
|
|
}
|
|
|
|
/**/
|
|
void
|
|
endofbufferorhistory(void)
|
|
{
|
|
if (findeol() != ll)
|
|
cs = ll;
|
|
else
|
|
endofhistory();
|
|
}
|
|
|
|
/**/
|
|
void
|
|
endofhistory(void)
|
|
{
|
|
zle_goto_hist(curhist);
|
|
}
|
|
|
|
/**/
|
|
void
|
|
insertlastword(void)
|
|
{
|
|
int n;
|
|
char *s, *t;
|
|
Histent he;
|
|
|
|
/* multiple calls will now search back through the history, pem */
|
|
static char *lastinsert;
|
|
static int lasthist, lastpos;
|
|
int evhist = curhist - 1, save;
|
|
|
|
if (lastinsert) {
|
|
int lastlen = ztrlen(lastinsert);
|
|
int pos = cs;
|
|
|
|
if (lastpos <= pos &&
|
|
lastlen == pos - lastpos &&
|
|
memcmp(lastinsert, (char *)&line[lastpos], lastlen) == 0) {
|
|
evhist = --lasthist;
|
|
cs = lastpos;
|
|
foredel(pos - cs);
|
|
}
|
|
zsfree(lastinsert);
|
|
lastinsert = NULL;
|
|
}
|
|
if (!(he = quietgethist(evhist)) || !he->nwords) {
|
|
feep();
|
|
return;
|
|
}
|
|
if (zmult > 0) {
|
|
n = he->nwords - (zmult - 1);
|
|
} else {
|
|
n = 1 - zmult;
|
|
}
|
|
if (n < 1 || n > he->nwords) {
|
|
feep();
|
|
return;
|
|
}
|
|
s = he->text + he->words[2*n-2];
|
|
t = he->text + he->words[2*n-1];
|
|
save = *t;
|
|
*t = '\0'; /* ignore trailing whitespace */
|
|
|
|
lasthist = evhist;
|
|
lastpos = cs;
|
|
lastinsert = ztrdup(s);
|
|
n = zmult;
|
|
zmult = 1;
|
|
doinsert(s);
|
|
zmult = n;
|
|
*t = save;
|
|
}
|
|
|
|
/**/
|
|
char *
|
|
qgetevent(int ev)
|
|
{
|
|
return ((ev == curhist) ? curhistline : quietgetevent(ev));
|
|
}
|
|
|
|
/**/
|
|
char *
|
|
zle_get_event(int ev)
|
|
{
|
|
Histent ent;
|
|
|
|
if (ev == curhist)
|
|
return curhistline;
|
|
if (! (ent = quietgethist(ev)))
|
|
return NULL;
|
|
if (ent->zle_text)
|
|
return ent->zle_text;
|
|
return ent->text;
|
|
}
|
|
|
|
/**/
|
|
static int
|
|
zle_goto_hist(int ev)
|
|
{
|
|
char *t;
|
|
|
|
remember_edits();
|
|
if(!(t = zle_get_event(ev)))
|
|
return 0;
|
|
mkundoent();
|
|
histline = ev;
|
|
setline(t);
|
|
setlastline();
|
|
return 1;
|
|
}
|
|
|
|
/**/
|
|
void
|
|
pushline(void)
|
|
{
|
|
int n = zmult;
|
|
|
|
if (n < 0)
|
|
return;
|
|
pushnode(bufstack, metafy((char *) line, ll, META_DUP));
|
|
while (--n)
|
|
pushnode(bufstack, ztrdup(""));
|
|
stackcs = cs;
|
|
*line = '\0';
|
|
ll = cs = 0;
|
|
}
|
|
|
|
/**/
|
|
void
|
|
pushlineoredit(void)
|
|
{
|
|
int ics;
|
|
unsigned char *s;
|
|
char *hline = hgetline();
|
|
|
|
if (zmult < 0)
|
|
return;
|
|
if (hline && *hline) {
|
|
ics = ztrlen(hline);
|
|
sizeline(ics + ll + 1);
|
|
for (s = line + ll; --s >= line; *(s + ics) = *s);
|
|
for (s = line; *hline; hline++)
|
|
*s++ = *hline == Meta ? *++hline ^ 32 : *hline;
|
|
ll += ics;
|
|
cs += ics;
|
|
}
|
|
pushline();
|
|
if (!isfirstln) {
|
|
errflag = done = 1;
|
|
}
|
|
}
|
|
|
|
/**/
|
|
void
|
|
pushinput(void)
|
|
{
|
|
int i;
|
|
|
|
if (zmult < 0)
|
|
return;
|
|
zmult += i = !isfirstln;
|
|
pushlineoredit();
|
|
zmult -= i;
|
|
}
|
|
|
|
/**/
|
|
void
|
|
getline(void)
|
|
{
|
|
char *s = (char *)getlinknode(bufstack);
|
|
|
|
if (!s)
|
|
feep();
|
|
else {
|
|
int cc;
|
|
|
|
unmetafy(s, &cc);
|
|
spaceinline(cc);
|
|
memcpy((char *)line + cs, s, cc);
|
|
cs += cc;
|
|
free(s);
|
|
}
|
|
}
|
|
|
|
/**/
|
|
void
|
|
historyincrementalsearchbackward(void)
|
|
{
|
|
doisearch(-1);
|
|
}
|
|
|
|
/**/
|
|
void
|
|
historyincrementalsearchforward(void)
|
|
{
|
|
doisearch(1);
|
|
}
|
|
|
|
static struct isrch_spot {
|
|
int hl; /* This spot's histline */
|
|
unsigned short pos; /* The search position in our metafied str */
|
|
unsigned short cs; /* The visible search position to the user */
|
|
unsigned short len; /* The search string's length */
|
|
unsigned short flags; /* This spot's flags */
|
|
#define ISS_FAILING 1
|
|
#define ISS_FORWARD 2
|
|
} *isrch_spots;
|
|
|
|
static int max_spot = 0;
|
|
|
|
#ifdef MODULE
|
|
|
|
/**/
|
|
void
|
|
free_isrch_spots(void)
|
|
{
|
|
zfree(isrch_spots, max_spot * sizeof(*isrch_spots));
|
|
}
|
|
|
|
#endif /* MODULE */
|
|
|
|
/**/
|
|
static void
|
|
set_isrch_spot(int num, int hl, int pos, int cs, int len, int dir, int nomatch)
|
|
{
|
|
if (num >= max_spot) {
|
|
if (!isrch_spots) {
|
|
isrch_spots = (struct isrch_spot*)
|
|
zalloc((max_spot = 64) * sizeof *isrch_spots);
|
|
} else {
|
|
isrch_spots = (struct isrch_spot*)realloc((char*)isrch_spots,
|
|
(max_spot += 64) * sizeof *isrch_spots);
|
|
}
|
|
}
|
|
|
|
isrch_spots[num].hl = hl;
|
|
isrch_spots[num].pos = (unsigned short)pos;
|
|
isrch_spots[num].cs = (unsigned short)cs;
|
|
isrch_spots[num].len = (unsigned short)len;
|
|
isrch_spots[num].flags = (dir > 0? ISS_FORWARD : 0)
|
|
+ (nomatch? ISS_FAILING : 0);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
get_isrch_spot(int num, int *hlp, int *posp, int *csp, int *lenp, int *dirp, int *nomatch)
|
|
{
|
|
*hlp = isrch_spots[num].hl;
|
|
*posp = (int)isrch_spots[num].pos;
|
|
*csp = (int)isrch_spots[num].cs;
|
|
*lenp = (int)isrch_spots[num].len;
|
|
*dirp = (isrch_spots[num].flags & ISS_FORWARD)? 1 : -1;
|
|
*nomatch = (isrch_spots[num].flags & ISS_FAILING);
|
|
}
|
|
|
|
#define ISEARCH_PROMPT "failing XXX-i-search: "
|
|
#define NORM_PROMPT_POS 8
|
|
#define FIRST_SEARCH_CHAR (NORM_PROMPT_POS + 14)
|
|
|
|
/**/
|
|
static void
|
|
doisearch(int dir)
|
|
{
|
|
char *s, *ibuf = halloc(80), *sbuf = ibuf + FIRST_SEARCH_CHAR;
|
|
int sbptr = 0, top_spot = 0, pos, sibuf = 80;
|
|
int nomatch = 0, skip_line = 0, skip_pos = 0;
|
|
int odir = dir, sens = zmult == 1 ? 3 : 1;
|
|
int hl = histline;
|
|
Thingy cmd;
|
|
char *okeymap = curkeymapname;
|
|
static char *previous_search = NULL;
|
|
static int previous_search_len = 0;
|
|
|
|
strcpy(ibuf, ISEARCH_PROMPT);
|
|
memcpy(ibuf + NORM_PROMPT_POS, (dir == 1) ? "fwd" : "bck", 3);
|
|
remember_edits();
|
|
s = zle_get_event(hl);
|
|
selectkeymap("main", 1);
|
|
pos = metalen(s, cs);
|
|
for (;;) {
|
|
/* Remember the current values in case search fails (doesn't push). */
|
|
set_isrch_spot(top_spot, hl, pos, cs, sbptr, dir, nomatch);
|
|
if (sbptr == 1 && sbuf[0] == '^') {
|
|
cs = 0;
|
|
nomatch = 0;
|
|
statusline = ibuf + NORM_PROMPT_POS;
|
|
} else if (sbptr > 0) {
|
|
char *last_line = s;
|
|
|
|
for (;;) {
|
|
char *t;
|
|
|
|
if (skip_pos) {
|
|
if (dir < 0) {
|
|
if (pos == 0)
|
|
skip_line = 1;
|
|
else
|
|
pos -= 1 + (pos != 1 && s[pos-2] == Meta);
|
|
} else if (sbuf[0] != '^') {
|
|
if (pos >= strlen(s+1))
|
|
skip_line = 1;
|
|
else
|
|
pos += 1 + (s[pos] == Meta);
|
|
} else
|
|
skip_line = 1;
|
|
skip_pos = 0;
|
|
}
|
|
if (!skip_line && ((sbuf[0] == '^') ?
|
|
(t = metadiffer(s, sbuf + 1, sbptr - 1) < sens ? s : NULL) :
|
|
(t = hstrnstr(s, pos, sbuf, sbptr, dir, sens)))) {
|
|
zle_goto_hist(hl);
|
|
pos = t - s;
|
|
cs = ztrsub(t, s) + (dir == 1? sbptr - (sbuf[0]=='^') : 0);
|
|
nomatch = 0;
|
|
statusline = ibuf + NORM_PROMPT_POS;
|
|
break;
|
|
}
|
|
hl += dir;
|
|
if (!(s = zle_get_event(hl))) {
|
|
if (sbptr == (int)isrch_spots[top_spot-1].len
|
|
&& (isrch_spots[top_spot-1].flags & ISS_FAILING))
|
|
top_spot--;
|
|
get_isrch_spot(top_spot, &hl, &pos, &cs, &sbptr,
|
|
&dir, &nomatch);
|
|
if (!nomatch) {
|
|
feep();
|
|
nomatch = 1;
|
|
}
|
|
s = last_line;
|
|
skip_line = 0;
|
|
statusline = ibuf;
|
|
break;
|
|
}
|
|
pos = dir == 1? 0 : strlen(s);
|
|
skip_line = !strcmp(last_line, s);
|
|
}
|
|
} else {
|
|
top_spot = 0;
|
|
nomatch = 0;
|
|
statusline = ibuf + NORM_PROMPT_POS;
|
|
}
|
|
sbuf[sbptr] = '_';
|
|
statusll = sbuf - statusline + sbptr + 1;
|
|
ref:
|
|
refresh();
|
|
if (!(cmd = getkeycmd()) || cmd == Th(z_sendbreak)) {
|
|
int i;
|
|
get_isrch_spot(0, &hl, &pos, &i, &sbptr, &dir, &nomatch);
|
|
s = zle_get_event(hl);
|
|
zle_goto_hist(hl);
|
|
cs = i;
|
|
break;
|
|
}
|
|
if(cmd == Th(z_clearscreen)) {
|
|
clearscreen();
|
|
goto ref;
|
|
} else if(cmd == Th(z_redisplay)) {
|
|
redisplay();
|
|
goto ref;
|
|
} else if(cmd == Th(z_vicmdmode)) {
|
|
if(selectkeymap(invicmdmode() ? "main" : "vicmd", 0))
|
|
feep();
|
|
goto ref;
|
|
} else if(cmd == Th(z_vibackwarddeletechar) ||
|
|
cmd == Th(z_backwarddeletechar)) {
|
|
if (top_spot)
|
|
get_isrch_spot(--top_spot, &hl, &pos, &cs, &sbptr,
|
|
&dir, &nomatch);
|
|
else
|
|
feep();
|
|
if (nomatch) {
|
|
statusline = ibuf;
|
|
skip_pos = 1;
|
|
}
|
|
s = zle_get_event(hl);
|
|
if (nomatch || !sbptr || (sbptr == 1 && sbuf[0] == '^')) {
|
|
int i = cs;
|
|
zle_goto_hist(hl);
|
|
cs = i;
|
|
}
|
|
memcpy(ibuf + NORM_PROMPT_POS, (dir == 1) ? "fwd" : "bck", 3);
|
|
continue;
|
|
} else if(cmd == Th(z_acceptandhold)) {
|
|
acceptandhold();
|
|
break;
|
|
} else if(cmd == Th(z_acceptandinfernexthistory)) {
|
|
acceptandinfernexthistory();
|
|
break;
|
|
} else if(cmd == Th(z_acceptlineanddownhistory)) {
|
|
acceptlineanddownhistory();
|
|
break;
|
|
} else if(cmd == Th(z_acceptline)) {
|
|
acceptline();
|
|
break;
|
|
} else if(cmd == Th(z_historyincrementalsearchbackward)) {
|
|
set_isrch_spot(top_spot++, hl, pos, cs, sbptr, dir, nomatch);
|
|
if (dir != -1)
|
|
dir = -1;
|
|
else
|
|
skip_pos = 1;
|
|
goto rpt;
|
|
} else if(cmd == Th(z_historyincrementalsearchforward)) {
|
|
set_isrch_spot(top_spot++, hl, pos, cs, sbptr, dir, nomatch);
|
|
if (dir != 1)
|
|
dir = 1;
|
|
else
|
|
skip_pos = 1;
|
|
goto rpt;
|
|
} else if(cmd == Th(z_virevrepeatsearch)) {
|
|
set_isrch_spot(top_spot++, hl, pos, cs, sbptr, dir, nomatch);
|
|
dir = -odir;
|
|
skip_pos = 1;
|
|
goto rpt;
|
|
} else if(cmd == Th(z_virepeatsearch)) {
|
|
set_isrch_spot(top_spot++, hl, pos, cs, sbptr, dir, nomatch);
|
|
dir = odir;
|
|
skip_pos = 1;
|
|
rpt:
|
|
if (!sbptr && previous_search_len) {
|
|
if (previous_search_len > sibuf - FIRST_SEARCH_CHAR - 2) {
|
|
ibuf = hrealloc(ibuf, sibuf, sibuf + previous_search_len);
|
|
sbuf = ibuf + FIRST_SEARCH_CHAR;
|
|
sibuf += previous_search_len;
|
|
}
|
|
memcpy(sbuf, previous_search, sbptr = previous_search_len);
|
|
}
|
|
memcpy(ibuf + NORM_PROMPT_POS, (dir == 1) ? "fwd" : "bck", 3);
|
|
continue;
|
|
} else if(cmd == Th(z_viquotedinsert) ||
|
|
cmd == Th(z_quotedinsert)) {
|
|
if(cmd == Th(z_viquotedinsert)) {
|
|
sbuf[sbptr] = '^';
|
|
refresh();
|
|
}
|
|
if ((c = getkey(0)) == EOF)
|
|
feep();
|
|
else
|
|
goto ins;
|
|
} else {
|
|
if(cmd == Th(z_selfinsertunmeta)) {
|
|
c &= 0x7f;
|
|
if(c == '\r')
|
|
c = '\n';
|
|
} else if (cmd == Th(z_magicspace))
|
|
c = ' ';
|
|
else if (cmd != Th(z_selfinsert)) {
|
|
ungetkeycmd();
|
|
if (cmd == Th(z_sendbreak))
|
|
sbptr = 0;
|
|
break;
|
|
}
|
|
ins:
|
|
if (sbptr == PATH_MAX) {
|
|
feep();
|
|
continue;
|
|
}
|
|
set_isrch_spot(top_spot++, hl, pos, cs, sbptr, dir, nomatch);
|
|
if (sbptr == sibuf - FIRST_SEARCH_CHAR - 2) {
|
|
ibuf = hrealloc(ibuf, sibuf, sibuf * 2);
|
|
sbuf = ibuf + FIRST_SEARCH_CHAR;
|
|
sibuf *= 2;
|
|
}
|
|
sbuf[sbptr++] = c;
|
|
}
|
|
handlefeep();
|
|
}
|
|
if (sbptr) {
|
|
zfree(previous_search, previous_search_len);
|
|
previous_search = zalloc(sbptr);
|
|
memcpy(previous_search, sbuf, previous_search_len = sbptr);
|
|
}
|
|
statusline = NULL;
|
|
selectkeymap(okeymap, 1);
|
|
}
|
|
|
|
/**/
|
|
void
|
|
acceptandinfernexthistory(void)
|
|
{
|
|
int t0;
|
|
char *s;
|
|
|
|
done = 1;
|
|
for (t0 = histline - 2;; t0--) {
|
|
if (!(s = qgetevent(t0)))
|
|
return;
|
|
if (!metadiffer(s, (char *) line, ll))
|
|
break;
|
|
}
|
|
if (!(s = qgetevent(t0 + 1)))
|
|
return;
|
|
pushnode(bufstack, ztrdup(s));
|
|
stackhist = t0 + 1;
|
|
}
|
|
|
|
/**/
|
|
void
|
|
infernexthistory(void)
|
|
{
|
|
int t0;
|
|
char *s;
|
|
|
|
for (t0 = histline - 2;; t0--) {
|
|
if (!(s = qgetevent(t0))) {
|
|
feep();
|
|
return;
|
|
}
|
|
if (! metadiffer(s, (char *) line, ll))
|
|
break;
|
|
}
|
|
if (!(s = qgetevent(t0 + 1))) {
|
|
feep();
|
|
return;
|
|
}
|
|
zle_goto_hist(t0 + 1);
|
|
}
|
|
|
|
/**/
|
|
void
|
|
vifetchhistory(void)
|
|
{
|
|
if (zmult < 0)
|
|
return;
|
|
if (histline == curhist) {
|
|
if (!(zmod.flags & MOD_MULT)) {
|
|
cs = ll;
|
|
cs = findbol();
|
|
return;
|
|
}
|
|
}
|
|
if (!zle_goto_hist((zmod.flags & MOD_MULT) ? zmult : curhist) &&
|
|
isset(HISTBEEP))
|
|
feep();
|
|
}
|
|
|
|
/* the last vi search */
|
|
|
|
static char *visrchstr;
|
|
static int visrchsense;
|
|
|
|
/**/
|
|
static int
|
|
getvisrchstr(void)
|
|
{
|
|
char *sbuf = halloc(80);
|
|
int sptr = 1, ret = 0, ssbuf = 80;
|
|
Thingy cmd;
|
|
char *okeymap = curkeymapname;
|
|
|
|
if (visrchstr) {
|
|
zsfree(visrchstr);
|
|
visrchstr = NULL;
|
|
}
|
|
statusline = sbuf;
|
|
sbuf[0] = (visrchsense == -1) ? '?' : '/';
|
|
selectkeymap("main", 1);
|
|
while (sptr) {
|
|
sbuf[sptr] = '_';
|
|
statusll = sptr + 1;
|
|
refresh();
|
|
if (!(cmd = getkeycmd()) || cmd == Th(z_sendbreak)) {
|
|
ret = 0;
|
|
break;
|
|
}
|
|
if(cmd == Th(z_magicspace)) {
|
|
c = ' ';
|
|
cmd = Th(z_selfinsert);
|
|
}
|
|
if(cmd == Th(z_redisplay)) {
|
|
redisplay();
|
|
} else if(cmd == Th(z_clearscreen)) {
|
|
clearscreen();
|
|
} else if(cmd == Th(z_acceptline) ||
|
|
cmd == Th(z_vicmdmode)) {
|
|
sbuf[sptr] = 0;
|
|
visrchstr = metafy(sbuf + 1, sptr - 1, META_DUP);
|
|
ret = 1;
|
|
sptr = 0;
|
|
} else if(cmd == Th(z_backwarddeletechar) ||
|
|
cmd == Th(z_vibackwarddeletechar)) {
|
|
sptr--;
|
|
} else if(cmd == Th(z_backwardkillword) ||
|
|
cmd == Th(z_vibackwardkillword)) {
|
|
while(sptr != 1 && iblank(sbuf[sptr - 1]))
|
|
sptr--;
|
|
if(iident(sbuf[sptr - 1]))
|
|
while(sptr != 1 && iident(sbuf[sptr - 1]))
|
|
sptr--;
|
|
else
|
|
while(sptr != 1 && !iident(sbuf[sptr - 1]) && !iblank(sbuf[sptr - 1]))
|
|
sptr--;
|
|
} else if(cmd == Th(z_viquotedinsert) || cmd == Th(z_quotedinsert)) {
|
|
if(cmd == Th(z_viquotedinsert)) {
|
|
sbuf[sptr] = '^';
|
|
refresh();
|
|
}
|
|
if ((c = getkey(0)) == EOF)
|
|
feep();
|
|
else
|
|
goto ins;
|
|
} else if(cmd == Th(z_selfinsertunmeta) || cmd == Th(z_selfinsert)) {
|
|
if(cmd == Th(z_selfinsertunmeta)) {
|
|
c &= 0x7f;
|
|
if(c == '\r')
|
|
c = '\n';
|
|
}
|
|
ins:
|
|
if(sptr == ssbuf - 1) {
|
|
char *newbuf = halloc(ssbuf *= 2);
|
|
strcpy(newbuf, sbuf);
|
|
statusline = sbuf = newbuf;
|
|
}
|
|
sbuf[sptr++] = c;
|
|
} else {
|
|
feep();
|
|
}
|
|
handlefeep();
|
|
}
|
|
statusline = NULL;
|
|
selectkeymap(okeymap, 1);
|
|
return ret;
|
|
}
|
|
|
|
/**/
|
|
void
|
|
vihistorysearchforward(void)
|
|
{
|
|
visrchsense = 1;
|
|
if (getvisrchstr())
|
|
virepeatsearch();
|
|
}
|
|
|
|
/**/
|
|
void
|
|
vihistorysearchbackward(void)
|
|
{
|
|
visrchsense = -1;
|
|
if (getvisrchstr())
|
|
virepeatsearch();
|
|
}
|
|
|
|
/**/
|
|
void
|
|
virepeatsearch(void)
|
|
{
|
|
int hl = histline, t0;
|
|
int n = zmult;
|
|
char *s;
|
|
|
|
if (!visrchstr) {
|
|
feep();
|
|
return;
|
|
}
|
|
if (!n)
|
|
return;
|
|
if (n < 0) {
|
|
n = -n;
|
|
visrchsense = -visrchsense;
|
|
}
|
|
t0 = strlen(visrchstr);
|
|
for (;;) {
|
|
hl += visrchsense;
|
|
if (!(s = zle_get_event(hl))) {
|
|
feep();
|
|
return;
|
|
}
|
|
if (!metadiffer(s, (char *) line, ll))
|
|
continue;
|
|
if (*visrchstr == '^') {
|
|
if (strncmp(s, visrchstr + 1, t0 - 1) != 0)
|
|
continue;
|
|
} else if (!hstrnstr(s, 0, visrchstr, t0, 1, 1))
|
|
continue;
|
|
if (--n <= 0)
|
|
break;
|
|
}
|
|
zle_goto_hist(hl);
|
|
}
|
|
|
|
/**/
|
|
void
|
|
virevrepeatsearch(void)
|
|
{
|
|
visrchsense = -visrchsense;
|
|
virepeatsearch();
|
|
visrchsense = -visrchsense;
|
|
}
|
|
|
|
/* Extra function added by A.R. Iano-Fletcher. */
|
|
/*The extern variable "cs" is the position of the cursor. */
|
|
/* history-beginning-search-backward */
|
|
|
|
/**/
|
|
void
|
|
historybeginningsearchbackward(void)
|
|
{
|
|
int cpos = cs; /* save cursor position */
|
|
int hl = histline;
|
|
int n = zmult;
|
|
char *s;
|
|
|
|
if (!n)
|
|
return;
|
|
if (n < 0) {
|
|
zmult = -n;
|
|
historybeginningsearchforward();
|
|
zmult = n;
|
|
return;
|
|
}
|
|
for (;;) {
|
|
hl--;
|
|
if (!(s = zle_get_event(hl))) {
|
|
feep();
|
|
return;
|
|
}
|
|
if (metadiffer(s, (char *)line, cs) < 0 &&
|
|
metadiffer(s, (char *)line, ll))
|
|
if (--n <= 0)
|
|
break;
|
|
}
|
|
|
|
zle_goto_hist(hl);
|
|
cs = cpos;
|
|
}
|
|
|
|
/* Extra function added by A.R. Iano-Fletcher. */
|
|
|
|
/* history-beginning-search-forward */
|
|
/**/
|
|
void
|
|
historybeginningsearchforward(void)
|
|
{
|
|
int cpos = cs; /* save cursor position */
|
|
int hl = histline;
|
|
int n = zmult;
|
|
char *s;
|
|
|
|
if (!n)
|
|
return;
|
|
if (n < 0) {
|
|
zmult = -n;
|
|
historybeginningsearchbackward();
|
|
zmult = n;
|
|
return;
|
|
}
|
|
for (;;) {
|
|
hl++;
|
|
if (!(s = zle_get_event(hl))) {
|
|
feep();
|
|
return;
|
|
}
|
|
if (metadiffer(s, (char *)line, cs) < (hl == curhist) &&
|
|
metadiffer(s, (char *)line, ll))
|
|
if (--n <= 0)
|
|
break;
|
|
}
|
|
|
|
zle_goto_hist(hl);
|
|
cs = cpos;
|
|
}
|