mirror of
git://git.code.sf.net/p/zsh/code
synced 2024-11-19 21:44:11 +01:00
- Added functions to push and pop the current history list, allowing
functions to more easily switch to their own private history. - Changed the existing history push/pop code in savehistfile() (which uses a separate history buf to allow it to rewrite the on-disk version of the history file without disturbing the in-memory list).
This commit is contained in:
parent
76ec200cc4
commit
e8eca2ee4b
151
Src/hist.c
151
Src/hist.c
@ -1791,13 +1791,26 @@ resizehistents(void)
|
||||
}
|
||||
|
||||
/* Remember the last line in the history file so we can find it again. */
|
||||
static struct {
|
||||
static struct histfile_stats {
|
||||
char *text;
|
||||
time_t stim, mtim;
|
||||
off_t fpos, fsiz;
|
||||
int next_write_ev;
|
||||
} lasthist;
|
||||
|
||||
static struct histsave {
|
||||
struct histfile_stats lasthist;
|
||||
char *histfile;
|
||||
HashTable histtab;
|
||||
Histent hist_ring;
|
||||
int curhist;
|
||||
int histlinect;
|
||||
int histsiz;
|
||||
int savehistsiz;
|
||||
} *histsave_stack;
|
||||
static int histsave_stack_size = 0;
|
||||
static int histsave_stack_pos = 0;
|
||||
|
||||
static int histfile_linect;
|
||||
|
||||
static int
|
||||
@ -2078,31 +2091,20 @@ savehistfile(char *fn, int err, int writeflags)
|
||||
fclose(out);
|
||||
|
||||
if ((writeflags & (HFILE_SKIPOLD | HFILE_FAST)) == HFILE_SKIPOLD) {
|
||||
HashTable remember_histtab = histtab;
|
||||
Histent remember_hist_ring = hist_ring;
|
||||
int remember_histlinect = histlinect;
|
||||
int remember_curhist = curhist;
|
||||
int remember_histsiz = histsiz;
|
||||
int remember_histactive = histactive;
|
||||
|
||||
hist_ring = NULL;
|
||||
curhist = histlinect = 0;
|
||||
histsiz = savehistsiz;
|
||||
/* Zeroing histactive avoids unnecessary munging of curline. */
|
||||
histactive = 0;
|
||||
createhisttable(); /* sets histtab */
|
||||
/* The NULL leaves HISTFILE alone, preserving fn's value. */
|
||||
pushhiststack(NULL, savehistsiz, savehistsiz);
|
||||
|
||||
hist_ignore_all_dups |= isset(HISTSAVENODUPS);
|
||||
readhistfile(fn, err, 0);
|
||||
hist_ignore_all_dups = isset(HISTIGNOREALLDUPS);
|
||||
if (histlinect)
|
||||
savehistfile(fn, err, 0);
|
||||
deletehashtable(histtab);
|
||||
|
||||
curhist = remember_curhist;
|
||||
histlinect = remember_histlinect;
|
||||
hist_ring = remember_hist_ring;
|
||||
histtab = remember_histtab;
|
||||
histsiz = remember_histsiz;
|
||||
pophiststack();
|
||||
histactive = remember_histactive;
|
||||
}
|
||||
} else if (err)
|
||||
@ -2331,3 +2333,120 @@ bufferwords(LinkList list, char *buf, int *index)
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/* Move the current history list out of the way and prepare a fresh history
|
||||
* list using hf for HISTFILE, hs for HISTSIZE, and shs for SAVEHIST. If
|
||||
* the hf value is an empty string, HISTFILE will be unset from the new
|
||||
* environment; if it is NULL, HISTFILE will not be changed, not even by the
|
||||
* pop function (this functionality is used internally to rewrite the current
|
||||
* history file without affecting pointers into the environment).
|
||||
*/
|
||||
|
||||
/**/
|
||||
int
|
||||
pushhiststack(char *hf, int hs, int shs)
|
||||
{
|
||||
struct histsave *h;
|
||||
int curline_in_ring = (histactive & HA_ACTIVE) && hist_ring == &curline;
|
||||
|
||||
if (histsave_stack_pos == histsave_stack_size) {
|
||||
histsave_stack_size += 5;
|
||||
histsave_stack = zrealloc(histsave_stack,
|
||||
histsave_stack_size * sizeof (struct histsave));
|
||||
}
|
||||
|
||||
if (curline_in_ring)
|
||||
unlinkcurline();
|
||||
|
||||
h = &histsave_stack[histsave_stack_pos++];
|
||||
|
||||
h->lasthist = lasthist;
|
||||
if (hf) {
|
||||
if ((h->histfile = getsparam("HISTFILE")) != NULL && *h->histfile)
|
||||
h->histfile = ztrdup(h->histfile);
|
||||
else
|
||||
h->histfile = "";
|
||||
} else
|
||||
h->histfile = NULL;
|
||||
h->histtab = histtab;
|
||||
h->hist_ring = hist_ring;
|
||||
h->curhist = curhist;
|
||||
h->histlinect = histlinect;
|
||||
h->histsiz = histsiz;
|
||||
h->savehistsiz = savehistsiz;
|
||||
|
||||
memset(&lasthist, 0, sizeof lasthist);
|
||||
if (hf) {
|
||||
if (*hf)
|
||||
setsparam("HISTFILE", ztrdup(hf));
|
||||
else
|
||||
unsetparam("HISTFILE");
|
||||
}
|
||||
hist_ring = NULL;
|
||||
curhist = histlinect = 0;
|
||||
histsiz = hs;
|
||||
savehistsiz = shs;
|
||||
inithist(); /* sets histtab */
|
||||
|
||||
if (curline_in_ring)
|
||||
linkcurline();
|
||||
|
||||
return histsave_stack_pos;
|
||||
}
|
||||
|
||||
|
||||
/**/
|
||||
int
|
||||
pophiststack(void)
|
||||
{
|
||||
struct histsave *h;
|
||||
int curline_in_ring = (histactive & HA_ACTIVE) && hist_ring == &curline;
|
||||
|
||||
if (histsave_stack_pos == 0)
|
||||
return 0;
|
||||
|
||||
if (curline_in_ring)
|
||||
unlinkcurline();
|
||||
|
||||
deletehashtable(histtab);
|
||||
zsfree(lasthist.text);
|
||||
|
||||
h = &histsave_stack[--histsave_stack_pos];
|
||||
|
||||
lasthist = h->lasthist;
|
||||
if (h->histfile) {
|
||||
if (*h->histfile)
|
||||
setsparam("HISTFILE", h->histfile);
|
||||
else
|
||||
unsetparam("HISTFILE");
|
||||
}
|
||||
histtab = h->histtab;
|
||||
hist_ring = h->hist_ring;
|
||||
curhist = h->curhist;
|
||||
histlinect = h->histlinect;
|
||||
histsiz = h->histsiz;
|
||||
savehistsiz = h->savehistsiz;
|
||||
|
||||
if (curline_in_ring)
|
||||
linkcurline();
|
||||
|
||||
return histsave_stack_pos + 1;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
saveandpophiststack(int down_through)
|
||||
{
|
||||
if (down_through < 0)
|
||||
down_through += histsave_stack_pos + 1;
|
||||
if (down_through <= 0)
|
||||
down_through = 1;
|
||||
if (histsave_stack_pos < down_through)
|
||||
return 0;
|
||||
do {
|
||||
if (!nohistsave)
|
||||
savehistfile(NULL, 1, HFILE_USE_OPTIONS);
|
||||
pophiststack();
|
||||
} while (histsave_stack_pos >= down_through);
|
||||
return 1;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user