diff --git a/.vscode/launch.json b/.vscode/launch.json index a038b85d67cc..30669ff13f39 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -7,7 +7,7 @@ "request": "launch", "mode": "debug", "program": "${workspaceRoot}/src", - "args": ["--config=/Users/jan/.jandedobbeleer.omp.json"] + "args": ["--config=${workspaceRoot}/themes/jandedobbeleer.omp.json"] }, { "name": "Launch tests", diff --git a/docs/docs/configuration.md b/docs/docs/configuration.md index e4ea79d40789..b68d754cbd43 100644 --- a/docs/docs/configuration.md +++ b/docs/docs/configuration.md @@ -105,7 +105,8 @@ the current working directory is `/usr/home/omp` and the shell is `zsh`. Let's take a closer look at what defines a block. -- type: `prompt` | `rprompt` | `newline` +- type: `prompt` | `rprompt` +- newline: `boolean` - alignment: `left` | `right` - vertical_offset: `int` - horizontal_offset: `int` @@ -117,9 +118,11 @@ Tells the engine what to do with the block. There are three options: - `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`. +Supported on [ZSH][rprompt], Bash and Powershell. + +### Newline + +Start the block on a new line. Defaults to `false`. ### Alignment @@ -402,12 +405,10 @@ has to be enabled at the segment level. Hyperlink generation is disabled by defa } ] }, - { - "type": "newline" - }, { "type": "prompt", "alignment": "left", + "newline": true, "segments": [ { "type": "session", diff --git a/src/block.go b/src/block.go new file mode 100644 index 000000000000..efc08680ed88 --- /dev/null +++ b/src/block.go @@ -0,0 +1,192 @@ +package main + +import ( + "fmt" + "sync" + "time" +) + +// BlockType type of block +type BlockType string + +// BlockAlignment aligment of a Block +type BlockAlignment string + +const ( + // Prompt writes one or more Segments + Prompt BlockType = "prompt" + // LineBreak creates a line break in the prompt + LineBreak BlockType = "newline" + // RPrompt a right aligned prompt in ZSH and Powershell + RPrompt BlockType = "rprompt" + // Left aligns left + Left BlockAlignment = "left" + // Right aligns right + Right BlockAlignment = "right" +) + +// Block defines a part of the prompt with optional segments +type Block struct { + Type BlockType `config:"type"` + Alignment BlockAlignment `config:"alignment"` + HorizontalOffset int `config:"horizontal_offset"` + VerticalOffset int `config:"vertical_offset"` + Segments []*Segment `config:"segments"` + Newline bool `config:"newline"` + + env environmentInfo + color *AnsiColor + activeSegment *Segment + previousActiveSegment *Segment +} + +func (b *Block) init(env environmentInfo, color *AnsiColor) { + b.env = env + b.color = color +} + +func (b *Block) enabled() bool { + if b.Type == LineBreak { + return true + } + for _, segment := range b.Segments { + if segment.active { + return true + } + } + return false +} + +func (b *Block) setStringValues() { + wg := sync.WaitGroup{} + wg.Add(len(b.Segments)) + defer wg.Wait() + cwd := b.env.getcwd() + for _, segment := range b.Segments { + go func(s *Segment) { + defer wg.Done() + s.setStringValue(b.env, cwd) + }(segment) + } +} + +func (b *Block) renderSegments() string { + for _, segment := range b.Segments { + if !segment.active { + continue + } + b.activeSegment = segment + b.endPowerline() + b.renderSegmentText(segment.stringValue) + } + if b.previousActiveSegment != nil && b.previousActiveSegment.Style == Powerline { + b.writePowerLineSeparator(Transparent, b.previousActiveSegment.background(), true) + } + return b.color.string() +} + +func (b *Block) endPowerline() { + if b.activeSegment != nil && + b.activeSegment.Style != Powerline && + b.previousActiveSegment != nil && + b.previousActiveSegment.Style == Powerline { + b.writePowerLineSeparator(b.getPowerlineColor(false), b.previousActiveSegment.background(), true) + } +} + +func (b *Block) writePowerLineSeparator(background, foreground string, end bool) { + symbol := b.activeSegment.PowerlineSymbol + if end { + symbol = b.previousActiveSegment.PowerlineSymbol + } + if b.activeSegment.InvertPowerline { + b.color.write(foreground, background, symbol) + return + } + b.color.write(background, foreground, symbol) +} + +func (b *Block) getPowerlineColor(foreground bool) string { + if b.previousActiveSegment == nil { + return Transparent + } + if !foreground && b.activeSegment.Style != Powerline { + return Transparent + } + if foreground && b.previousActiveSegment.Style != Powerline { + return Transparent + } + return b.previousActiveSegment.background() +} + +func (b *Block) renderSegmentText(text string) { + switch b.activeSegment.Style { + case Plain: + b.renderPlainSegment(text) + case Diamond: + b.renderDiamondSegment(text) + case Powerline: + b.renderPowerLineSegment(text) + } + b.previousActiveSegment = b.activeSegment +} + +func (b *Block) renderPowerLineSegment(text string) { + b.writePowerLineSeparator(b.activeSegment.background(), b.getPowerlineColor(true), false) + b.renderText(text) +} + +func (b *Block) renderPlainSegment(text string) { + b.renderText(text) +} + +func (b *Block) renderDiamondSegment(text string) { + b.color.write(Transparent, b.activeSegment.background(), b.activeSegment.LeadingDiamond) + b.renderText(text) + b.color.write(Transparent, b.activeSegment.background(), b.activeSegment.TrailingDiamond) +} + +func (b *Block) renderText(text string) { + text = b.color.formats.generateHyperlink(text) + defaultValue := " " + prefix := b.activeSegment.getValue(Prefix, defaultValue) + postfix := b.activeSegment.getValue(Postfix, defaultValue) + b.color.write(b.activeSegment.background(), b.activeSegment.foreground(), fmt.Sprintf("%s%s%s", prefix, text, postfix)) +} + +func (b *Block) debug() (int, []*SegmentTiming) { + var segmentTimings []*SegmentTiming + largestSegmentNameLength := 0 + for _, segment := range b.Segments { + err := segment.mapSegmentWithWriter(b.env) + if err != nil || !segment.shouldIncludeFolder(b.env.getcwd()) { + continue + } + var segmentTiming SegmentTiming + segmentTiming.name = string(segment.Type) + segmentTiming.nameLength = len(segmentTiming.name) + if segmentTiming.nameLength > largestSegmentNameLength { + largestSegmentNameLength = segmentTiming.nameLength + } + // enabled() timing + start := time.Now() + segmentTiming.enabled = segment.enabled() + segmentTiming.enabledDuration = time.Since(start) + // string() timing + if segmentTiming.enabled { + start = time.Now() + segmentTiming.stringValue = segment.string() + segmentTiming.stringDuration = time.Since(start) + b.previousActiveSegment = nil + b.activeSegment = segment + b.renderSegmentText(segmentTiming.stringValue) + if b.activeSegment.Style == Powerline { + b.writePowerLineSeparator(Transparent, b.activeSegment.background(), true) + } + segmentTiming.stringValue = b.color.string() + b.color.builder.Reset() + } + segmentTimings = append(segmentTimings, &segmentTiming) + } + return largestSegmentNameLength, segmentTimings +} diff --git a/src/block_test.go b/src/block_test.go new file mode 100644 index 000000000000..863d8515a70b --- /dev/null +++ b/src/block_test.go @@ -0,0 +1,29 @@ +package main + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestBlockEnabled(t *testing.T) { + cases := []struct { + Case string + Expected bool + Segments []*Segment + Type BlockType + }{ + {Case: "line break block", Expected: true, Type: LineBreak}, + {Case: "prompt enabled", Expected: true, Type: Prompt, Segments: []*Segment{{active: true}}}, + {Case: "prompt disabled", Expected: false, Type: Prompt, Segments: []*Segment{{active: false}}}, + {Case: "prompt enabled multiple", Expected: true, Type: Prompt, Segments: []*Segment{{active: false}, {active: true}}}, + {Case: "rprompt enabled multiple", Expected: true, Type: RPrompt, Segments: []*Segment{{active: false}, {active: true}}}, + } + for _, tc := range cases { + block := &Block{ + Type: tc.Type, + Segments: tc.Segments, + } + assert.Equal(t, tc.Expected, block.enabled(), tc.Case) + } +} diff --git a/src/config.go b/src/config.go index a559ef303bb7..4fcd6576dcd6 100644 --- a/src/config.go +++ b/src/config.go @@ -28,36 +28,11 @@ type Config struct { Blocks []*Block `config:"blocks"` } -// BlockType type of block -type BlockType string - -// BlockAlignment aligment of a Block -type BlockAlignment string - const ( - // Prompt writes one or more Segments - Prompt BlockType = "prompt" - // LineBreak creates a line break in the prompt - LineBreak BlockType = "newline" - // RPrompt a right aligned prompt in ZSH and Powershell - RPrompt BlockType = "rprompt" - // Left aligns left - Left BlockAlignment = "left" - // Right aligns right - Right BlockAlignment = "right" // EnableHyperlink enable hyperlink EnableHyperlink Property = "enable_hyperlink" ) -// Block defines a part of the prompt with optional segments -type Block struct { - Type BlockType `config:"type"` - Alignment BlockAlignment `config:"alignment"` - HorizontalOffset int `config:"horizontal_offset"` - VerticalOffset int `config:"vertical_offset"` - Segments []*Segment `config:"segments"` -} - // GetConfig returns the default configuration including possible user overrides func GetConfig(env environmentInfo) *Config { cfg, err := loadConfig(env) diff --git a/src/engine.go b/src/engine.go index ff6f69f888ba..56ea8ae3684e 100644 --- a/src/engine.go +++ b/src/engine.go @@ -3,154 +3,24 @@ package main import ( "fmt" "strings" - "sync" "time" ) type engine struct { - config *Config - env environmentInfo - color *AnsiColor - renderer *AnsiRenderer - consoleTitle *consoleTitle - activeBlock *Block - activeSegment *Segment - previousActiveSegment *Segment - rprompt string -} - -// SegmentTiming holds the timing context for a segment -type SegmentTiming struct { - name string - nameLength int - enabled bool - stringValue string - enabledDuration time.Duration - stringDuration time.Duration -} - -func (e *engine) getPowerlineColor(foreground bool) string { - if e.previousActiveSegment == nil { - return Transparent - } - if !foreground && e.activeSegment.Style != Powerline { - return Transparent - } - if foreground && e.previousActiveSegment.Style != Powerline { - return Transparent - } - return e.previousActiveSegment.background() -} - -func (e *engine) writePowerLineSeparator(background, foreground string, end bool) { - symbol := e.activeSegment.PowerlineSymbol - if end { - symbol = e.previousActiveSegment.PowerlineSymbol - } - if e.activeSegment.InvertPowerline { - e.color.write(foreground, background, symbol) - return - } - e.color.write(background, foreground, symbol) -} - -func (e *engine) endPowerline() { - if e.activeSegment != nil && - e.activeSegment.Style != Powerline && - e.previousActiveSegment != nil && - e.previousActiveSegment.Style == Powerline { - e.writePowerLineSeparator(e.getPowerlineColor(false), e.previousActiveSegment.background(), true) - } -} - -func (e *engine) renderPowerLineSegment(text string) { - e.writePowerLineSeparator(e.activeSegment.background(), e.getPowerlineColor(true), false) - e.renderText(text) -} - -func (e *engine) renderPlainSegment(text string) { - e.renderText(text) -} - -func (e *engine) renderDiamondSegment(text string) { - e.color.write(Transparent, e.activeSegment.background(), e.activeSegment.LeadingDiamond) - e.renderText(text) - e.color.write(Transparent, e.activeSegment.background(), e.activeSegment.TrailingDiamond) -} - -func (e *engine) renderText(text string) { - text = e.color.formats.generateHyperlink(text) - defaultValue := " " - prefix := e.activeSegment.getValue(Prefix, defaultValue) - postfix := e.activeSegment.getValue(Postfix, defaultValue) - e.color.write(e.activeSegment.background(), e.activeSegment.foreground(), fmt.Sprintf("%s%s%s", prefix, text, postfix)) -} - -func (e *engine) renderSegmentText(text string) { - switch e.activeSegment.Style { - case Plain: - e.renderPlainSegment(text) - case Diamond: - e.renderDiamondSegment(text) - case Powerline: - e.renderPowerLineSegment(text) - } - e.previousActiveSegment = e.activeSegment -} - -func (e *engine) renderBlockSegments(block *Block) string { - defer e.resetBlock() - e.activeBlock = block - e.setStringValues(block.Segments) - for _, segment := range block.Segments { - if !segment.active { - continue - } - e.activeSegment = segment - e.endPowerline() - e.renderSegmentText(segment.stringValue) - } - if e.previousActiveSegment != nil && e.previousActiveSegment.Style == Powerline { - e.writePowerLineSeparator(Transparent, e.previousActiveSegment.background(), true) - } - return e.color.string() -} - -func (e *engine) setStringValues(segments []*Segment) { - wg := sync.WaitGroup{} - wg.Add(len(segments)) - defer wg.Wait() - cwd := e.env.getcwd() - for _, segment := range segments { - go func(s *Segment) { - defer wg.Done() - s.setStringValue(e.env, cwd) - }(segment) - } + config *Config + env environmentInfo + color *AnsiColor + renderer *AnsiRenderer + consoleTitle *consoleTitle + // activeBlock *Block + // activeSegment *Segment + // previousActiveSegment *Segment + rprompt string } func (e *engine) render() string { for _, block := range e.config.Blocks { - // if line break, append a line break - switch block.Type { - case LineBreak: - e.renderer.write("\n") - case Prompt: - if block.VerticalOffset != 0 { - e.renderer.changeLine(block.VerticalOffset) - } - switch block.Alignment { - case Right: - e.renderer.carriageForward() - blockText := e.renderBlockSegments(block) - e.renderer.setCursorForRightWrite(blockText, block.HorizontalOffset) - e.renderer.write(blockText) - case Left: - e.renderer.write(e.renderBlockSegments(block)) - } - case RPrompt: - e.rprompt = e.renderBlockSegments(block) - } + e.renderBlock(block) } if e.config.ConsoleTitle { e.renderer.write(e.consoleTitle.getConsoleTitle()) @@ -171,9 +41,43 @@ func (e *engine) render() string { return e.print() } +func (e *engine) renderBlock(block *Block) { + block.init(e.env, e.color) + block.setStringValues() + defer e.color.reset() + if !block.enabled() { + return + } + if block.Newline { + e.renderer.write("\n") + } + switch block.Type { + // This is deprecated but leave if to not break current configs + // It is encouraged to used "newline": true on block level + // rather than the standalone the linebreak block + case LineBreak: + e.renderer.write("\n") + case Prompt: + if block.VerticalOffset != 0 { + e.renderer.changeLine(block.VerticalOffset) + } + switch block.Alignment { + case Right: + e.renderer.carriageForward() + blockText := block.renderSegments() + e.renderer.setCursorForRightWrite(blockText, block.HorizontalOffset) + e.renderer.write(blockText) + case Left: + e.renderer.write(block.renderSegments()) + } + case RPrompt: + e.rprompt = block.renderSegments() + } +} + // debug will loop through your config file and output the timings for each segments func (e *engine) debug() string { - var segmentTimings []SegmentTiming + var segmentTimings []*SegmentTiming largestSegmentNameLength := 0 e.renderer.write("\n\x1b[1mHere are the timings of segments in your prompt:\x1b[0m\n\n") @@ -181,7 +85,7 @@ func (e *engine) debug() string { start := time.Now() consoleTitle := e.consoleTitle.getTemplateText() duration := time.Since(start) - segmentTiming := SegmentTiming{ + segmentTiming := &SegmentTiming{ name: "ConsoleTitle", nameLength: 12, enabled: e.config.ConsoleTitle, @@ -192,36 +96,11 @@ func (e *engine) debug() string { segmentTimings = append(segmentTimings, segmentTiming) // loop each segments of each blocks for _, block := range e.config.Blocks { - for _, segment := range block.Segments { - err := segment.mapSegmentWithWriter(e.env) - if err != nil || !segment.shouldIncludeFolder(e.env.getcwd()) { - continue - } - var segmentTiming SegmentTiming - segmentTiming.name = string(segment.Type) - segmentTiming.nameLength = len(segmentTiming.name) - if segmentTiming.nameLength > largestSegmentNameLength { - largestSegmentNameLength = segmentTiming.nameLength - } - // enabled() timing - start := time.Now() - segmentTiming.enabled = segment.enabled() - segmentTiming.enabledDuration = time.Since(start) - // string() timing - if segmentTiming.enabled { - start = time.Now() - segmentTiming.stringValue = segment.string() - segmentTiming.stringDuration = time.Since(start) - e.previousActiveSegment = nil - e.activeSegment = segment - e.renderSegmentText(segmentTiming.stringValue) - if e.activeSegment.Style == Powerline { - e.writePowerLineSeparator(Transparent, e.activeSegment.background(), true) - } - segmentTiming.stringValue = e.color.string() - e.color.builder.Reset() - } - segmentTimings = append(segmentTimings, segmentTiming) + block.init(e.env, e.color) + longestSegmentName, timings := block.debug() + segmentTimings = append(segmentTimings, timings...) + if longestSegmentName > largestSegmentNameLength { + largestSegmentNameLength = longestSegmentName } } @@ -258,9 +137,3 @@ func (e *engine) print() string { } return e.renderer.string() } - -func (e *engine) resetBlock() { - e.color.reset() - e.previousActiveSegment = nil - e.activeBlock = nil -} diff --git a/src/segment.go b/src/segment.go index c50e901846ea..4e0d5c04efe2 100644 --- a/src/segment.go +++ b/src/segment.go @@ -3,6 +3,7 @@ package main import ( "errors" "fmt" + "time" ) // Segment represent a single segment and it's configuration @@ -24,6 +25,16 @@ type Segment struct { active bool } +// SegmentTiming holds the timing context for a segment +type SegmentTiming struct { + name string + nameLength int + enabled bool + stringValue string + enabledDuration time.Duration + stringDuration time.Duration +} + // SegmentWriter is the interface used to define what and if to write to the prompt type SegmentWriter interface { enabled() bool diff --git a/themes/agnosterplus.omp.json b/themes/agnosterplus.omp.json index 210f4152b686..97488a009828 100644 --- a/themes/agnosterplus.omp.json +++ b/themes/agnosterplus.omp.json @@ -16,12 +16,10 @@ } ] }, - { - "type": "newline" - }, { "type": "prompt", "alignment": "left", + "newline": true, "segments": [ { "type": "session", diff --git a/themes/avit.omp.json b/themes/avit.omp.json index 710a81f0d3a2..ad7a60e13660 100644 --- a/themes/avit.omp.json +++ b/themes/avit.omp.json @@ -34,12 +34,10 @@ } ] }, - { - "type": "newline" - }, { "type": "prompt", "alignment": "left", + "newline": true, "segments": [ { "type": "text", diff --git a/themes/blueish.omp.json b/themes/blueish.omp.json index 5845b8812c0e..3adde2640633 100644 --- a/themes/blueish.omp.json +++ b/themes/blueish.omp.json @@ -107,11 +107,9 @@ ] }, { - "type": "newline" - }, - { "type": "prompt", "alignment": "left", + "newline": true, "segments": [ { "type": "text", diff --git a/themes/bubbles.omp.json b/themes/bubbles.omp.json index 8fcad407b650..47660bea52ec 100644 --- a/themes/bubbles.omp.json +++ b/themes/bubbles.omp.json @@ -146,12 +146,10 @@ } ] }, - { - "type": "newline" - }, { "type": "prompt", "alignment": "left", + "newline": true, "segments": [ { "type": "executiontime", diff --git a/themes/bubblesline.omp.json b/themes/bubblesline.omp.json index 44265d7abcc8..61efb00f2803 100644 --- a/themes/bubblesline.omp.json +++ b/themes/bubblesline.omp.json @@ -133,12 +133,10 @@ } ] }, - { - "type": "newline" - }, { "type": "prompt", "alignment": "left", + "newline": true, "segments": [ { "type": "session", diff --git a/themes/cinnamon.omp.json b/themes/cinnamon.omp.json index 52d1bbf304c0..56ae76a64881 100644 --- a/themes/cinnamon.omp.json +++ b/themes/cinnamon.omp.json @@ -38,12 +38,10 @@ } ] }, - { - "type": "newline" - }, { "type": "prompt", "alignment": "left", + "newline": true, "segments": [ { "type": "text", diff --git a/themes/darkblood.omp.json b/themes/darkblood.omp.json index 39b9a2f08c33..f452ec4efada 100644 --- a/themes/darkblood.omp.json +++ b/themes/darkblood.omp.json @@ -45,12 +45,10 @@ } ] }, - { - "type": "newline" - }, { "type": "prompt", "alignment": "left", + "newline": true, "segments": [ { "type": "path", diff --git a/themes/honukai.omp.json b/themes/honukai.omp.json index 62cd8496e67c..15ec2cf87018 100644 --- a/themes/honukai.omp.json +++ b/themes/honukai.omp.json @@ -51,12 +51,10 @@ } ] }, - { - "type": "newline" - }, { "type": "prompt", "alignment": "left", + "newline": true, "segments": [ { "type": "root", diff --git a/themes/huvix.omp.json b/themes/huvix.omp.json index e6c88e6ae61a..e0d1a1632d1c 100644 --- a/themes/huvix.omp.json +++ b/themes/huvix.omp.json @@ -39,7 +39,7 @@ "foreground": "#9e7eff", "properties": { "prefix": "\u0028\uE235 ", - "postfix": "\u0029 " + "postfix": "\u0029 " } }, { @@ -67,12 +67,10 @@ } ] }, - { - "type": "newline" - }, { "type": "prompt", "alignment": "left", + "newline": true, "segments": [ { "type": "battery", @@ -97,4 +95,4 @@ ], "final_space": true } - + diff --git a/themes/jonnychipz.omp.json b/themes/jonnychipz.omp.json index 6ef5f2c8a8eb..ec80839274b2 100644 --- a/themes/jonnychipz.omp.json +++ b/themes/jonnychipz.omp.json @@ -20,7 +20,7 @@ "postfix": "", "prefix": "" } - }, + }, { "type": "session", "style": "diamond", @@ -42,7 +42,7 @@ "prefix": " \uFD03 " } }, - + { "type": "exit", "style": "diamond", @@ -60,13 +60,11 @@ } ] }, - { - "type": "newline" - }, { "type": "prompt", "alignment": "left", - "segments": [ + "newline": true, + "segments": [ { "type": "os", "style": "diamond", @@ -94,7 +92,7 @@ "postfix": "<#000000> \ue0b1" } }, - + { "type": "root", "style": "diamond", @@ -174,4 +172,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/themes/microverse-power.omp.json b/themes/microverse-power.omp.json index 4aca65f33b5a..748b924167a6 100644 --- a/themes/microverse-power.omp.json +++ b/themes/microverse-power.omp.json @@ -86,12 +86,10 @@ } ] }, - { - "type": "newline" - }, { "type": "prompt", "alignment": "left", + "newline": true, "segments": [ { "type": "text", diff --git a/themes/negligible.omp.json b/themes/negligible.omp.json index c5e192f7d9cd..88331b388cc3 100644 --- a/themes/negligible.omp.json +++ b/themes/negligible.omp.json @@ -56,12 +56,10 @@ } ] }, - { - "type": "newline" - }, { "type": "prompt", "alignment": "left", + "newline": true, "segments": [ { "type": "exit", diff --git a/themes/paradox.omp.json b/themes/paradox.omp.json index 48c2263a1865..153e0611ae22 100644 --- a/themes/paradox.omp.json +++ b/themes/paradox.omp.json @@ -60,12 +60,10 @@ } ] }, - { - "type": "newline" - }, { "type": "prompt", "alignment": "left", + "newline": true, "segments": [ { "type": "text", diff --git a/themes/pararussel.omp.json b/themes/pararussel.omp.json index 1bf35f4b0d5b..e05755ac67d6 100644 --- a/themes/pararussel.omp.json +++ b/themes/pararussel.omp.json @@ -60,12 +60,10 @@ } ] }, - { - "type": "newline" - }, { "type": "prompt", "alignment": "left", + "newline": true, "segments": [ { "type": "text", diff --git a/themes/pixelrobots.omp.json b/themes/pixelrobots.omp.json index 823e47a2e389..6330a7cdd348 100644 --- a/themes/pixelrobots.omp.json +++ b/themes/pixelrobots.omp.json @@ -22,38 +22,36 @@ } }, { - "type": "kubectl", - "style": "powerline", - "powerline_symbol": "", - "foreground": "#000000", - "background": "#ffea00", - "properties": { - "prefix": " \uFD31", - "template": " {{.Context}}{{if .Namespace}} :: {{.Namespace}}{{end}}" - } - }, - { - "type": "az", - "style": "powerline", - "powerline_symbol": "\uE0B0", - "foreground": "#000000", - "background": "#008AD7", - "properties": { - "display_id": false, - "display_name": true, - "info_separator": " @ ", - "prefix": " \uFD03 " - } - } - ] + "type": "kubectl", + "style": "powerline", + "powerline_symbol": "", + "foreground": "#000000", + "background": "#ffea00", + "properties": { + "prefix": " \uFD31", + "template": " {{.Context}}{{if .Namespace}} :: {{.Namespace}}{{end}}" + } + }, + { + "type": "az", + "style": "powerline", + "powerline_symbol": "\uE0B0", + "foreground": "#000000", + "background": "#008AD7", + "properties": { + "display_id": false, + "display_name": true, + "info_separator": " @ ", + "prefix": " \uFD03 " + } + } + ] }, - { - "type": "newline" - }, - { - "type": "prompt", - "alignment": "left", - "segments": [ + { + "type": "prompt", + "alignment": "left", + "newline": true, + "segments": [ { "type": "os", "style": "diamond", @@ -167,4 +165,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/themes/powerlevel10k_classic.omp.json b/themes/powerlevel10k_classic.omp.json index 6348f71cb46d..16e303b3b62d 100644 --- a/themes/powerlevel10k_classic.omp.json +++ b/themes/powerlevel10k_classic.omp.json @@ -78,12 +78,10 @@ } ] }, - { - "type": "newline" - }, { "type": "prompt", "alignment": "left", + "newline": true, "segments": [ { "type": "exit", diff --git a/themes/powerlevel10k_lean.omp.json b/themes/powerlevel10k_lean.omp.json index 774f3bae9047..0c959866c497 100644 --- a/themes/powerlevel10k_lean.omp.json +++ b/themes/powerlevel10k_lean.omp.json @@ -16,12 +16,10 @@ } ] }, - { - "type": "newline" - }, { "type": "prompt", "alignment": "left", + "newline": true, "segments": [ { "type": "path", diff --git a/themes/pure.omp.json b/themes/pure.omp.json index 7117e63ad422..dacec272be60 100644 --- a/themes/pure.omp.json +++ b/themes/pure.omp.json @@ -4,12 +4,10 @@ "console_title_style": "template", "console_title_template": "{{if .Root}}(Admin){{end}} {{.Path}}", "blocks": [ - { - "type": "newline" - }, { "type": "prompt", "alignment": "left", + "newline": true, "segments": [ { "type": "root", @@ -69,11 +67,9 @@ ] }, { - "type": "newline" - }, - { - "alignment": "left", "type": "prompt", + "alignment": "left", + "newline": true, "segments": [ { "type": "exit", diff --git a/themes/schema.json b/themes/schema.json index de4357e46641..34c75898094f 100644 --- a/themes/schema.json +++ b/themes/schema.json @@ -50,17 +50,6 @@ "type": "object", "description": "https://ohmyposh.dev/docs/configure#block", "allOf": [ - { - "if": { - "properties": { - "type": { "const": "newline" } - } - }, - "then": { - "required": ["type"], - "title": "Newline, renders a line break" - } - }, { "if": { "properties": { @@ -89,7 +78,7 @@ "type": "string", "title": "Block type", "description": "https://ohmyposh.dev/docs/configure#type", - "enum": ["prompt", "rprompt", "newline"], + "enum": ["prompt", "rprompt"], "default": "prompt" }, "alignment": { @@ -99,6 +88,12 @@ "enum": ["left", "right"], "default": "left" }, + "newline": { + "type": "boolean", + "title": "Newline", + "description": "https://ohmyposh.dev/docs/configure#newline", + "default": false + }, "vertical_offset": { "type": "integer", "title": "Block vertical offset", diff --git a/themes/slim.omp.json b/themes/slim.omp.json index c550ef94f835..f9ceb6cfcac9 100644 --- a/themes/slim.omp.json +++ b/themes/slim.omp.json @@ -165,12 +165,10 @@ } ] }, - { - "type": "newline" - }, { "type": "prompt", "alignment": "left", + "newline": true, "segments": [ { "type": "text", diff --git a/themes/slimfat.omp.json b/themes/slimfat.omp.json index a3fdaf292063..0ad306933075 100644 --- a/themes/slimfat.omp.json +++ b/themes/slimfat.omp.json @@ -163,12 +163,10 @@ } ] }, - { - "type": "newline" - }, { "type": "prompt", "alignment": "left", + "newline": true, "segments": [ { "type": "text", diff --git a/themes/star.omp.json b/themes/star.omp.json index 209a3db34331..fb7751a78714 100644 --- a/themes/star.omp.json +++ b/themes/star.omp.json @@ -53,12 +53,10 @@ } ] }, - { - "type": "newline" - }, { "type": "prompt", "alignment": "left", + "newline": true, "segments": [ { "type": "text", diff --git a/themes/stelbent.minimal.omp.json b/themes/stelbent.minimal.omp.json index b7c2fae8df15..be3e8bfcc468 100644 --- a/themes/stelbent.minimal.omp.json +++ b/themes/stelbent.minimal.omp.json @@ -37,12 +37,10 @@ } ] }, - { - "type": "newline" - }, { "type": "prompt", "alignment": "left", + "newline": true, "segments": [ { "type": "session", @@ -117,12 +115,10 @@ } ] }, - { - "type": "newline" - }, { "type": "prompt", "alignment": "left", + "newline": true, "segments": [ { "type": "text", diff --git a/themes/ys.omp.json b/themes/ys.omp.json index 75267131b4f6..d9ae5e07c081 100644 --- a/themes/ys.omp.json +++ b/themes/ys.omp.json @@ -17,12 +17,10 @@ } ] }, - { - "type": "newline" - }, { "type": "prompt", "alignment": "left", + "newline": true, "segments": [ { "type": "text", @@ -87,12 +85,10 @@ } ] }, - { - "type": "newline" - }, { "type": "prompt", "alignment": "left", + "newline": true, "segments": [ { "type": "text",