mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2024-11-10 13:04:04 -08:00
parent
992add9a78
commit
d8b979ec3b
|
@ -10,7 +10,8 @@ func (ansi *Ansi) MeasureText(text string) int {
|
||||||
// skip strings with ANSI
|
// skip strings with ANSI
|
||||||
if !strings.Contains(text, "\x1b") {
|
if !strings.Contains(text, "\x1b") {
|
||||||
text = ansi.TrimEscapeSequences(text)
|
text = ansi.TrimEscapeSequences(text)
|
||||||
return utf8.RuneCountInString(text)
|
length := utf8.RuneCountInString(text)
|
||||||
|
return length
|
||||||
}
|
}
|
||||||
if strings.Contains(text, "\x1b]8;;") {
|
if strings.Contains(text, "\x1b]8;;") {
|
||||||
matches := regex.FindAllNamedRegexMatch(ansi.hyperlinkRegex, text)
|
matches := regex.FindAllNamedRegexMatch(ansi.hyperlinkRegex, text)
|
||||||
|
@ -20,7 +21,8 @@ func (ansi *Ansi) MeasureText(text string) int {
|
||||||
}
|
}
|
||||||
text = ansi.TrimAnsi(text)
|
text = ansi.TrimAnsi(text)
|
||||||
text = ansi.TrimEscapeSequences(text)
|
text = ansi.TrimEscapeSequences(text)
|
||||||
return utf8.RuneCountInString(text)
|
length := utf8.RuneCountInString(text)
|
||||||
|
return length
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ansi *Ansi) TrimAnsi(text string) string {
|
func (ansi *Ansi) TrimAnsi(text string) string {
|
||||||
|
|
|
@ -41,6 +41,9 @@ func (e *Engine) string() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Engine) canWriteRPrompt() bool {
|
func (e *Engine) canWriteRPrompt() bool {
|
||||||
|
if e.rprompt == "" || e.Plain {
|
||||||
|
return false
|
||||||
|
}
|
||||||
consoleWidth, err := e.Env.TerminalWidth()
|
consoleWidth, err := e.Env.TerminalWidth()
|
||||||
if err != nil || consoleWidth == 0 {
|
if err != nil || consoleWidth == 0 {
|
||||||
return true
|
return true
|
||||||
|
@ -86,7 +89,7 @@ func (e *Engine) shouldFill(block *Block, length int) (string, bool) {
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
terminalWidth, err := e.Env.TerminalWidth()
|
terminalWidth, err := e.Env.TerminalWidth()
|
||||||
if err != nil && terminalWidth == 0 {
|
if err != nil || terminalWidth == 0 {
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
padLength := terminalWidth - e.currentLineLength - length
|
padLength := terminalWidth - e.currentLineLength - length
|
||||||
|
@ -106,7 +109,7 @@ func (e *Engine) shouldFill(block *Block, length int) (string, bool) {
|
||||||
func (e *Engine) renderBlock(block *Block) {
|
func (e *Engine) renderBlock(block *Block) {
|
||||||
// when in bash, for rprompt blocks we need to write plain
|
// when in bash, for rprompt blocks we need to write plain
|
||||||
// and wrap in escaped mode or the prompt will not render correctly
|
// and wrap in escaped mode or the prompt will not render correctly
|
||||||
if block.Type == RPrompt && e.Env.Shell() == shell.BASH {
|
if e.Env.Shell() == shell.BASH && (block.Type == RPrompt || block.Alignment == Right) {
|
||||||
block.InitPlain(e.Env, e.Config)
|
block.InitPlain(e.Env, e.Config)
|
||||||
} else {
|
} else {
|
||||||
block.Init(e.Env, e.Writer, e.Ansi)
|
block.Init(e.Env, e.Writer, e.Ansi)
|
||||||
|
@ -127,28 +130,42 @@ func (e *Engine) renderBlock(block *Block) {
|
||||||
if block.VerticalOffset != 0 {
|
if block.VerticalOffset != 0 {
|
||||||
e.writeANSI(e.Ansi.ChangeLine(block.VerticalOffset))
|
e.writeANSI(e.Ansi.ChangeLine(block.VerticalOffset))
|
||||||
}
|
}
|
||||||
switch block.Alignment {
|
|
||||||
case Right:
|
if block.Alignment == Left {
|
||||||
text, length := block.RenderSegments()
|
|
||||||
if padText, OK := e.shouldFill(block, length); OK {
|
|
||||||
e.write(padText)
|
|
||||||
}
|
|
||||||
e.writeANSI(e.Ansi.CarriageForward())
|
|
||||||
e.writeANSI(e.Ansi.GetCursorForRightWrite(length, block.HorizontalOffset))
|
|
||||||
e.currentLineLength = 0
|
|
||||||
e.write(text)
|
|
||||||
case Left:
|
|
||||||
text, length := block.RenderSegments()
|
text, length := block.RenderSegments()
|
||||||
e.currentLineLength += length
|
e.currentLineLength += length
|
||||||
e.write(text)
|
e.write(text)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
case RPrompt:
|
|
||||||
|
if block.Alignment != Right {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
text, length := block.RenderSegments()
|
text, length := block.RenderSegments()
|
||||||
e.rpromptLength = length
|
padText, hasPadText := e.shouldFill(block, length)
|
||||||
if e.Env.Shell() == shell.BASH {
|
if hasPadText {
|
||||||
text = e.Ansi.FormatText(text)
|
// in this case we can print plain
|
||||||
|
e.write(padText)
|
||||||
|
e.write(text)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
e.rprompt = text
|
// this can contain ANSI escape sequences
|
||||||
|
ansi := e.Ansi
|
||||||
|
if e.Env.Shell() == shell.BASH {
|
||||||
|
ansi = &color.Ansi{}
|
||||||
|
ansi.InitPlain()
|
||||||
|
}
|
||||||
|
prompt := ansi.CarriageForward()
|
||||||
|
prompt += ansi.GetCursorForRightWrite(length, block.HorizontalOffset)
|
||||||
|
prompt += text
|
||||||
|
e.currentLineLength = 0
|
||||||
|
if e.Env.Shell() == shell.BASH {
|
||||||
|
prompt = e.Ansi.FormatText(prompt)
|
||||||
|
}
|
||||||
|
e.write(prompt)
|
||||||
|
case RPrompt:
|
||||||
|
e.rprompt, e.rpromptLength = block.RenderSegments()
|
||||||
}
|
}
|
||||||
// Due to a bug in Powershell, the end of the line needs to be cleared.
|
// 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
|
// If this doesn't happen, the portion after the prompt gets colored in the background
|
||||||
|
@ -213,8 +230,8 @@ func (e *Engine) print() string {
|
||||||
prompt := fmt.Sprintf("PS1=\"%s\"", strings.ReplaceAll(e.string(), `"`, `\"`))
|
prompt := fmt.Sprintf("PS1=\"%s\"", strings.ReplaceAll(e.string(), `"`, `\"`))
|
||||||
prompt += fmt.Sprintf("\nRPROMPT=\"%s\"", e.rprompt)
|
prompt += fmt.Sprintf("\nRPROMPT=\"%s\"", e.rprompt)
|
||||||
return prompt
|
return prompt
|
||||||
case shell.PWSH, shell.PWSH5, shell.BASH, shell.PLAIN, shell.NU:
|
case shell.PWSH, shell.PWSH5, shell.PLAIN, shell.NU:
|
||||||
if e.rprompt == "" || !e.canWriteRPrompt() || e.Plain {
|
if !e.canWriteRPrompt() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
e.write(e.Ansi.SaveCursorPosition())
|
e.write(e.Ansi.SaveCursorPosition())
|
||||||
|
@ -222,6 +239,21 @@ func (e *Engine) print() string {
|
||||||
e.write(e.Ansi.GetCursorForRightWrite(e.rpromptLength, 0))
|
e.write(e.Ansi.GetCursorForRightWrite(e.rpromptLength, 0))
|
||||||
e.write(e.rprompt)
|
e.write(e.rprompt)
|
||||||
e.write(e.Ansi.RestoreCursorPosition())
|
e.write(e.Ansi.RestoreCursorPosition())
|
||||||
|
case shell.BASH:
|
||||||
|
if !e.canWriteRPrompt() {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// in bash, the entire rprompt needs to be escaped for the prompt to be interpreted correctly
|
||||||
|
// see https://github.com/JanDeDobbeleer/oh-my-posh/pull/2398
|
||||||
|
ansi := &color.Ansi{}
|
||||||
|
ansi.InitPlain()
|
||||||
|
prompt := ansi.SaveCursorPosition()
|
||||||
|
prompt += ansi.CarriageForward()
|
||||||
|
prompt += ansi.GetCursorForRightWrite(e.rpromptLength, 0)
|
||||||
|
prompt += e.rprompt
|
||||||
|
prompt += ansi.RestoreCursorPosition()
|
||||||
|
prompt = e.Ansi.FormatText(prompt)
|
||||||
|
e.write(prompt)
|
||||||
}
|
}
|
||||||
return e.string()
|
return e.string()
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,10 +34,11 @@ func TestCanWriteRPrompt(t *testing.T) {
|
||||||
env := new(mock.MockedEnvironment)
|
env := new(mock.MockedEnvironment)
|
||||||
env.On("TerminalWidth").Return(tc.TerminalWidth, tc.TerminalWidthError)
|
env.On("TerminalWidth").Return(tc.TerminalWidth, tc.TerminalWidthError)
|
||||||
engine := &Engine{
|
engine := &Engine{
|
||||||
Env: env,
|
Env: env,
|
||||||
|
rpromptLength: tc.RPromptLength,
|
||||||
|
currentLineLength: tc.PromptLength,
|
||||||
|
rprompt: "hello",
|
||||||
}
|
}
|
||||||
engine.rpromptLength = tc.RPromptLength
|
|
||||||
engine.currentLineLength = tc.PromptLength
|
|
||||||
got := engine.canWriteRPrompt()
|
got := engine.canWriteRPrompt()
|
||||||
assert.Equal(t, tc.Expected, got, tc.Case)
|
assert.Equal(t, tc.Expected, got, tc.Case)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue