summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWayne Davison <wayned@users.sourceforge.net>2004-05-20 22:23:02 +0000
committerWayne Davison <wayned@users.sourceforge.net>2004-05-20 22:23:02 +0000
commite8eca2ee4b2c46ea6eb047e54fa4c7dcb1869fa1 (patch)
treea9c12dbd02bbf7419778aaf1dbc8430e9ccc51ec
parent76ec200cc4daa7f7cdd0bd9565236a7f7bf19b4c (diff)
downloadzsh-e8eca2ee4b2c46ea6eb047e54fa4c7dcb1869fa1.tar.gz
zsh-e8eca2ee4b2c46ea6eb047e54fa4c7dcb1869fa1.zip
- 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).
-rw-r--r--Src/hist.c151
1 files changed, 135 insertions, 16 deletions
diff --git a/Src/hist.c b/Src/hist.c
index e0be6e030..7f8bc7cc9 100644
--- a/Src/hist.c
+++ b/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;
+}