mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2024-12-31 13:57:26 -08:00
222 lines
6.2 KiB
Go
222 lines
6.2 KiB
Go
package main
|
|
|
|
import (
|
|
"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
|
|
writer promptWriter
|
|
ansi *ansiUtils
|
|
activeSegment *Segment
|
|
previousActiveSegment *Segment
|
|
activeBackground string
|
|
activeForeground string
|
|
}
|
|
|
|
func (b *Block) init(env environmentInfo, writer promptWriter, ansi *ansiUtils) {
|
|
b.env = env
|
|
b.writer = writer
|
|
b.ansi = ansi
|
|
}
|
|
|
|
func (b *Block) initPlain(env environmentInfo, config *Config) {
|
|
b.ansi = &ansiUtils{}
|
|
b.ansi.init(plain)
|
|
b.writer = &AnsiWriter{
|
|
ansi: b.ansi,
|
|
terminalBackground: getConsoleBackgroundColor(env, config.TerminalBackground),
|
|
ansiColors: MakeColors(env, config),
|
|
}
|
|
b.env = env
|
|
}
|
|
|
|
func (b *Block) setActiveSegment(segment *Segment) {
|
|
b.activeSegment = segment
|
|
b.activeBackground = segment.background()
|
|
b.activeForeground = segment.foreground()
|
|
}
|
|
|
|
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()
|
|
for _, segment := range b.Segments {
|
|
go func(s *Segment) {
|
|
defer wg.Done()
|
|
s.setStringValue(b.env)
|
|
}(segment)
|
|
}
|
|
}
|
|
|
|
func (b *Block) renderSegments() string {
|
|
defer b.writer.reset()
|
|
for _, segment := range b.Segments {
|
|
if !segment.active {
|
|
continue
|
|
}
|
|
b.setActiveSegment(segment)
|
|
b.writer.setColors(b.activeBackground, b.activeForeground)
|
|
b.endPowerline()
|
|
b.renderSegmentText(segment.stringValue)
|
|
}
|
|
if b.previousActiveSegment != nil && b.previousActiveSegment.Style == Powerline {
|
|
b.writePowerLineSeparator(Transparent, b.previousActiveSegment.background(), true)
|
|
}
|
|
b.writer.clearParentColors()
|
|
return b.writer.string()
|
|
}
|
|
|
|
func (b *Block) endPowerline() {
|
|
if b.previousActiveSegment == nil || b.activeSegment == nil {
|
|
return
|
|
}
|
|
if b.activeSegment.Style != Powerline &&
|
|
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.writer.write(foreground, background, symbol)
|
|
return
|
|
}
|
|
b.writer.write(background, foreground, symbol)
|
|
}
|
|
|
|
func (b *Block) getPowerlineColor(foreground bool) string {
|
|
if b.previousActiveSegment == nil {
|
|
return Transparent
|
|
}
|
|
if b.previousActiveSegment.Style == Diamond && len(b.previousActiveSegment.TrailingDiamond) == 0 {
|
|
return b.previousActiveSegment.background()
|
|
}
|
|
if b.activeSegment.Style == Diamond && len(b.activeSegment.LeadingDiamond) == 0 {
|
|
return b.activeBackground
|
|
}
|
|
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
|
|
b.writer.setParentColors(b.activeBackground, b.activeForeground)
|
|
}
|
|
|
|
func (b *Block) renderPowerLineSegment(text string) {
|
|
b.writePowerLineSeparator(b.activeBackground, b.getPowerlineColor(true), false)
|
|
b.renderText(text)
|
|
}
|
|
|
|
func (b *Block) renderPlainSegment(text string) {
|
|
b.renderText(text)
|
|
}
|
|
|
|
func (b *Block) renderDiamondSegment(text string) {
|
|
b.writer.write(Transparent, b.activeBackground, b.activeSegment.LeadingDiamond)
|
|
b.renderText(text)
|
|
b.writer.write(Transparent, b.activeBackground, b.activeSegment.TrailingDiamond)
|
|
}
|
|
|
|
func (b *Block) renderText(text string) {
|
|
defaultValue := " "
|
|
b.writer.write(b.activeBackground, b.activeForeground, b.activeSegment.getValue(Prefix, defaultValue))
|
|
b.writer.write(b.activeBackground, b.activeForeground, text)
|
|
b.writer.write(b.activeBackground, b.activeForeground, b.activeSegment.getValue(Postfix, defaultValue))
|
|
}
|
|
|
|
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() {
|
|
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.setActiveSegment(segment)
|
|
b.renderSegmentText(segmentTiming.stringValue)
|
|
if b.activeSegment.Style == Powerline {
|
|
b.writePowerLineSeparator(Transparent, b.activeBackground, true)
|
|
}
|
|
segmentTiming.stringValue = b.writer.string()
|
|
b.writer.reset()
|
|
}
|
|
segmentTimings = append(segmentTimings, &segmentTiming)
|
|
}
|
|
return largestSegmentNameLength, segmentTimings
|
|
}
|