oh-my-posh/src/block.go

206 lines
5.8 KiB
Go
Raw Normal View History

package main
import (
2022-01-26 04:09:21 -08:00
"oh-my-posh/color"
"oh-my-posh/environment"
"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 environment.Environment
2022-01-26 04:09:21 -08:00
writer color.Writer
ansi *color.Ansi
activeSegment *Segment
previousActiveSegment *Segment
activeBackground string
activeForeground string
}
2022-01-26 04:09:21 -08:00
func (b *Block) init(env environment.Environment, writer color.Writer, ansi *color.Ansi) {
b.env = env
2021-04-20 12:30:46 -07:00
b.writer = writer
b.ansi = ansi
}
func (b *Block) initPlain(env environment.Environment, config *Config) {
2022-01-26 04:09:21 -08:00
b.ansi = &color.Ansi{}
b.ansi.Init(plain)
b.writer = &color.AnsiWriter{
Ansi: b.ansi,
TerminalBackground: getConsoleBackgroundColor(env, config.TerminalBackground),
AnsiColors: config.MakeColors(env),
}
b.env = env
}
2021-11-10 11:03:42 -08:00
func (b *Block) setActiveSegment(segment *Segment) {
b.activeSegment = segment
b.activeBackground = segment.background()
b.activeForeground = segment.foreground()
2022-01-26 04:09:21 -08:00
b.writer.SetColors(b.activeBackground, b.activeForeground)
2021-11-10 11:03:42 -08:00
}
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 {
2022-01-26 04:09:21 -08:00
defer b.writer.Reset()
for _, segment := range b.Segments {
if !segment.active {
continue
}
2021-12-16 01:57:28 -08:00
b.renderSegment(segment)
}
2021-12-16 01:57:28 -08:00
b.writePowerline(true)
2022-01-26 04:09:21 -08:00
b.writer.ClearParentColors()
return b.writer.String()
}
func (b *Block) renderSegment(segment *Segment) {
b.setActiveSegment(segment)
b.writePowerline(false)
switch b.activeSegment.Style {
case Plain, Powerline:
b.renderText(segment.stringValue)
case Diamond:
2022-01-26 04:09:21 -08:00
b.writer.Write(color.Transparent, b.activeBackground, b.activeSegment.LeadingDiamond)
b.renderText(segment.stringValue)
2022-01-26 04:09:21 -08:00
b.writer.Write(color.Transparent, b.activeBackground, b.activeSegment.TrailingDiamond)
}
b.previousActiveSegment = b.activeSegment
2022-01-26 04:09:21 -08:00
b.writer.SetParentColors(b.activeBackground, b.activeForeground)
}
func (b *Block) renderText(text string) {
defaultValue := " "
2022-01-26 04:09:21 -08:00
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) writePowerline(final bool) {
2021-12-16 01:57:28 -08:00
resolvePowerlineSymbol := func() string {
var symbol string
if b.activeSegment.Style == Powerline {
2021-12-16 01:57:28 -08:00
symbol = b.activeSegment.PowerlineSymbol
} else if b.previousActiveSegment != nil && b.previousActiveSegment.Style == Powerline {
symbol = b.previousActiveSegment.PowerlineSymbol
2021-12-16 01:57:28 -08:00
}
return symbol
}
symbol := resolvePowerlineSymbol()
if len(symbol) == 0 {
return
}
2021-12-16 01:57:28 -08:00
background := b.activeSegment.background()
if final || b.activeSegment.Style != Powerline {
2022-01-26 04:09:21 -08:00
background = color.Transparent
}
2021-12-16 01:57:28 -08:00
if b.activeSegment.Style == Diamond && len(b.activeSegment.LeadingDiamond) == 0 {
background = b.activeSegment.background()
}
if b.activeSegment.InvertPowerline {
2022-01-26 04:09:21 -08:00
b.writer.Write(b.getPowerlineColor(), background, symbol)
return
}
2022-01-26 04:09:21 -08:00
b.writer.Write(background, b.getPowerlineColor(), symbol)
}
2021-12-16 01:57:28 -08:00
func (b *Block) getPowerlineColor() string {
if b.previousActiveSegment == nil {
2022-01-26 04:09:21 -08:00
return color.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 {
2021-12-16 01:57:28 -08:00
return b.previousActiveSegment.background()
}
2021-12-16 01:57:28 -08:00
if b.previousActiveSegment.Style != Powerline {
2022-01-26 04:09:21 -08:00
return color.Transparent
}
return b.previousActiveSegment.background()
}
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()
2021-12-16 01:57:28 -08:00
segment.stringValue = segment.string()
segmentTiming.stringDuration = time.Since(start)
2021-12-16 01:57:28 -08:00
b.renderSegment(segment)
2021-12-17 03:19:03 -08:00
b.writePowerline(true)
2022-01-26 04:09:21 -08:00
segmentTiming.stringValue = b.writer.String()
b.writer.Reset()
}
segmentTimings = append(segmentTimings, &segmentTiming)
}
return largestSegmentNameLength, segmentTimings
}