mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-04-14 03:25:50 +00:00
bash: fix multiline PS1 with command substitutions (#11369)
Only replace the \n prompt escape when inserting secondary prompt marks,
not literal newlines `($'\n')`. Literal newlines may appear inside
`$(...)` or `...` command substitutions, and inserting escape sequences
there breaks the shell syntax. For example:
PS1='$(if [ $? -eq 0 ]; then echo -e "P";
else echo -e "F";
fi) $ '
The literal newlines between the if/else/fi are part of the shell syntax
inside the command substitution. The previous code replaced all literal
newlines in PS1 with newline + OSC 133 escape sequences, which injected
terminal escapes into the middle of the command substitution and caused
bash to report a syntax error when evaluating it.
The \n prompt escape is PS1-specific and safe to replace globally. This
means prompts using literal newlines for line breaks (rather than \n)
won't get per-line secondary marks, but this is the conventional form
and avoids the need for complex shell parsing.
Fixes: #11267
This commit is contained in:
@@ -201,14 +201,16 @@ function __ghostty_precmd() {
|
||||
PS1='\[\e]133;A;redraw=last;cl=line;aid='"$BASHPID"'\a\]'$PS1'\[\e]133;B\a\]'
|
||||
PS2='\[\e]133;A;k=s\a\]'$PS2'\[\e]133;B\a\]'
|
||||
|
||||
# Bash doesn't redraw the leading lines in a multiline prompt so
|
||||
# we mark the start of each line (after each newline) as a secondary
|
||||
# prompt. This correctly handles multiline prompts by setting the first
|
||||
# to primary and the subsequent lines to secondary.
|
||||
if [[ "${PS1}" == *"\n"* || "${PS1}" == *$'\n'* ]]; then
|
||||
builtin local __ghostty_mark=$'\\[\\e]133;A;k=s\\a\\]'
|
||||
PS1="${PS1//$'\n'/$'\n'$__ghostty_mark}"
|
||||
PS1="${PS1//\\n/\\n$__ghostty_mark}"
|
||||
# Bash doesn't redraw the leading lines in a multiline prompt so we mark
|
||||
# the start of each line (after each newline) as a secondary prompt. This
|
||||
# correctly handles multiline prompts by setting the first to primary and
|
||||
# the subsequent lines to secondary.
|
||||
#
|
||||
# We only replace the \n prompt escape, not literal newlines ($'\n'),
|
||||
# because literal newlines may appear inside $(...) command substitutions
|
||||
# where inserting escape sequences would break shell syntax.
|
||||
if [[ "$PS1" == *"\n"* ]]; then
|
||||
PS1="${PS1//\\n/\\n$'\\[\\e]133;A;k=s\\a\\]'}"
|
||||
fi
|
||||
|
||||
# Cursor
|
||||
|
||||
Reference in New Issue
Block a user