diff options
author | Juraj Lutter <otis@FreeBSD.org> | 2022-12-08 20:30:26 +0000 |
---|---|---|
committer | Juraj Lutter <otis@FreeBSD.org> | 2022-12-22 18:10:48 +0000 |
commit | 3cf65f8a7f8ee993118fe06f3c187ad30f875132 (patch) | |
tree | 3ee6d240d96159560c2888a9c6dbeb431423e071 /bin | |
parent | 65308195e82487d82a1feace82686e5c45f88bd3 (diff) | |
download | src-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.c | 2 | ||||
-rw-r--r-- | bin/sh/parser.c | 47 | ||||
-rw-r--r-- | bin/sh/sh.1 | 20 |
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 |