summary refs log tree commit diff
path: root/bin
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2020-12-23 14:19:58 -0500
committerJune McEnroe <june@causal.agency>2020-12-23 15:56:18 -0500
commite50150458145caddac0fb0e2dd75cf99042e2b06 (patch)
tree22ad917fc6cab92659d5c23733ef78bdc9255cd2 /bin
parentBind libedit's secret filename completion function (diff)
downloadsrc-e50150458145caddac0fb0e2dd75cf99042e2b06.tar.gz
src-e50150458145caddac0fb0e2dd75cf99042e2b06.zip
Cache the expanded prompt for editline
Previously, the prompt would be expanded every time editline called the
getprompt callback. I think the code may have been written assuming that
editline only calls getprompt once per prompt, but it may actually call
it many times, for instance every time you type backspace. This results
not only in slower editing from expanding complex prompts repeatedly, it
also consumes more and more stack memory each time getprompt is called.
This can be seen by setting PS1 to some command substitution, typing
many characters at the prompt, then holding backspace and observing
memory usage. Thankfully all this stack memory is freed between prompts
by the stackmark calls around el_gets.

This change causes prompt expansion to always happen in the setprompt
call, as it would when editline is disabled, and a cached copy of the
prompt is saved for getprompt to return every time editline calls it.
Since getprompt is no longer doing expansion, the stackmark calls
surrounding el_gets can be removed.
Diffstat (limited to 'bin')
-rw-r--r--bin/dash/src/input.c6
-rw-r--r--bin/dash/src/parser.c66
2 files changed, 37 insertions, 35 deletions
diff --git a/bin/dash/src/input.c b/bin/dash/src/input.c
index 17544e78..4167bd18 100644
--- a/bin/dash/src/input.c
+++ b/bin/dash/src/input.c
@@ -152,12 +152,8 @@ retry:
 		static const char *rl_cp;
 		static int el_len;
 
-		if (rl_cp == NULL) {
-			struct stackmark smark;
-			pushstackmark(&smark, stackblocksize());
+		if (rl_cp == NULL)
 			rl_cp = el_gets(el, &el_len);
-			popstackmark(&smark);
-		}
 		if (rl_cp == NULL)
 			nr = 0;
 		else {
diff --git a/bin/dash/src/parser.c b/bin/dash/src/parser.c
index a47022e0..270a01de 100644
--- a/bin/dash/src/parser.c
+++ b/bin/dash/src/parser.c
@@ -107,6 +107,9 @@ struct heredoc *heredoc;
 int quoteflag;			/* set if (part of) last token was quoted */
 
 
+static char *promptcache;
+
+
 STATIC union node *list(int);
 STATIC union node *andor(void);
 STATIC union node *pipeline(void);
@@ -1541,27 +1544,6 @@ synerror(const char *msg)
 	/* NOTREACHED */
 }
 
-STATIC void
-setprompt(int which)
-{
-	struct stackmark smark;
-	int show;
-
-	needprompt = 0;
-	whichprompt = which;
-
-#ifdef SMALL
-	show = 1;
-#else
-	show = !el;
-#endif
-	if (show) {
-		pushstackmark(&smark, stackblocksize());
-		out2str(getprompt(NULL));
-		popstackmark(&smark);
-	}
-}
-
 const char *
 expandstr(const char *ps)
 {
@@ -1611,22 +1593,25 @@ out:
 	return result;
 }
 
-/*
- * called by editline -- any expansions to the prompt
- *    should be added here.
- */
-const char *
-getprompt(void *unused)
+STATIC void
+setprompt(int which)
 {
+	struct stackmark smark;
 	const char *prompt;
+	int show;
+
+	needprompt = 0;
+	whichprompt = which;
 
 	switch (whichprompt) {
 	default:
 #ifdef DEBUG
-		return "<internal prompt error>";
+		prompt = "<internal prompt error>";
+		break;
 #endif
 	case 0:
-		return nullstr;
+		prompt = nullstr;
+		break;
 	case 1:
 		prompt = ps1val();
 		break;
@@ -1635,7 +1620,28 @@ getprompt(void *unused)
 		break;
 	}
 
-	return expandstr(prompt);
+#ifdef SMALL
+	show = 1;
+#else
+	show = !el;
+#endif
+	pushstackmark(&smark, stackblocksize());
+	if (show) {
+		out2str(expandstr(prompt));
+	} else {
+		free(promptcache);
+		promptcache = savestr(expandstr(prompt));
+	}
+	popstackmark(&smark);
+}
+
+/*
+ * called by editline -- return the cached prompt expansion.
+ */
+const char *
+getprompt(void *unused)
+{
+	return promptcache;
 }
 
 const char *const *
'>Add -X flag to install X stuff on OpenBSDJune McEnroe 2021-02-07Adjust brightness by smaller incrementsJune McEnroe 2021-02-07Fix cwm window cycling, move big by defaultJune McEnroe 2021-02-07Use class names for Foreground, Background, BorderColorJune McEnroe I'm not really sure what difference this makes, but it seems like the right thing to do to be generic? 2021-02-07Add simple battery status and clock to xsessionJune McEnroe I love how simple this is. 2021-02-07Set cursor theme and sizeJune McEnroe 2021-02-07Use scrot for up -s if no screencaptureJune McEnroe Still missing putting the URL in an X selection. 2021-02-07Enable mouse acceleration in XJune McEnroe 2021-02-07Set colours for Xt and cwmJune McEnroe And increase XTerm internalBorder. 2021-02-07Set urgency on bell in xtermJune McEnroe 2021-02-07Add bindings for brightness controlJune McEnroe Weirdly the Fn key doesn't change how the F row registers... I wonder if I can do something about that. 2021-02-07Set X key repeat rateJune McEnroe 2021-02-07Bump font size to 12June McEnroe 11 is what I use on macOS, but I feel like my eyes are working harder here. 2021-02-07Fully configure and rebind cwmJune McEnroe This is sort of a mix of trying to emulate macOS somewhat for my muscle memory and just rebinding some of the cwm defaults to use 4- rather than M-. 2021-02-07Add BintiJune McEnroe 2021-02-07Finish configuring xtermJune McEnroe 2021-02-06Enable tapping, reverse scroll, set scaling in wsconsctlJune McEnroe 2021-02-06Set root window to black on purple snowJune McEnroe 2021-02-06Add xmodmap configurationJune McEnroe 2021-02-06Add initial OpenBSD X configurationJune McEnroe cwm still needs a lot more rebinding, and I need to actually look at its other options. xterm definitely still needs some configuration, but I at least managed to get it to use a decent looking font. Very happy that OpenBSD includes Luxi Mono, which is what my usual font, Go Mono, is based on anyway. Still missing is xmodmap and such. 2021-02-06Add xterm output to schemeJune McEnroe