aboutsummaryrefslogtreecommitdiff
path: root/bin
diff options
context:
space:
mode:
authorJuraj Lutter <otis@FreeBSD.org>2022-12-08 20:30:26 +0000
committerJuraj Lutter <otis@FreeBSD.org>2022-12-22 18:10:48 +0000
commit3cf65f8a7f8ee993118fe06f3c187ad30f875132 (patch)
tree3ee6d240d96159560c2888a9c6dbeb431423e071 /bin
parent65308195e82487d82a1feace82686e5c45f88bd3 (diff)
downloadsrc-3cf65f8a7f8ee993118fe06f3c187ad30f875132.tar.gz
src-3cf65f8a7f8ee993118fe06f3c187ad30f875132.zip
sh(1): Allow non-printing characters in prompt strings
Introduce new prompt format characters: - '\[' starts the sequence of non-printing chatacters - '\]' ends the sequence of non-printing characters Within these sequences, the following characters are now supported: - '\a' emits ASCII BEL (0x07, 007) character - '\e' emits ASCII ESC (0x1b, 033) character - '\r' emits ASCII CR (0x0d, 015) character - '\n' emits ASCII CRLF sequence These can be used to embed ANSI sequences into prompt strings. Example in .shrc: PS1="\[\e[7m\]\u@\h\[\e[0m\]:\w \\$ " This tries to maintain some degree of compatibility with GNU bash, that uses GNU readline library (which behaves slightly different from BSD editline): It has two "non-printing boundary" characters: - RL_PROMPT_START_IGNORE (\001) - RL_PROMPT_END_IGNORE (\002) while BSD editline only has one (when using EL_PROMPT_ESC setting), so for this purpose, ASCII \001 was chosen and both \[ and \] emits this character. And while here, enlarge PROMPTLEN from 128 to 192 characters. Reviewed by: jilles Approved by: jilles Differential Revision: https://reviews.freebsd.org/D37701
Diffstat (limited to 'bin')
-rw-r--r--bin/sh/histedit.c2
-rw-r--r--bin/sh/parser.c47
-rw-r--r--bin/sh/sh.120
3 files changed, 59 insertions, 10 deletions
diff --git a/bin/sh/histedit.c b/bin/sh/histedit.c
index 8812200279f0..0eb8c6c1784f 100644
--- a/bin/sh/histedit.c
+++ b/bin/sh/histedit.c
@@ -190,7 +190,7 @@ histedit(void)
if (el != NULL) {
if (hist)
el_set(el, EL_HIST, history, hist);
- el_set(el, EL_PROMPT, getprompt);
+ el_set(el, EL_PROMPT_ESC, getprompt, '\001');
el_set(el, EL_ADDFN, "sh-complete",
"Filename completion",
sh_complete);
diff --git a/bin/sh/parser.c b/bin/sh/parser.c
index e75798800edf..7f8283ca4dff 100644
--- a/bin/sh/parser.c
+++ b/bin/sh/parser.c
@@ -70,7 +70,7 @@ __FBSDID("$FreeBSD$");
* Shell command parser.
*/
-#define PROMPTLEN 128
+#define PROMPTLEN 192
/* values of checkkwd variable */
#define CHKALIAS 0x1
@@ -2061,6 +2061,44 @@ getprompt(void *unused __unused)
switch (*++fmt) {
/*
+ * Non-printing sequence begin and end.
+ */
+ case '[':
+ case ']':
+ ps[i] = '\001';
+ break;
+
+ /*
+ * Literal \ and some ASCII characters:
+ * \a BEL
+ * \e ESC
+ * \r CR
+ */
+ case '\\':
+ case 'a':
+ case 'e':
+ case 'r':
+ if (*fmt == 'a')
+ ps[i] = '\007';
+ else if (*fmt == 'e')
+ ps[i] = '\033';
+ else if (*fmt == 'r')
+ ps[i] = '\r';
+ else
+ ps[i] = '\\';
+ break;
+
+ /*
+ * CRLF sequence
+ */
+ case 'n':
+ if (i < PROMPTLEN - 3) {
+ ps[i++] = '\r';
+ ps[i] = '\n';
+ }
+ break;
+
+ /*
* Hostname.
*
* \h specifies just the local hostname,
@@ -2137,13 +2175,6 @@ getprompt(void *unused __unused)
break;
/*
- * A literal \.
- */
- case '\\':
- ps[i] = '\\';
- break;
-
- /*
* Emit unrecognized formats verbatim.
*/
default:
diff --git a/bin/sh/sh.1 b/bin/sh/sh.1
index 7a30020f2f7f..330685a911e1 100644
--- a/bin/sh/sh.1
+++ b/bin/sh/sh.1
@@ -32,7 +32,7 @@
.\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95
.\" $FreeBSD$
.\"
-.Dd May 10, 2021
+.Dd December 14, 2022
.Dt SH 1
.Os
.Sh NAME
@@ -1446,6 +1446,24 @@ for normal users and
for superusers.
.It Li \e\e
A literal backslash.
+.It Li \e[
+Start of a sequence of non-printing characters (used, for example,
+to embed ANSI CSI sequences into the prompt).
+.It Li \e]
+End of a sequence of non-printing characters.
+.El
+.Pp
+The following special and non-printing characters are supported
+within the sequence of non-printing characters:
+.Bl -tag -width indent
+.It Li \ea
+Emits ASCII BEL (0x07, 007) character.
+.It Li \ee
+Emits ASCII ESC (0x1b, 033) character.
+.It Li \er
+Emits ASCII CR (0x0d, 015) character.
+.It Li \en
+Emits CRLF sequence.
.El
.It Va PS2
The secondary prompt string, which defaults to