feat: powershell rprompt support

This commit is contained in:
TravisTX 2020-12-15 06:58:15 -07:00 committed by Jan De Dobbeleer
parent 3ca2cb5ef3
commit 85b1fc2662
6 changed files with 49 additions and 16 deletions

3
.gitignore vendored
View file

@ -145,3 +145,6 @@ dist
.history .history
# End of https://www.toptal.com/developers/gitignore/api/node,go,visualstudiocode # End of https://www.toptal.com/developers/gitignore/api/node,go,visualstudiocode
# linux binary
/oh-my-posh3

View file

@ -30,12 +30,14 @@ func lenWithoutANSI(text, shell string) int {
} }
type formats struct { type formats struct {
linechange string linechange string
left string left string
right string right string
title string title string
creset string creset string
clearOEL string clearOEL string
saveCursorPosition string
restoreCursorPosition string
} }
// AnsiRenderer exposes functionality using ANSI // AnsiRenderer exposes functionality using ANSI
@ -46,8 +48,10 @@ type AnsiRenderer struct {
} }
const ( const (
zsh = "zsh" zsh = "zsh"
bash = "bash" bash = "bash"
pwsh = "pwsh"
powershell5 = "powershell"
) )
func (r *AnsiRenderer) init(shell string) { func (r *AnsiRenderer) init(shell string) {
@ -61,6 +65,8 @@ func (r *AnsiRenderer) init(shell string) {
r.formats.title = "%%{\033]0;%s\007%%}" r.formats.title = "%%{\033]0;%s\007%%}"
r.formats.creset = "%{\x1b[0m%}" r.formats.creset = "%{\x1b[0m%}"
r.formats.clearOEL = "%{\x1b[K%}" r.formats.clearOEL = "%{\x1b[K%}"
r.formats.saveCursorPosition = "%{\x1b7%}"
r.formats.restoreCursorPosition = "%{\x1b8%}"
case bash: case bash:
r.formats.linechange = "\\[\x1b[%d%s\\]" r.formats.linechange = "\\[\x1b[%d%s\\]"
r.formats.left = "\\[\x1b[%dC\\]" r.formats.left = "\\[\x1b[%dC\\]"
@ -68,6 +74,8 @@ func (r *AnsiRenderer) init(shell string) {
r.formats.title = "\\[\033]0;%s\007\\]" r.formats.title = "\\[\033]0;%s\007\\]"
r.formats.creset = "\\[\x1b[0m\\]" r.formats.creset = "\\[\x1b[0m\\]"
r.formats.clearOEL = "\\[\x1b[K\\]" r.formats.clearOEL = "\\[\x1b[K\\]"
r.formats.saveCursorPosition = "\\[\x1b7\\]"
r.formats.restoreCursorPosition = "\\[\x1b8\\]"
default: default:
r.formats.linechange = "\x1b[%d%s" r.formats.linechange = "\x1b[%d%s"
r.formats.left = "\x1b[%dC" r.formats.left = "\x1b[%dC"
@ -75,6 +83,8 @@ func (r *AnsiRenderer) init(shell string) {
r.formats.title = "\033]0;%s\007" r.formats.title = "\033]0;%s\007"
r.formats.creset = "\x1b[0m" r.formats.creset = "\x1b[0m"
r.formats.clearOEL = "\x1b[K" r.formats.clearOEL = "\x1b[K"
r.formats.saveCursorPosition = "\x1b7"
r.formats.restoreCursorPosition = "\x1b8"
} }
} }
@ -116,3 +126,11 @@ func (r *AnsiRenderer) clearEOL() {
func (r *AnsiRenderer) string() string { func (r *AnsiRenderer) string() string {
return r.buffer.String() return r.buffer.String()
} }
func (r *AnsiRenderer) saveCursorPosition() {
r.buffer.WriteString(r.formats.saveCursorPosition)
}
func (r *AnsiRenderer) restoreCursorPosition() {
r.buffer.WriteString(r.formats.restoreCursorPosition)
}

View file

@ -67,7 +67,7 @@ boxes with question marks, [set up your terminal][setupterm] to use a supported
Let's take a closer look at what defines a block. Let's take a closer look at what defines a block.
- type: `prompt` | `newline` | `rprompt` - type: `prompt` | `rprompt` | `newline`
- alignment: `left` | `right` - alignment: `left` | `right`
- vertical_offset: `int` - vertical_offset: `int`
- horizontal_offset: `int` - horizontal_offset: `int`
@ -75,9 +75,13 @@ Let's take a closer look at what defines a block.
### Type ### Type
Tells the engine what to do with the block. There are three options, either it renders one or more segments, Tells the engine what to do with the block. There are three options:
inserts a newline to start the next block on a new line or sets a block as the `RPROMPT` when on [ZSH][rprompt].
New line blocks require no additional configuration other than the `type`. - `prompt` renders one or more segments
- `rprompt` renders one or more segments aligned to the right of the cursor. Only one `rprompt` block is permitted.
Supported on [ZSH][rprompt] and Powershell.
- `newline` inserts a new line to start the next block on a new line. `newline` blocks require no additional
configuration other than the `type`.
### Alignment ### Alignment

View file

@ -168,11 +168,19 @@ func (e *engine) render() {
func (e *engine) write() { func (e *engine) write() {
if *e.env.getArgs().Eval { if *e.env.getArgs().Eval {
fmt.Printf("PS1=\"%s\"", e.renderer.string()) fmt.Printf("PS1=\"%s\"", e.renderer.string())
if e.rprompt != "" && e.env.getShellName() == zsh { if e.env.getShellName() == zsh {
fmt.Printf("\nRPROMPT=\"%s\"", e.rprompt) fmt.Printf("\nRPROMPT=\"%s\"", e.rprompt)
} }
return return
} }
if e.rprompt != "" && (e.env.getShellName() == pwsh || e.env.getShellName() == powershell5) {
e.renderer.saveCursorPosition()
e.renderer.carriageForward()
e.renderer.setCursorForRightWrite(e.rprompt, 0)
e.renderer.print(e.rprompt)
e.renderer.restoreCursorPosition()
}
fmt.Print(e.renderer.string()) fmt.Print(e.renderer.string())
} }

View file

@ -28,7 +28,7 @@ const (
Prompt BlockType = "prompt" Prompt BlockType = "prompt"
// LineBreak creates a line break in the prompt // LineBreak creates a line break in the prompt
LineBreak BlockType = "newline" LineBreak BlockType = "newline"
// RPrompt a right aligned prompt in ZSH // RPrompt a right aligned prompt in ZSH and Powershell
RPrompt BlockType = "rprompt" RPrompt BlockType = "rprompt"
// Left aligns left // Left aligns left
Left BlockAlignment = "left" Left BlockAlignment = "left"

View file

@ -51,7 +51,7 @@
}, },
"then": { "then": {
"required": ["type", "segments"], "required": ["type", "segments"],
"title": "RPrompt definition, contains 1 or more segments to render in ZSH RPROMPT" "title": "RPrompt definition, contains 1 or more segments to render to the right of the cursor"
} }
} }
], ],
@ -60,7 +60,7 @@
"type": "string", "type": "string",
"title": "Block type", "title": "Block type",
"description": "https://ohmyposh.dev/docs/configure#type", "description": "https://ohmyposh.dev/docs/configure#type",
"enum": ["prompt", "newline", "rprompt"], "enum": ["prompt", "rprompt", "newline"],
"default": "prompt" "default": "prompt"
}, },
"alignment": { "alignment": {