show the exit status of a failed command in the prompt
- user@host:dir [N] $ after a command failed with exit status N, the plain prompt again after a successful command - the status is colored bold red by default, configurable with the new GOSH_COLORS key error Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b3311cbf94
commit
041406a340
3 files changed
+86
-28
No files matched your search
+29
-9
@@ -1054,24 +1054,24 @@ func TestGetPrompt_EscapesControlCharacters(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBuildPrompt_Color(t *testing.T) {
|
||||
got := buildPrompt("flow", "host", "~/src", false, &defaultColors)
|
||||
got := buildPrompt("flow", "host", "~/src", false, 0, &defaultColors)
|
||||
want := "\x1b[1;32mflow@host\x1b[0m:\x1b[1;34m~/src\x1b[0m $ "
|
||||
if got != want {
|
||||
t.Errorf("buildPrompt() = %q, want %q", got, want)
|
||||
}
|
||||
|
||||
got = buildPrompt("root", "host", "/", true, &defaultColors)
|
||||
got = buildPrompt("root", "host", "/", true, 0, &defaultColors)
|
||||
if !strings.HasPrefix(got, "\x1b[1;31mroot@host") {
|
||||
t.Errorf("expected red user for root, got %q", got)
|
||||
}
|
||||
|
||||
got = buildPrompt("flow", "host", "~/src", false, nil)
|
||||
got = buildPrompt("flow", "host", "~/src", false, 0, nil)
|
||||
if got != "flow@host:~/src $ " {
|
||||
t.Errorf("buildPrompt() without color = %q", got)
|
||||
}
|
||||
|
||||
colors := promptColors{user: "38;5;208", path: ""}
|
||||
got = buildPrompt("flow", "host", "~/src", false, &colors)
|
||||
got = buildPrompt("flow", "host", "~/src", false, 0, &colors)
|
||||
if got != "\x1b[38;5;208mflow@host\x1b[0m:~/src $ " {
|
||||
t.Errorf("buildPrompt() with custom colors = %q", got)
|
||||
}
|
||||
@@ -1083,13 +1083,14 @@ func TestParseColors(t *testing.T) {
|
||||
want promptColors
|
||||
}{
|
||||
{"", defaultColors},
|
||||
{"user=1;33", promptColors{user: "1;33", root: "1;31", path: "1;34"}},
|
||||
{"user=33:root=41;97:path=38;5;208", promptColors{user: "33", root: "41;97", path: "38;5;208"}},
|
||||
{"path=", promptColors{user: "1;32", root: "1;31", path: ""}},
|
||||
{"user=1;33", promptColors{user: "1;33", root: "1;31", path: "1;34", error: "1;31"}},
|
||||
{"user=33:root=41;97:path=38;5;208", promptColors{user: "33", root: "41;97", path: "38;5;208", error: "1;31"}},
|
||||
{"error=33", promptColors{user: "1;32", root: "1;31", path: "1;34", error: "33"}},
|
||||
{"path=", promptColors{user: "1;32", root: "1;31", path: "", error: "1;31"}},
|
||||
{"path=0m\x1b[2J", defaultColors}, // escape sequences are rejected
|
||||
{"path=red", defaultColors}, // only numeric codes
|
||||
{"foo=1:user", defaultColors}, // unknown key, missing value
|
||||
{"user=35::path=36", promptColors{user: "35", root: "1;31", path: "36"}},
|
||||
{"user=35::path=36", promptColors{user: "35", root: "1;31", path: "36", error: "1;31"}},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
if got := parseColors(tc.spec); got != tc.want {
|
||||
@@ -1098,8 +1099,27 @@ func TestParseColors(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildPrompt_Status(t *testing.T) {
|
||||
if got := buildPrompt("flow", "host", "~", false, 0, nil); got != "flow@host:~ $ " {
|
||||
t.Errorf("status 0: %q", got)
|
||||
}
|
||||
if got := buildPrompt("flow", "host", "~", false, 127, nil); got != "flow@host:~ [127] $ " {
|
||||
t.Errorf("status 127 without color: %q", got)
|
||||
}
|
||||
got := buildPrompt("flow", "host", "~", false, 1, &defaultColors)
|
||||
want := "\x1b[1;32mflow@host\x1b[0m:\x1b[1;34m~\x1b[0m \x1b[1;31m[1]\x1b[0m $ "
|
||||
if got != want {
|
||||
t.Errorf("status 1 with color = %q, want %q", got, want)
|
||||
}
|
||||
colors := defaultColors
|
||||
colors.error = ""
|
||||
if got := buildPrompt("flow", "host", "~", false, 2, &colors); !strings.HasSuffix(got, " [2] $ ") {
|
||||
t.Errorf("status without error color = %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildPrompt_ColorEscapesControlCharacters(t *testing.T) {
|
||||
got := buildPrompt("flow", "host", "evil\x1b[2J\x07", false, &defaultColors)
|
||||
got := buildPrompt("flow", "host", "evil\x1b[2J\x07", false, 0, &defaultColors)
|
||||
if strings.Contains(got, "\x1b[2J") || strings.Contains(got, "\x07") {
|
||||
t.Errorf("prompt contains control characters from path: %q", got)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user