Skip to content

Commit

Permalink
fix(bash): escape entire rprompt
Browse files Browse the repository at this point in the history
resolves #717
  • Loading branch information
JanDeDobbeleer committed May 21, 2021
1 parent 5047376 commit b67f625
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 16 deletions.
2 changes: 2 additions & 0 deletions src/ansi.go
Expand Up @@ -30,10 +30,12 @@ type ansiUtils struct {
italic string
underline string
strikethrough string
bashFormat string
}

func (a *ansiUtils) init(shell string) {
a.shell = shell
a.bashFormat = "\\[%s\\]"
switch shell {
case zsh:
a.linechange = "%%{\x1b[%d%s%%}"
Expand Down
10 changes: 10 additions & 0 deletions src/block.go
Expand Up @@ -47,6 +47,16 @@ func (b *Block) init(env environmentInfo, writer colorWriter, ansi *ansiUtils) {
b.ansi = ansi
}

func (b *Block) initPlain(env environmentInfo, config *Config) {
b.ansi = &ansiUtils{}
b.ansi.init(plain)
b.writer = &AnsiColor{
ansi: b.ansi,
terminalBackground: getConsoleBackgroundColor(env, config.TerminalBackground),
}
b.env = env
}

func (b *Block) enabled() bool {
if b.Type == LineBreak {
return true
Expand Down
40 changes: 26 additions & 14 deletions src/engine.go
Expand Up @@ -49,7 +49,13 @@ func (e *engine) render() string {
}

func (e *engine) renderBlock(block *Block) {
block.init(e.env, e.colorWriter, e.ansi)
// when in bash, for rprompt blocks we need to write plain
// and wrap in escaped mode or the prompt will not render correctly
if block.Type == RPrompt && e.env.getShellName() == bash {
block.initPlain(e.env, e.config)
} else {
block.init(e.env, e.colorWriter, e.ansi)
}
block.setStringValues()
if !block.enabled() {
return
Expand Down Expand Up @@ -77,7 +83,11 @@ func (e *engine) renderBlock(block *Block) {
e.write(block.renderSegments())
}
case RPrompt:
e.rprompt = block.renderSegments()
blockText := block.renderSegments()
if e.env.getShellName() == bash {
blockText = fmt.Sprintf(e.ansi.bashFormat, blockText)
}
e.rprompt = blockText
}
// Due to a bug in Powershell, the end of the line needs to be cleared.
// If this doesn't happen, the portion after the prompt gets colored in the background
Expand Down Expand Up @@ -133,20 +143,22 @@ func (e *engine) debug() string {
func (e *engine) print() string {
switch e.env.getShellName() {
case zsh:
if *e.env.getArgs().Eval {
// escape double quotes contained in the prompt
prompt := fmt.Sprintf("PS1=\"%s\"", strings.ReplaceAll(e.string(), "\"", "\"\""))
prompt += fmt.Sprintf("\nRPROMPT=\"%s\"", e.rprompt)
return prompt
if !*e.env.getArgs().Eval {
break
}
case pwsh, powershell5, bash, shelly:
if e.rprompt != "" {
e.write(e.ansi.saveCursorPosition)
e.write(e.ansi.carriageForward())
e.write(e.ansi.getCursorForRightWrite(e.rprompt, 0))
e.write(e.rprompt)
e.write(e.ansi.restoreCursorPosition)
// escape double quotes contained in the prompt
prompt := fmt.Sprintf("PS1=\"%s\"", strings.ReplaceAll(e.string(), "\"", "\"\""))
prompt += fmt.Sprintf("\nRPROMPT=\"%s\"", e.rprompt)
return prompt
case pwsh, powershell5, bash, plain:
if e.rprompt == "" {
break
}
e.write(e.ansi.saveCursorPosition)
e.write(e.ansi.carriageForward())
e.write(e.ansi.getCursorForRightWrite(e.rprompt, 0))
e.write(e.rprompt)
e.write(e.ansi.restoreCursorPosition)
}
return e.string()
}
2 changes: 1 addition & 1 deletion src/image_test.go
Expand Up @@ -16,7 +16,7 @@ func runImageTest(content string) error {
}
defer os.Remove(file.Name())
ansi := &ansiUtils{}
ansi.init(shelly)
ansi.init(plain)
image := &ImageRenderer{
ansiString: content,
ansi: ansi,
Expand Down
2 changes: 1 addition & 1 deletion src/main.go
Expand Up @@ -33,7 +33,7 @@ const (
pwsh = "pwsh"
fish = "fish"
powershell5 = "powershell"
shelly = "shell"
plain = "shell"
)

type args struct {
Expand Down

0 comments on commit b67f625

Please sign in to comment.