summary refs log tree commit diff
path: root/Src
diff options
context:
space:
mode:
Diffstat (limited to 'Src')
-rw-r--r--Src/Zle/zle_params.c13
-rw-r--r--Src/Zle/zle_tricky.c16
-rw-r--r--Src/hist.c16
-rw-r--r--Src/lex.c12
4 files changed, 48 insertions, 9 deletions
diff --git a/Src/Zle/zle_params.c b/Src/Zle/zle_params.c
index f384753e2..2883c0fbd 100644
--- a/Src/Zle/zle_params.c
+++ b/Src/Zle/zle_params.c
@@ -334,8 +334,19 @@ get_rbuffer(UNUSED(Param pm))
 static char *
 get_prebuffer(UNUSED(Param pm))
 {
-    if (chline)
+    /*
+     * Use the editing current history line, not necessarily the
+     * history line that's currently in the history mechanism
+     * since our line may have been stacked.
+     */
+    if (zle_chline) {
+	/* zle_chline was NULL terminated when pushed onto the stack */
+	return dupstring(zle_chline);
+    }
+    if (chline) {
+	/* hptr is valid */
 	return dupstrpfx(chline, hptr - chline);
+    }
     return dupstring("");
 }
 
diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c
index dce7fb700..3e2a35171 100644
--- a/Src/Zle/zle_tricky.c
+++ b/Src/Zle/zle_tricky.c
@@ -632,16 +632,16 @@ docomplete(int lst)
     origline = dupstring(zlemetaline);
     origcs = zlemetacs;
     origll = zlemetall;
-    if (!isfirstln && chline != NULL) {
-	/* If we are completing in a multi-line buffer (which was not  *
-	 * taken from the history), we have to prepend the stuff saved *
-	 * in chline to the contents of line.                          */
-
+    if (!isfirstln && (chline != NULL || zle_chline != NULL)) {
 	ol = dupstring(zlemetaline);
-	/* Make sure that chline is zero-terminated. */
-	*hptr = '\0';
+	/*
+	 * Make sure that chline is zero-terminated.
+	 * zle_chline always is and hptr doesn't point into it anyway.
+	 */
+	if (!zle_chline)
+	    *hptr = '\0';
 	zlemetacs = 0;
-	inststr(chline);
+	inststr(zle_chline ? zle_chline : chline);
 	chl = zlemetacs;
 	zlemetacs += ocs;
     } else
diff --git a/Src/hist.c b/Src/hist.c
index b1e4e82c4..08a613d4c 100644
--- a/Src/hist.c
+++ b/Src/hist.c
@@ -164,6 +164,22 @@ mod_export char *hptr;
 /**/
 mod_export char *chline;
 
+/*
+ * The current history line as seen by ZLE.
+ * We modify chline for use in other contexts while ZLE may
+ * still be running; ZLE should see only the top-level value.
+ *
+ * To avoid having to modify this every time we modify chline,
+ * we set it when we push the stack, and unset it when we pop
+ * the appropriate value off the stack.  As it's never modified
+ * on the stack this is the only maintainance we ever do on it.
+ * In return, ZLE has to check both zle_chline and (if that's
+ * NULL) chline to get the current value.
+ */
+
+/**/
+mod_export char *zle_chline;
+
 /* true if the last character returned by hgetc was an escaped bangchar *
  * if it is set and NOBANGHIST is unset hwaddc escapes bangchars        */
 
diff --git a/Src/lex.c b/Src/lex.c
index f25bd3eca..8f432515c 100644
--- a/Src/lex.c
+++ b/Src/lex.c
@@ -249,6 +249,13 @@ lexsave(void)
     ls->histdone = histdone;
     ls->stophist = stophist;
     stophist = 0;
+    if (!lstack) {
+	/* top level, make this version visible to ZLE */
+	zle_chline = chline;
+	/* ensure line stored is NULL-terminated */
+	if (hptr)
+	    *hptr = '\0';
+    }
     ls->hline = chline;
     chline = NULL;
     ls->hptr = hptr;
@@ -355,6 +362,11 @@ lexrestore(void)
     errflag = 0;
 
     ln = lstack->next;
+    if (!ln) {
+	/* Back to top level: don't need special ZLE value */
+	DPUTS(chline != zle_chline, "BUG: Ouch, wrong chline for ZLE");
+	zle_chline = NULL;
+    }
     free(lstack);
     lstack = ln;
 }