mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2025-03-05 20:49:04 -08:00
parent
d6b56de4c1
commit
f403db826f
|
@ -14,6 +14,9 @@ type BlockType string
|
||||||
// BlockAlignment aligment of a Block
|
// BlockAlignment aligment of a Block
|
||||||
type BlockAlignment string
|
type BlockAlignment string
|
||||||
|
|
||||||
|
// Overflow defines how to handle a right block that overflows with the previous block
|
||||||
|
type Overflow string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Prompt writes one or more Segments
|
// Prompt writes one or more Segments
|
||||||
Prompt BlockType = "prompt"
|
Prompt BlockType = "prompt"
|
||||||
|
@ -25,6 +28,10 @@ const (
|
||||||
Left BlockAlignment = "left"
|
Left BlockAlignment = "left"
|
||||||
// Right aligns right
|
// Right aligns right
|
||||||
Right BlockAlignment = "right"
|
Right BlockAlignment = "right"
|
||||||
|
// Break adds a line break
|
||||||
|
Break Overflow = "break"
|
||||||
|
// Hide hides the block
|
||||||
|
Hide Overflow = "hide"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Block defines a part of the prompt with optional segments
|
// Block defines a part of the prompt with optional segments
|
||||||
|
@ -36,6 +43,7 @@ type Block struct {
|
||||||
Segments []*Segment `json:"segments,omitempty"`
|
Segments []*Segment `json:"segments,omitempty"`
|
||||||
Newline bool `json:"newline,omitempty"`
|
Newline bool `json:"newline,omitempty"`
|
||||||
Filler string `json:"filler,omitempty"`
|
Filler string `json:"filler,omitempty"`
|
||||||
|
Overflow Overflow `json:"overflow,omitempty"`
|
||||||
|
|
||||||
env environment.Environment
|
env environment.Environment
|
||||||
writer color.Writer
|
writer color.Writer
|
||||||
|
|
|
@ -40,8 +40,8 @@ func (e *Engine) string() string {
|
||||||
return e.console.String()
|
return e.console.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Engine) canWriteRPrompt() bool {
|
func (e *Engine) canWriteRPrompt(rprompt bool) bool {
|
||||||
if e.rprompt == "" || e.Plain {
|
if rprompt && (e.rprompt == "" || e.Plain) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
consoleWidth, err := e.Env.TerminalWidth()
|
consoleWidth, err := e.Env.TerminalWidth()
|
||||||
|
@ -55,7 +55,10 @@ func (e *Engine) canWriteRPrompt() bool {
|
||||||
overflow := promptWidth % consoleWidth
|
overflow := promptWidth % consoleWidth
|
||||||
availableSpace = consoleWidth - overflow
|
availableSpace = consoleWidth - overflow
|
||||||
}
|
}
|
||||||
promptBreathingRoom := 30
|
promptBreathingRoom := 5
|
||||||
|
if rprompt {
|
||||||
|
promptBreathingRoom = 30
|
||||||
|
}
|
||||||
canWrite := (availableSpace - e.rpromptLength) >= promptBreathingRoom
|
canWrite := (availableSpace - e.rpromptLength) >= promptBreathingRoom
|
||||||
return canWrite
|
return canWrite
|
||||||
}
|
}
|
||||||
|
@ -107,6 +110,15 @@ func (e *Engine) shouldFill(block *Block, length int) (string, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Engine) renderBlock(block *Block) {
|
func (e *Engine) renderBlock(block *Block) {
|
||||||
|
defer func() {
|
||||||
|
// 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
|
||||||
|
// color of the line above the new input line. Clearing the line fixes this,
|
||||||
|
// but can hopefully one day be removed when this is resolved natively.
|
||||||
|
if e.Env.Shell() == shell.PWSH || e.Env.Shell() == shell.PWSH5 {
|
||||||
|
e.writeANSI(e.Ansi.ClearAfter())
|
||||||
|
}
|
||||||
|
}()
|
||||||
// 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 e.Env.Shell() == shell.BASH && (block.Type == RPrompt || block.Alignment == Right) {
|
if e.Env.Shell() == shell.BASH && (block.Type == RPrompt || block.Alignment == Right) {
|
||||||
|
@ -135,20 +147,34 @@ func (e *Engine) renderBlock(block *Block) {
|
||||||
text, length := block.RenderSegments()
|
text, length := block.RenderSegments()
|
||||||
e.currentLineLength += length
|
e.currentLineLength += length
|
||||||
e.write(text)
|
e.write(text)
|
||||||
break
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if block.Alignment != Right {
|
if block.Alignment != Right {
|
||||||
break
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
text, length := block.RenderSegments()
|
text, length := block.RenderSegments()
|
||||||
padText, hasPadText := e.shouldFill(block, length)
|
e.rpromptLength = length
|
||||||
if hasPadText {
|
|
||||||
|
if !e.canWriteRPrompt(false) {
|
||||||
|
switch block.Overflow {
|
||||||
|
case Break:
|
||||||
|
e.newline()
|
||||||
|
case Hide:
|
||||||
|
// make sure to fill if needed
|
||||||
|
if padText, OK := e.shouldFill(block, 0); OK {
|
||||||
|
e.write(padText)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if padText, OK := e.shouldFill(block, length); OK {
|
||||||
// in this case we can print plain
|
// in this case we can print plain
|
||||||
e.write(padText)
|
e.write(padText)
|
||||||
e.write(text)
|
e.write(text)
|
||||||
break
|
return
|
||||||
}
|
}
|
||||||
// this can contain ANSI escape sequences
|
// this can contain ANSI escape sequences
|
||||||
ansi := e.Ansi
|
ansi := e.Ansi
|
||||||
|
@ -167,13 +193,6 @@ func (e *Engine) renderBlock(block *Block) {
|
||||||
case RPrompt:
|
case RPrompt:
|
||||||
e.rprompt, e.rpromptLength = block.RenderSegments()
|
e.rprompt, e.rpromptLength = block.RenderSegments()
|
||||||
}
|
}
|
||||||
// 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
|
|
||||||
// color of the line above the new input line. Clearing the line fixes this,
|
|
||||||
// but can hopefully one day be removed when this is resolved natively.
|
|
||||||
if e.Env.Shell() == shell.PWSH || e.Env.Shell() == shell.PWSH5 {
|
|
||||||
e.writeANSI(e.Ansi.ClearAfter())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// debug will loop through your config file and output the timings for each segments
|
// debug will loop through your config file and output the timings for each segments
|
||||||
|
@ -231,7 +250,7 @@ func (e *Engine) print() 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.PLAIN, shell.NU:
|
case shell.PWSH, shell.PWSH5, shell.PLAIN, shell.NU:
|
||||||
if !e.canWriteRPrompt() {
|
if !e.canWriteRPrompt(true) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
e.write(e.Ansi.SaveCursorPosition())
|
e.write(e.Ansi.SaveCursorPosition())
|
||||||
|
@ -240,7 +259,7 @@ func (e *Engine) print() string {
|
||||||
e.write(e.rprompt)
|
e.write(e.rprompt)
|
||||||
e.write(e.Ansi.RestoreCursorPosition())
|
e.write(e.Ansi.RestoreCursorPosition())
|
||||||
case shell.BASH:
|
case shell.BASH:
|
||||||
if !e.canWriteRPrompt() {
|
if !e.canWriteRPrompt(true) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// in bash, the entire rprompt needs to be escaped for the prompt to be interpreted correctly
|
// in bash, the entire rprompt needs to be escaped for the prompt to be interpreted correctly
|
||||||
|
|
|
@ -39,7 +39,7 @@ func TestCanWriteRPrompt(t *testing.T) {
|
||||||
currentLineLength: tc.PromptLength,
|
currentLineLength: tc.PromptLength,
|
||||||
rprompt: "hello",
|
rprompt: "hello",
|
||||||
}
|
}
|
||||||
got := engine.canWriteRPrompt()
|
got := engine.canWriteRPrompt(true)
|
||||||
assert.Equal(t, tc.Expected, got, tc.Case)
|
assert.Equal(t, tc.Expected, got, tc.Case)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,6 +125,29 @@
|
||||||
"required": ["type", "segments"],
|
"required": ["type", "segments"],
|
||||||
"title": "RPrompt definition, contains 1 or more segments to render to the right of the cursor"
|
"title": "RPrompt definition, contains 1 or more segments to render to the right of the cursor"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"const": "prompt"
|
||||||
|
},
|
||||||
|
"alignment": {
|
||||||
|
"const": "right"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"title": "Block overflow",
|
||||||
|
"description": "https://ohmyposh.dev/docs/configuration/block#overflow",
|
||||||
|
"enum": ["break", "hide"],
|
||||||
|
"default": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
@ -71,6 +71,7 @@ segments = [
|
||||||
- newline: `boolean`
|
- newline: `boolean`
|
||||||
- alignment: `left` | `right`
|
- alignment: `left` | `right`
|
||||||
- filler: `string`
|
- filler: `string`
|
||||||
|
- overflow: `break` | `hide`
|
||||||
- segments: `array` of one or more `segments`
|
- segments: `array` of one or more `segments`
|
||||||
|
|
||||||
### Type
|
### Type
|
||||||
|
@ -100,6 +101,11 @@ to be repeated to this property. Add this property to the _right_ aligned block.
|
||||||
"filler": "."
|
"filler": "."
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Overflow
|
||||||
|
|
||||||
|
When the right aligned block is so long it will overflow the left aligned block, the engine will either
|
||||||
|
break the block or hide it based on the setting. By default it is printed as is on the same line.
|
||||||
|
|
||||||
### Segments
|
### Segments
|
||||||
|
|
||||||
Array of one or more segments.
|
Array of one or more segments.
|
||||||
|
|
Loading…
Reference in a new issue