mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2025-02-02 05:41:10 -08:00
refactor: split engine logic
This commit is contained in:
parent
6c181c1120
commit
a1b95a0274
|
@ -75,7 +75,7 @@ Exports the config to an image file using customized output options.`,
|
|||
Writer: writer,
|
||||
}
|
||||
|
||||
prompt := eng.PrintPrimary()
|
||||
prompt := eng.Primary()
|
||||
|
||||
imageCreator := &engine.ImageRenderer{
|
||||
AnsiString: prompt,
|
||||
|
|
|
@ -67,21 +67,21 @@ var printCmd = &cobra.Command{
|
|||
|
||||
switch args[0] {
|
||||
case "debug":
|
||||
fmt.Print(eng.PrintExtraPrompt(engine.Debug))
|
||||
fmt.Print(eng.ExtraPrompt(engine.Debug))
|
||||
case "primary":
|
||||
fmt.Print(eng.PrintPrimary())
|
||||
fmt.Print(eng.Primary())
|
||||
case "secondary":
|
||||
fmt.Print(eng.PrintExtraPrompt(engine.Secondary))
|
||||
fmt.Print(eng.ExtraPrompt(engine.Secondary))
|
||||
case "transient":
|
||||
fmt.Print(eng.PrintExtraPrompt(engine.Transient))
|
||||
fmt.Print(eng.ExtraPrompt(engine.Transient))
|
||||
case "right":
|
||||
fmt.Print(eng.PrintRPrompt())
|
||||
fmt.Print(eng.RPrompt())
|
||||
case "tooltip":
|
||||
fmt.Print(eng.PrintTooltip(command))
|
||||
fmt.Print(eng.Tooltip(command))
|
||||
case "valid":
|
||||
fmt.Print(eng.PrintExtraPrompt(engine.Valid))
|
||||
fmt.Print(eng.ExtraPrompt(engine.Valid))
|
||||
case "error":
|
||||
fmt.Print(eng.PrintExtraPrompt(engine.Error))
|
||||
fmt.Print(eng.ExtraPrompt(engine.Error))
|
||||
default:
|
||||
_ = cmd.Help()
|
||||
}
|
||||
|
|
65
src/engine/debug.go
Normal file
65
src/engine/debug.go
Normal file
|
@ -0,0 +1,65 @@
|
|||
package engine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/log"
|
||||
)
|
||||
|
||||
// debug will loop through your config file and output the timings for each segments
|
||||
func (e *Engine) PrintDebug(startTime time.Time, version string) string {
|
||||
e.write(fmt.Sprintf("\n%s %s\n", log.Text("Version:").Green().Bold().Plain(), version))
|
||||
sh := e.Env.Shell()
|
||||
shellVersion := e.Env.Getenv("POSH_SHELL_VERSION")
|
||||
if len(shellVersion) != 0 {
|
||||
sh += fmt.Sprintf(" (%s)", shellVersion)
|
||||
}
|
||||
e.write(fmt.Sprintf("\n%s %s\n", log.Text("Shell:").Green().Bold().Plain(), sh))
|
||||
e.write(log.Text("\nSegments:\n\n").Green().Bold().Plain().String())
|
||||
// console title timing
|
||||
titleStartTime := time.Now()
|
||||
e.Env.Debug("Segment: Title")
|
||||
title := e.getTitleTemplateText()
|
||||
consoleTitleTiming := &SegmentTiming{
|
||||
name: "ConsoleTitle",
|
||||
nameLength: 12,
|
||||
active: len(e.Config.ConsoleTitleTemplate) > 0,
|
||||
text: title,
|
||||
duration: time.Since(titleStartTime),
|
||||
}
|
||||
largestSegmentNameLength := consoleTitleTiming.nameLength
|
||||
var segmentTimings []*SegmentTiming
|
||||
segmentTimings = append(segmentTimings, consoleTitleTiming)
|
||||
// cache a pointer to the color cycle
|
||||
cycle = &e.Config.Cycle
|
||||
// loop each segments of each blocks
|
||||
for _, block := range e.Config.Blocks {
|
||||
block.Init(e.Env, e.Writer)
|
||||
longestSegmentName, timings := block.Debug()
|
||||
segmentTimings = append(segmentTimings, timings...)
|
||||
if longestSegmentName > largestSegmentNameLength {
|
||||
largestSegmentNameLength = longestSegmentName
|
||||
}
|
||||
}
|
||||
|
||||
// 22 is the color for false/true and 7 is the reset color
|
||||
largestSegmentNameLength += 22 + 7
|
||||
for _, segment := range segmentTimings {
|
||||
duration := segment.duration.Milliseconds()
|
||||
var active log.Text
|
||||
if segment.active {
|
||||
active = log.Text("true").Yellow()
|
||||
} else {
|
||||
active = log.Text("false").Purple()
|
||||
}
|
||||
segmentName := fmt.Sprintf("%s(%s)", segment.name, active.Plain())
|
||||
e.write(fmt.Sprintf("%-*s - %3d ms - %s\n", largestSegmentNameLength, segmentName, duration, segment.text))
|
||||
}
|
||||
e.write(fmt.Sprintf("\n%s %s\n", log.Text("Run duration:").Green().Bold().Plain(), time.Since(startTime)))
|
||||
e.write(fmt.Sprintf("\n%s %s\n", log.Text("Cache path:").Green().Bold().Plain(), e.Env.CachePath()))
|
||||
e.write(fmt.Sprintf("\n%s %s\n", log.Text("Config path:").Green().Bold().Plain(), e.Env.Flags().Config))
|
||||
e.write(log.Text("\nLogs:\n\n").Green().Bold().Plain().String())
|
||||
e.write(e.Env.Logs())
|
||||
return e.string()
|
||||
}
|
|
@ -1,12 +1,9 @@
|
|||
package engine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/ansi"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/log"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/platform"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/shell"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/template"
|
||||
|
@ -61,29 +58,7 @@ func (e *Engine) canWriteRightBlock(rprompt bool) bool {
|
|||
return canWrite
|
||||
}
|
||||
|
||||
func (e *Engine) PrintPrimary() string {
|
||||
// cache a pointer to the color cycle
|
||||
cycle = &e.Config.Cycle
|
||||
for i, block := range e.Config.Blocks {
|
||||
var cancelNewline bool
|
||||
if i == 0 {
|
||||
row, _ := e.Env.CursorPosition()
|
||||
cancelNewline = e.Env.Flags().Cleared || e.Env.Flags().PromptCount == 1 || row == 1
|
||||
}
|
||||
e.renderBlock(block, cancelNewline)
|
||||
}
|
||||
if len(e.Config.ConsoleTitleTemplate) > 0 {
|
||||
title := e.getTitleTemplateText()
|
||||
e.write(e.Writer.FormatTitle(title))
|
||||
}
|
||||
if e.Config.FinalSpace {
|
||||
e.write(" ")
|
||||
}
|
||||
e.printPWD()
|
||||
return e.print()
|
||||
}
|
||||
|
||||
func (e *Engine) printPWD() {
|
||||
func (e *Engine) pwd() {
|
||||
// only print when supported
|
||||
sh := e.Env.Shell()
|
||||
if sh == shell.ELVISH || sh == shell.XONSH {
|
||||
|
@ -250,267 +225,3 @@ func (e *Engine) renderBlock(block *Block, cancelNewline bool) {
|
|||
e.rprompt, e.rpromptLength = block.RenderSegments()
|
||||
}
|
||||
}
|
||||
|
||||
// debug will loop through your config file and output the timings for each segments
|
||||
func (e *Engine) PrintDebug(startTime time.Time, version string) string {
|
||||
e.write(fmt.Sprintf("\n%s %s\n", log.Text("Version:").Green().Bold().Plain(), version))
|
||||
sh := e.Env.Shell()
|
||||
shellVersion := e.Env.Getenv("POSH_SHELL_VERSION")
|
||||
if len(shellVersion) != 0 {
|
||||
sh += fmt.Sprintf(" (%s)", shellVersion)
|
||||
}
|
||||
e.write(fmt.Sprintf("\n%s %s\n", log.Text("Shell:").Green().Bold().Plain(), sh))
|
||||
e.write(log.Text("\nSegments:\n\n").Green().Bold().Plain().String())
|
||||
// console title timing
|
||||
titleStartTime := time.Now()
|
||||
e.Env.Debug("Segment: Title")
|
||||
title := e.getTitleTemplateText()
|
||||
consoleTitleTiming := &SegmentTiming{
|
||||
name: "ConsoleTitle",
|
||||
nameLength: 12,
|
||||
active: len(e.Config.ConsoleTitleTemplate) > 0,
|
||||
text: title,
|
||||
duration: time.Since(titleStartTime),
|
||||
}
|
||||
largestSegmentNameLength := consoleTitleTiming.nameLength
|
||||
var segmentTimings []*SegmentTiming
|
||||
segmentTimings = append(segmentTimings, consoleTitleTiming)
|
||||
// cache a pointer to the color cycle
|
||||
cycle = &e.Config.Cycle
|
||||
// loop each segments of each blocks
|
||||
for _, block := range e.Config.Blocks {
|
||||
block.Init(e.Env, e.Writer)
|
||||
longestSegmentName, timings := block.Debug()
|
||||
segmentTimings = append(segmentTimings, timings...)
|
||||
if longestSegmentName > largestSegmentNameLength {
|
||||
largestSegmentNameLength = longestSegmentName
|
||||
}
|
||||
}
|
||||
|
||||
// 22 is the color for false/true and 7 is the reset color
|
||||
largestSegmentNameLength += 22 + 7
|
||||
for _, segment := range segmentTimings {
|
||||
duration := segment.duration.Milliseconds()
|
||||
var active log.Text
|
||||
if segment.active {
|
||||
active = log.Text("true").Yellow()
|
||||
} else {
|
||||
active = log.Text("false").Purple()
|
||||
}
|
||||
segmentName := fmt.Sprintf("%s(%s)", segment.name, active.Plain())
|
||||
e.write(fmt.Sprintf("%-*s - %3d ms - %s\n", largestSegmentNameLength, segmentName, duration, segment.text))
|
||||
}
|
||||
e.write(fmt.Sprintf("\n%s %s\n", log.Text("Run duration:").Green().Bold().Plain(), time.Since(startTime)))
|
||||
e.write(fmt.Sprintf("\n%s %s\n", log.Text("Cache path:").Green().Bold().Plain(), e.Env.CachePath()))
|
||||
e.write(fmt.Sprintf("\n%s %s\n", log.Text("Config path:").Green().Bold().Plain(), e.Env.Flags().Config))
|
||||
e.write(log.Text("\nLogs:\n\n").Green().Bold().Plain().String())
|
||||
e.write(e.Env.Logs())
|
||||
return e.string()
|
||||
}
|
||||
|
||||
func (e *Engine) print() string {
|
||||
switch e.Env.Shell() {
|
||||
case shell.ZSH:
|
||||
if !e.Env.Flags().Eval {
|
||||
break
|
||||
}
|
||||
// Warp doesn't support RPROMPT so we need to write it manually
|
||||
if e.isWarp() {
|
||||
e.write(e.Writer.SaveCursorPosition())
|
||||
e.write(e.Writer.CarriageForward())
|
||||
e.write(e.Writer.GetCursorForRightWrite(e.rpromptLength, 0))
|
||||
e.write(e.rprompt)
|
||||
e.write(e.Writer.RestoreCursorPosition())
|
||||
// escape double quotes contained in the prompt
|
||||
prompt := fmt.Sprintf("PS1=\"%s\"", strings.ReplaceAll(e.string(), `"`, `\"`))
|
||||
return prompt
|
||||
}
|
||||
// escape double quotes contained in the prompt
|
||||
prompt := fmt.Sprintf("PS1=\"%s\"", strings.ReplaceAll(e.string(), `"`, `\"`))
|
||||
prompt += fmt.Sprintf("\nRPROMPT=\"%s\"", e.rprompt)
|
||||
return prompt
|
||||
case shell.PWSH, shell.PWSH5, shell.GENERIC, shell.NU:
|
||||
if !e.canWriteRightBlock(true) {
|
||||
break
|
||||
}
|
||||
e.write(e.Writer.SaveCursorPosition())
|
||||
e.write(e.Writer.CarriageForward())
|
||||
e.write(e.Writer.GetCursorForRightWrite(e.rpromptLength, 0))
|
||||
e.write(e.rprompt)
|
||||
e.write(e.Writer.RestoreCursorPosition())
|
||||
case shell.BASH:
|
||||
if !e.canWriteRightBlock(true) {
|
||||
break
|
||||
}
|
||||
// in bash, the entire rprompt needs to be escaped for the prompt to be interpreted correctly
|
||||
// see https://github.com/jandedobbeleer/oh-my-posh/pull/2398
|
||||
writer := &ansi.Writer{
|
||||
TrueColor: e.Env.Flags().TrueColor,
|
||||
}
|
||||
writer.Init(shell.GENERIC)
|
||||
prompt := writer.SaveCursorPosition()
|
||||
prompt += writer.CarriageForward()
|
||||
prompt += writer.GetCursorForRightWrite(e.rpromptLength, 0)
|
||||
prompt += e.rprompt
|
||||
prompt += writer.RestoreCursorPosition()
|
||||
prompt = e.Writer.FormatText(prompt)
|
||||
e.write(prompt)
|
||||
}
|
||||
|
||||
return e.string()
|
||||
}
|
||||
|
||||
func (e *Engine) PrintTooltip(tip string) string {
|
||||
tip = strings.Trim(tip, " ")
|
||||
var tooltip *Segment
|
||||
for _, tp := range e.Config.Tooltips {
|
||||
if !tp.shouldInvokeWithTip(tip) {
|
||||
continue
|
||||
}
|
||||
tooltip = tp
|
||||
}
|
||||
if tooltip == nil {
|
||||
return ""
|
||||
}
|
||||
if err := tooltip.mapSegmentWithWriter(e.Env); err != nil {
|
||||
return ""
|
||||
}
|
||||
if !tooltip.writer.Enabled() {
|
||||
return ""
|
||||
}
|
||||
tooltip.Enabled = true
|
||||
// little hack to reuse the current logic
|
||||
block := &Block{
|
||||
Alignment: Right,
|
||||
Segments: []*Segment{tooltip},
|
||||
}
|
||||
switch e.Env.Shell() {
|
||||
case shell.ZSH, shell.CMD, shell.FISH, shell.GENERIC:
|
||||
block.Init(e.Env, e.Writer)
|
||||
if !block.Enabled() {
|
||||
return ""
|
||||
}
|
||||
text, _ := block.RenderSegments()
|
||||
return text
|
||||
case shell.PWSH, shell.PWSH5:
|
||||
block.InitPlain(e.Env, e.Config)
|
||||
if !block.Enabled() {
|
||||
return ""
|
||||
}
|
||||
text, length := block.RenderSegments()
|
||||
// clear from cursor to the end of the line in case a previous tooltip is cut off and partially preserved,
|
||||
// if the new one is shorter
|
||||
e.write(e.Writer.ClearAfter())
|
||||
e.write(e.Writer.CarriageForward())
|
||||
e.write(e.Writer.GetCursorForRightWrite(length, 0))
|
||||
e.write(text)
|
||||
return e.string()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type ExtraPromptType int
|
||||
|
||||
const (
|
||||
Transient ExtraPromptType = iota
|
||||
Valid
|
||||
Error
|
||||
Secondary
|
||||
Debug
|
||||
)
|
||||
|
||||
func (e *Engine) PrintExtraPrompt(promptType ExtraPromptType) string {
|
||||
// populate env with latest context
|
||||
e.Env.LoadTemplateCache()
|
||||
var prompt *Segment
|
||||
switch promptType {
|
||||
case Debug:
|
||||
prompt = e.Config.DebugPrompt
|
||||
case Transient:
|
||||
prompt = e.Config.TransientPrompt
|
||||
case Valid:
|
||||
prompt = e.Config.ValidLine
|
||||
case Error:
|
||||
prompt = e.Config.ErrorLine
|
||||
case Secondary:
|
||||
prompt = e.Config.SecondaryPrompt
|
||||
}
|
||||
if prompt == nil {
|
||||
prompt = &Segment{}
|
||||
}
|
||||
getTemplate := func(template string) string {
|
||||
if len(template) != 0 {
|
||||
return template
|
||||
}
|
||||
switch promptType { //nolint: exhaustive
|
||||
case Debug:
|
||||
return "[DBG]: "
|
||||
case Transient:
|
||||
return "{{ .Shell }}> "
|
||||
case Secondary:
|
||||
return "> "
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
tmpl := &template.Text{
|
||||
Template: getTemplate(prompt.Template),
|
||||
Env: e.Env,
|
||||
}
|
||||
promptText, err := tmpl.Render()
|
||||
if err != nil {
|
||||
promptText = err.Error()
|
||||
}
|
||||
foreground := prompt.ForegroundTemplates.FirstMatch(nil, e.Env, prompt.Foreground)
|
||||
background := prompt.BackgroundTemplates.FirstMatch(nil, e.Env, prompt.Background)
|
||||
e.Writer.SetColors(background, foreground)
|
||||
e.Writer.Write(background, foreground, promptText)
|
||||
str, length := e.Writer.String()
|
||||
if promptType == Transient {
|
||||
if padText, OK := e.shouldFill(prompt.Filler, length); OK {
|
||||
str += padText
|
||||
}
|
||||
}
|
||||
switch e.Env.Shell() {
|
||||
case shell.ZSH:
|
||||
// escape double quotes contained in the prompt
|
||||
if promptType == Transient {
|
||||
prompt := fmt.Sprintf("PS1=\"%s\"", strings.ReplaceAll(str, "\"", "\"\""))
|
||||
// empty RPROMPT
|
||||
prompt += "\nRPROMPT=\"\""
|
||||
return prompt
|
||||
}
|
||||
return str
|
||||
case shell.PWSH, shell.PWSH5:
|
||||
// Return the string and empty our buffer
|
||||
// clear the line afterwards to prevent text from being written on the same line
|
||||
// see https://github.com/JanDeDobbeleer/oh-my-posh/issues/3628
|
||||
return str + e.Writer.ClearAfter()
|
||||
case shell.CMD, shell.BASH, shell.FISH, shell.NU, shell.GENERIC:
|
||||
// Return the string and empty our buffer
|
||||
return str
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (e *Engine) PrintRPrompt() string {
|
||||
filterRPromptBlock := func(blocks []*Block) *Block {
|
||||
for _, block := range blocks {
|
||||
if block.Type == RPrompt {
|
||||
return block
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
block := filterRPromptBlock(e.Config.Blocks)
|
||||
if block == nil {
|
||||
return ""
|
||||
}
|
||||
block.Init(e.Env, e.Writer)
|
||||
if !block.Enabled() {
|
||||
return ""
|
||||
}
|
||||
text, length := block.RenderSegments()
|
||||
e.rpromptLength = length
|
||||
return text
|
||||
}
|
||||
|
|
|
@ -81,8 +81,8 @@ func TestPrintPWD(t *testing.T) {
|
|||
},
|
||||
Writer: writer,
|
||||
}
|
||||
engine.printPWD()
|
||||
got := engine.print()
|
||||
engine.pwd()
|
||||
got := engine.string()
|
||||
assert.Equal(t, tc.Expected, got, tc.Case)
|
||||
}
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ func engineRender() {
|
|||
Writer: writer,
|
||||
}
|
||||
|
||||
engine.PrintPrimary()
|
||||
engine.Primary()
|
||||
}
|
||||
|
||||
func BenchmarkEngineRenderPalette(b *testing.B) {
|
||||
|
|
200
src/engine/prompt.go
Normal file
200
src/engine/prompt.go
Normal file
|
@ -0,0 +1,200 @@
|
|||
package engine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/ansi"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/shell"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/template"
|
||||
)
|
||||
|
||||
type ExtraPromptType int
|
||||
|
||||
const (
|
||||
Transient ExtraPromptType = iota
|
||||
Valid
|
||||
Error
|
||||
Secondary
|
||||
Debug
|
||||
)
|
||||
|
||||
func (e *Engine) Primary() string {
|
||||
// cache a pointer to the color cycle
|
||||
cycle = &e.Config.Cycle
|
||||
for i, block := range e.Config.Blocks {
|
||||
var cancelNewline bool
|
||||
if i == 0 {
|
||||
row, _ := e.Env.CursorPosition()
|
||||
cancelNewline = e.Env.Flags().Cleared || e.Env.Flags().PromptCount == 1 || row == 1
|
||||
}
|
||||
e.renderBlock(block, cancelNewline)
|
||||
}
|
||||
|
||||
if len(e.Config.ConsoleTitleTemplate) > 0 {
|
||||
title := e.getTitleTemplateText()
|
||||
e.write(e.Writer.FormatTitle(title))
|
||||
}
|
||||
|
||||
if e.Config.FinalSpace {
|
||||
e.write(" ")
|
||||
}
|
||||
|
||||
e.pwd()
|
||||
|
||||
switch e.Env.Shell() {
|
||||
case shell.ZSH:
|
||||
if !e.Env.Flags().Eval {
|
||||
break
|
||||
}
|
||||
// Warp doesn't support RPROMPT so we need to write it manually
|
||||
if e.isWarp() {
|
||||
e.write(e.Writer.SaveCursorPosition())
|
||||
e.write(e.Writer.CarriageForward())
|
||||
e.write(e.Writer.GetCursorForRightWrite(e.rpromptLength, 0))
|
||||
e.write(e.rprompt)
|
||||
e.write(e.Writer.RestoreCursorPosition())
|
||||
// escape double quotes contained in the prompt
|
||||
prompt := fmt.Sprintf("PS1=\"%s\"", strings.ReplaceAll(e.string(), `"`, `\"`))
|
||||
return prompt
|
||||
}
|
||||
// escape double quotes contained in the prompt
|
||||
prompt := fmt.Sprintf("PS1=\"%s\"", strings.ReplaceAll(e.string(), `"`, `\"`))
|
||||
prompt += fmt.Sprintf("\nRPROMPT=\"%s\"", e.rprompt)
|
||||
return prompt
|
||||
case shell.PWSH, shell.PWSH5, shell.GENERIC, shell.NU:
|
||||
if !e.canWriteRightBlock(true) {
|
||||
break
|
||||
}
|
||||
e.write(e.Writer.SaveCursorPosition())
|
||||
e.write(e.Writer.CarriageForward())
|
||||
e.write(e.Writer.GetCursorForRightWrite(e.rpromptLength, 0))
|
||||
e.write(e.rprompt)
|
||||
e.write(e.Writer.RestoreCursorPosition())
|
||||
case shell.BASH:
|
||||
if !e.canWriteRightBlock(true) {
|
||||
break
|
||||
}
|
||||
// in bash, the entire rprompt needs to be escaped for the prompt to be interpreted correctly
|
||||
// see https://github.com/jandedobbeleer/oh-my-posh/pull/2398
|
||||
writer := &ansi.Writer{
|
||||
TrueColor: e.Env.Flags().TrueColor,
|
||||
}
|
||||
writer.Init(shell.GENERIC)
|
||||
prompt := writer.SaveCursorPosition()
|
||||
prompt += writer.CarriageForward()
|
||||
prompt += writer.GetCursorForRightWrite(e.rpromptLength, 0)
|
||||
prompt += e.rprompt
|
||||
prompt += writer.RestoreCursorPosition()
|
||||
prompt = e.Writer.FormatText(prompt)
|
||||
e.write(prompt)
|
||||
}
|
||||
|
||||
return e.string()
|
||||
}
|
||||
|
||||
func (e *Engine) ExtraPrompt(promptType ExtraPromptType) string {
|
||||
// populate env with latest context
|
||||
e.Env.LoadTemplateCache()
|
||||
var prompt *Segment
|
||||
switch promptType {
|
||||
case Debug:
|
||||
prompt = e.Config.DebugPrompt
|
||||
case Transient:
|
||||
prompt = e.Config.TransientPrompt
|
||||
case Valid:
|
||||
prompt = e.Config.ValidLine
|
||||
case Error:
|
||||
prompt = e.Config.ErrorLine
|
||||
case Secondary:
|
||||
prompt = e.Config.SecondaryPrompt
|
||||
}
|
||||
|
||||
if prompt == nil {
|
||||
prompt = &Segment{}
|
||||
}
|
||||
|
||||
getTemplate := func(template string) string {
|
||||
if len(template) != 0 {
|
||||
return template
|
||||
}
|
||||
switch promptType { //nolint: exhaustive
|
||||
case Debug:
|
||||
return "[DBG]: "
|
||||
case Transient:
|
||||
return "{{ .Shell }}> "
|
||||
case Secondary:
|
||||
return "> "
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
tmpl := &template.Text{
|
||||
Template: getTemplate(prompt.Template),
|
||||
Env: e.Env,
|
||||
}
|
||||
promptText, err := tmpl.Render()
|
||||
if err != nil {
|
||||
promptText = err.Error()
|
||||
}
|
||||
|
||||
foreground := prompt.ForegroundTemplates.FirstMatch(nil, e.Env, prompt.Foreground)
|
||||
background := prompt.BackgroundTemplates.FirstMatch(nil, e.Env, prompt.Background)
|
||||
e.Writer.SetColors(background, foreground)
|
||||
e.Writer.Write(background, foreground, promptText)
|
||||
|
||||
str, length := e.Writer.String()
|
||||
if promptType == Transient {
|
||||
if padText, OK := e.shouldFill(prompt.Filler, length); OK {
|
||||
str += padText
|
||||
}
|
||||
}
|
||||
|
||||
switch e.Env.Shell() {
|
||||
case shell.ZSH:
|
||||
// escape double quotes contained in the prompt
|
||||
if promptType == Transient {
|
||||
prompt := fmt.Sprintf("PS1=\"%s\"", strings.ReplaceAll(str, "\"", "\"\""))
|
||||
// empty RPROMPT
|
||||
prompt += "\nRPROMPT=\"\""
|
||||
return prompt
|
||||
}
|
||||
return str
|
||||
case shell.PWSH, shell.PWSH5:
|
||||
// Return the string and empty our buffer
|
||||
// clear the line afterwards to prevent text from being written on the same line
|
||||
// see https://github.com/JanDeDobbeleer/oh-my-posh/issues/3628
|
||||
return str + e.Writer.ClearAfter()
|
||||
case shell.CMD, shell.BASH, shell.FISH, shell.NU, shell.GENERIC:
|
||||
// Return the string and empty our buffer
|
||||
return str
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func (e *Engine) RPrompt() string {
|
||||
filterRPromptBlock := func(blocks []*Block) *Block {
|
||||
for _, block := range blocks {
|
||||
if block.Type == RPrompt {
|
||||
return block
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
block := filterRPromptBlock(e.Config.Blocks)
|
||||
if block == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
block.Init(e.Env, e.Writer)
|
||||
if !block.Enabled() {
|
||||
return ""
|
||||
}
|
||||
|
||||
text, length := block.RenderSegments()
|
||||
e.rpromptLength = length
|
||||
return text
|
||||
}
|
63
src/engine/tooltip.go
Normal file
63
src/engine/tooltip.go
Normal file
|
@ -0,0 +1,63 @@
|
|||
package engine
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/shell"
|
||||
)
|
||||
|
||||
func (e *Engine) Tooltip(tip string) string {
|
||||
tip = strings.Trim(tip, " ")
|
||||
var tooltip *Segment
|
||||
for _, tp := range e.Config.Tooltips {
|
||||
if !tp.shouldInvokeWithTip(tip) {
|
||||
continue
|
||||
}
|
||||
tooltip = tp
|
||||
}
|
||||
|
||||
if tooltip == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
if err := tooltip.mapSegmentWithWriter(e.Env); err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
if !tooltip.writer.Enabled() {
|
||||
return ""
|
||||
}
|
||||
|
||||
tooltip.Enabled = true
|
||||
|
||||
// little hack to reuse the current logic
|
||||
block := &Block{
|
||||
Alignment: Right,
|
||||
Segments: []*Segment{tooltip},
|
||||
}
|
||||
|
||||
switch e.Env.Shell() {
|
||||
case shell.ZSH, shell.CMD, shell.FISH, shell.GENERIC:
|
||||
block.Init(e.Env, e.Writer)
|
||||
if !block.Enabled() {
|
||||
return ""
|
||||
}
|
||||
text, _ := block.RenderSegments()
|
||||
return text
|
||||
case shell.PWSH, shell.PWSH5:
|
||||
block.InitPlain(e.Env, e.Config)
|
||||
if !block.Enabled() {
|
||||
return ""
|
||||
}
|
||||
text, length := block.RenderSegments()
|
||||
// clear from cursor to the end of the line in case a previous tooltip
|
||||
// is cut off and partially preserved, if the new one is shorter
|
||||
e.write(e.Writer.ClearAfter())
|
||||
e.write(e.Writer.CarriageForward())
|
||||
e.write(e.Writer.GetCursorForRightWrite(length, 0))
|
||||
e.write(text)
|
||||
return e.string()
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
Loading…
Reference in a new issue