2022-01-26 23:38:46 -08:00
|
|
|
package engine
|
2019-03-13 04:14:30 -07:00
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2022-12-17 13:30:23 -08:00
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
2023-01-05 12:57:38 -08:00
|
|
|
"github.com/jandedobbeleer/oh-my-posh/src/ansi"
|
|
|
|
"github.com/jandedobbeleer/oh-my-posh/src/platform"
|
|
|
|
"github.com/jandedobbeleer/oh-my-posh/src/shell"
|
|
|
|
"github.com/jandedobbeleer/oh-my-posh/src/template"
|
2019-03-13 04:14:30 -07:00
|
|
|
)
|
|
|
|
|
2023-01-11 04:36:25 -08:00
|
|
|
var (
|
2023-01-11 05:06:15 -08:00
|
|
|
cycle *ansi.Cycle = &ansi.Cycle{}
|
2023-01-11 04:36:25 -08:00
|
|
|
)
|
|
|
|
|
2022-01-26 23:38:46 -08:00
|
|
|
type Engine struct {
|
2023-01-03 03:21:27 -08:00
|
|
|
Config *Config
|
|
|
|
Env platform.Environment
|
2023-01-04 11:44:29 -08:00
|
|
|
Writer *ansi.Writer
|
2023-01-03 03:21:27 -08:00
|
|
|
Plain bool
|
2021-04-20 12:30:46 -07:00
|
|
|
|
2022-02-03 08:36:37 -08:00
|
|
|
console strings.Builder
|
|
|
|
currentLineLength int
|
|
|
|
rprompt string
|
|
|
|
rpromptLength int
|
2020-10-12 23:57:46 -07:00
|
|
|
}
|
|
|
|
|
2022-01-26 23:38:46 -08:00
|
|
|
func (e *Engine) write(text string) {
|
2021-04-20 12:30:46 -07:00
|
|
|
e.console.WriteString(text)
|
|
|
|
}
|
|
|
|
|
2022-01-26 23:38:46 -08:00
|
|
|
func (e *Engine) string() string {
|
2022-12-17 13:30:23 -08:00
|
|
|
text := e.console.String()
|
|
|
|
e.console.Reset()
|
|
|
|
return text
|
2021-04-20 12:30:46 -07:00
|
|
|
}
|
|
|
|
|
2023-01-02 07:33:25 -08:00
|
|
|
func (e *Engine) canWriteRightBlock(rprompt bool) bool {
|
2022-06-27 10:39:31 -07:00
|
|
|
if rprompt && (e.rprompt == "" || e.Plain) {
|
2022-06-12 10:55:57 -07:00
|
|
|
return false
|
|
|
|
}
|
2022-01-26 23:38:46 -08:00
|
|
|
consoleWidth, err := e.Env.TerminalWidth()
|
2021-05-25 09:31:23 -07:00
|
|
|
if err != nil || consoleWidth == 0 {
|
2021-05-22 07:50:34 -07:00
|
|
|
return true
|
|
|
|
}
|
2022-02-03 08:36:37 -08:00
|
|
|
promptWidth := e.currentLineLength
|
2021-05-22 07:50:34 -07:00
|
|
|
availableSpace := consoleWidth - promptWidth
|
2021-09-16 23:15:06 -07:00
|
|
|
// spanning multiple lines
|
|
|
|
if availableSpace < 0 {
|
|
|
|
overflow := promptWidth % consoleWidth
|
|
|
|
availableSpace = consoleWidth - overflow
|
2021-05-22 07:50:34 -07:00
|
|
|
}
|
2022-06-27 10:39:31 -07:00
|
|
|
promptBreathingRoom := 5
|
|
|
|
if rprompt {
|
|
|
|
promptBreathingRoom = 30
|
|
|
|
}
|
2022-02-03 08:36:37 -08:00
|
|
|
canWrite := (availableSpace - e.rpromptLength) >= promptBreathingRoom
|
2021-09-16 23:15:06 -07:00
|
|
|
return canWrite
|
2021-05-22 07:50:34 -07:00
|
|
|
}
|
|
|
|
|
2022-03-12 13:04:08 -08:00
|
|
|
func (e *Engine) PrintPrimary() string {
|
2023-01-09 11:10:55 -08:00
|
|
|
// cache a pointer to the color cycle
|
2023-01-11 04:36:25 -08:00
|
|
|
cycle = &e.Config.Cycle
|
2022-01-26 23:38:46 -08:00
|
|
|
for _, block := range e.Config.Blocks {
|
2021-04-18 10:16:06 -07:00
|
|
|
e.renderBlock(block)
|
2019-03-13 04:14:30 -07:00
|
|
|
}
|
2022-03-14 11:14:10 -07:00
|
|
|
if len(e.Config.ConsoleTitleTemplate) > 0 {
|
2023-01-03 03:21:27 -08:00
|
|
|
title := e.getTitleTemplateText()
|
|
|
|
e.write(e.Writer.FormatTitle(title))
|
2020-10-12 00:02:33 -07:00
|
|
|
}
|
2022-01-26 23:38:46 -08:00
|
|
|
if e.Config.FinalSpace {
|
2021-04-20 12:30:46 -07:00
|
|
|
e.write(" ")
|
2019-03-13 04:14:30 -07:00
|
|
|
}
|
2022-07-13 04:53:55 -07:00
|
|
|
e.printPWD()
|
|
|
|
return e.print()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *Engine) printPWD() {
|
|
|
|
if len(e.Config.PWD) == 0 && !e.Config.OSC99 {
|
|
|
|
return
|
2021-02-15 13:19:19 -08:00
|
|
|
}
|
2022-01-26 23:38:46 -08:00
|
|
|
cwd := e.Env.Pwd()
|
2022-07-13 04:53:55 -07:00
|
|
|
// Backwards compatibility for deprecated OSC99
|
|
|
|
if e.Config.OSC99 {
|
2023-01-04 11:44:29 -08:00
|
|
|
e.write(e.Writer.ConsolePwd(ansi.OSC99, "", "", cwd))
|
2022-07-13 04:53:55 -07:00
|
|
|
return
|
|
|
|
}
|
|
|
|
// Allow template logic to define when to enable the PWD (when supported)
|
|
|
|
tmpl := &template.Text{
|
|
|
|
Template: e.Config.PWD,
|
|
|
|
Env: e.Env,
|
|
|
|
}
|
|
|
|
pwdType, err := tmpl.Render()
|
|
|
|
if err != nil || len(pwdType) == 0 {
|
|
|
|
return
|
|
|
|
}
|
2022-11-24 14:45:44 -08:00
|
|
|
user := e.Env.User()
|
2022-07-25 23:28:39 -07:00
|
|
|
host, _ := e.Env.Host()
|
2023-01-03 03:21:27 -08:00
|
|
|
e.write(e.Writer.ConsolePwd(pwdType, user, host, cwd))
|
2020-12-17 23:59:45 -08:00
|
|
|
}
|
|
|
|
|
2022-02-03 08:36:37 -08:00
|
|
|
func (e *Engine) newline() {
|
2022-12-08 02:00:02 -08:00
|
|
|
// WARP terminal will remove \n from the prompt, so we hack a newline in
|
2022-12-08 02:30:21 -08:00
|
|
|
if e.isWarp() {
|
2023-01-03 03:21:27 -08:00
|
|
|
e.write(e.Writer.LineBreak())
|
2022-12-08 02:00:02 -08:00
|
|
|
} else {
|
|
|
|
e.write("\n")
|
|
|
|
}
|
2022-02-03 08:36:37 -08:00
|
|
|
e.currentLineLength = 0
|
|
|
|
}
|
|
|
|
|
2022-12-08 02:30:21 -08:00
|
|
|
func (e *Engine) isWarp() bool {
|
|
|
|
return e.Env.Getenv("TERM_PROGRAM") == "WarpTerminal"
|
|
|
|
}
|
|
|
|
|
2022-02-12 09:40:02 -08:00
|
|
|
func (e *Engine) shouldFill(block *Block, length int) (string, bool) {
|
|
|
|
if len(block.Filler) == 0 {
|
|
|
|
return "", false
|
|
|
|
}
|
|
|
|
terminalWidth, err := e.Env.TerminalWidth()
|
2022-06-12 10:55:57 -07:00
|
|
|
if err != nil || terminalWidth == 0 {
|
2022-02-12 09:40:02 -08:00
|
|
|
return "", false
|
|
|
|
}
|
|
|
|
padLength := terminalWidth - e.currentLineLength - length
|
|
|
|
if padLength <= 0 {
|
|
|
|
return "", false
|
|
|
|
}
|
|
|
|
e.Writer.Write("", "", block.Filler)
|
|
|
|
filler, lenFiller := e.Writer.String()
|
|
|
|
if lenFiller == 0 {
|
|
|
|
return "", false
|
|
|
|
}
|
|
|
|
repeat := padLength / lenFiller
|
|
|
|
return strings.Repeat(filler, repeat), true
|
|
|
|
}
|
|
|
|
|
2023-01-03 03:21:27 -08:00
|
|
|
func (e *Engine) getTitleTemplateText() string {
|
|
|
|
tmpl := &template.Text{
|
|
|
|
Template: e.Config.ConsoleTitleTemplate,
|
|
|
|
Env: e.Env,
|
|
|
|
}
|
|
|
|
if text, err := tmpl.Render(); err == nil {
|
|
|
|
return text
|
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
2022-01-26 23:38:46 -08:00
|
|
|
func (e *Engine) renderBlock(block *Block) {
|
2022-07-01 08:15:19 -07:00
|
|
|
defer func() {
|
2022-10-03 07:46:16 -07:00
|
|
|
// Due to a bug in PowerShell, the end of the line needs to be cleared.
|
2022-07-01 08:15:19 -07:00
|
|
|
// 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 {
|
2023-01-03 03:21:27 -08:00
|
|
|
e.write(e.Writer.ClearAfter())
|
2022-07-01 08:15:19 -07:00
|
|
|
}
|
|
|
|
}()
|
2021-05-21 13:10:20 -07:00
|
|
|
// when in bash, for rprompt blocks we need to write plain
|
|
|
|
// and wrap in escaped mode or the prompt will not render correctly
|
2023-01-11 06:29:50 -08:00
|
|
|
if e.Env.Shell() == shell.BASH && block.Type == RPrompt {
|
2022-05-05 23:41:58 -07:00
|
|
|
block.InitPlain(e.Env, e.Config)
|
2021-05-21 13:10:20 -07:00
|
|
|
} else {
|
2023-01-11 04:36:25 -08:00
|
|
|
block.Init(e.Env, e.Writer)
|
2021-05-21 13:10:20 -07:00
|
|
|
}
|
2022-05-05 23:41:58 -07:00
|
|
|
if !block.Enabled() {
|
2021-04-18 10:16:06 -07:00
|
|
|
return
|
|
|
|
}
|
|
|
|
if block.Newline {
|
2022-02-03 08:36:37 -08:00
|
|
|
e.newline()
|
2021-04-18 10:16:06 -07:00
|
|
|
}
|
|
|
|
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:
|
2022-02-03 08:36:37 -08:00
|
|
|
e.newline()
|
2021-04-18 10:16:06 -07:00
|
|
|
case Prompt:
|
|
|
|
if block.VerticalOffset != 0 {
|
2023-01-03 03:21:27 -08:00
|
|
|
e.write(e.Writer.ChangeLine(block.VerticalOffset))
|
2021-04-18 10:16:06 -07:00
|
|
|
}
|
2022-06-12 10:55:57 -07:00
|
|
|
|
|
|
|
if block.Alignment == Left {
|
2022-05-07 01:12:22 -07:00
|
|
|
text, length := block.RenderSegments()
|
2022-02-03 08:36:37 -08:00
|
|
|
e.currentLineLength += length
|
|
|
|
e.write(text)
|
2022-06-27 10:39:31 -07:00
|
|
|
return
|
2021-04-18 10:16:06 -07:00
|
|
|
}
|
2022-06-12 10:55:57 -07:00
|
|
|
|
|
|
|
if block.Alignment != Right {
|
2022-06-27 10:39:31 -07:00
|
|
|
return
|
2022-06-12 10:55:57 -07:00
|
|
|
}
|
|
|
|
|
2022-05-07 01:12:22 -07:00
|
|
|
text, length := block.RenderSegments()
|
2022-06-27 10:39:31 -07:00
|
|
|
e.rpromptLength = length
|
|
|
|
|
2023-01-02 07:33:25 -08:00
|
|
|
if !e.canWriteRightBlock(false) {
|
2022-06-27 10:39:31 -07:00
|
|
|
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 {
|
2022-06-12 10:55:57 -07:00
|
|
|
// in this case we can print plain
|
|
|
|
e.write(padText)
|
|
|
|
e.write(text)
|
2022-06-27 10:39:31 -07:00
|
|
|
return
|
2022-06-12 10:55:57 -07:00
|
|
|
}
|
2023-01-11 06:29:50 -08:00
|
|
|
prompt := e.Writer.CarriageForward()
|
|
|
|
prompt += e.Writer.GetCursorForRightWrite(length, block.HorizontalOffset)
|
2022-06-12 10:55:57 -07:00
|
|
|
prompt += text
|
|
|
|
e.currentLineLength = 0
|
|
|
|
e.write(prompt)
|
|
|
|
case RPrompt:
|
|
|
|
e.rprompt, e.rpromptLength = block.RenderSegments()
|
2021-04-18 10:16:06 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-09 07:18:37 -08:00
|
|
|
// debug will loop through your config file and output the timings for each segments
|
2022-05-05 23:41:58 -07:00
|
|
|
func (e *Engine) PrintDebug(startTime time.Time, version string) string {
|
2021-04-18 10:16:06 -07:00
|
|
|
var segmentTimings []*SegmentTiming
|
2020-12-31 05:00:46 -08:00
|
|
|
largestSegmentNameLength := 0
|
2022-01-26 23:38:46 -08:00
|
|
|
e.write(fmt.Sprintf("\n\x1b[1mVersion:\x1b[0m %s\n", version))
|
2021-11-16 10:59:42 -08:00
|
|
|
e.write("\n\x1b[1mSegments:\x1b[0m\n\n")
|
2021-01-14 21:10:36 -08:00
|
|
|
// console title timing
|
2022-05-07 01:12:22 -07:00
|
|
|
titleStartTime := time.Now()
|
2023-01-03 03:21:27 -08:00
|
|
|
title := e.getTitleTemplateText()
|
2021-04-18 10:16:06 -07:00
|
|
|
segmentTiming := &SegmentTiming{
|
2022-02-02 03:16:39 -08:00
|
|
|
name: "ConsoleTitle",
|
|
|
|
nameLength: 12,
|
2022-03-14 11:14:10 -07:00
|
|
|
active: len(e.Config.ConsoleTitleTemplate) > 0,
|
|
|
|
text: title,
|
2022-05-07 01:12:22 -07:00
|
|
|
duration: time.Since(titleStartTime),
|
2021-01-14 21:10:36 -08:00
|
|
|
}
|
|
|
|
segmentTimings = append(segmentTimings, segmentTiming)
|
2023-01-09 11:10:55 -08:00
|
|
|
// cache a pointer to the color cycle
|
2023-01-11 04:36:25 -08:00
|
|
|
cycle = &e.Config.Cycle
|
2020-12-27 08:53:58 -08:00
|
|
|
// loop each segments of each blocks
|
2022-01-26 23:38:46 -08:00
|
|
|
for _, block := range e.Config.Blocks {
|
2023-01-11 04:36:25 -08:00
|
|
|
block.Init(e.Env, e.Writer)
|
2022-05-07 01:12:22 -07:00
|
|
|
longestSegmentName, timings := block.Debug()
|
2021-04-18 10:16:06 -07:00
|
|
|
segmentTimings = append(segmentTimings, timings...)
|
|
|
|
if longestSegmentName > largestSegmentNameLength {
|
|
|
|
largestSegmentNameLength = longestSegmentName
|
2020-12-27 08:53:58 -08:00
|
|
|
}
|
|
|
|
}
|
2021-01-14 21:10:36 -08:00
|
|
|
|
2020-12-31 05:00:46 -08:00
|
|
|
// pad the output so the tabs render correctly
|
|
|
|
largestSegmentNameLength += 7
|
2020-12-27 08:53:58 -08:00
|
|
|
for _, segment := range segmentTimings {
|
2022-02-02 03:16:39 -08:00
|
|
|
duration := segment.duration.Milliseconds()
|
|
|
|
segmentName := fmt.Sprintf("%s(%t)", segment.name, segment.active)
|
|
|
|
e.write(fmt.Sprintf("%-*s - %3d ms - %s\n", largestSegmentNameLength, segmentName, duration, segment.text))
|
2020-12-27 08:53:58 -08:00
|
|
|
}
|
2022-05-05 23:41:58 -07:00
|
|
|
e.write(fmt.Sprintf("\n\x1b[1mRun duration:\x1b[0m %s\n", time.Since(startTime)))
|
2022-01-26 23:38:46 -08:00
|
|
|
e.write(fmt.Sprintf("\n\x1b[1mCache path:\x1b[0m %s\n", e.Env.CachePath()))
|
2022-05-07 07:43:24 -07:00
|
|
|
e.write(fmt.Sprintf("\n\x1b[1mConfig path:\x1b[0m %s\n", e.Env.Flags().Config))
|
2021-11-16 10:59:42 -08:00
|
|
|
e.write("\n\x1b[1mLogs:\x1b[0m\n\n")
|
2022-01-26 23:38:46 -08:00
|
|
|
e.write(e.Env.Logs())
|
2021-04-20 12:30:46 -07:00
|
|
|
return e.string()
|
2020-12-27 08:53:58 -08:00
|
|
|
}
|
|
|
|
|
2022-01-26 23:38:46 -08:00
|
|
|
func (e *Engine) print() string {
|
|
|
|
switch e.Env.Shell() {
|
2022-03-21 23:41:36 -07:00
|
|
|
case shell.ZSH:
|
2022-03-12 13:04:08 -08:00
|
|
|
if !e.Env.Flags().Eval {
|
2021-05-21 13:10:20 -07:00
|
|
|
break
|
2020-12-23 04:31:21 -08:00
|
|
|
}
|
2022-12-08 02:30:21 -08:00
|
|
|
// Warp doesn't support RPROMPT so we need to write it manually
|
|
|
|
if e.isWarp() {
|
2023-01-03 03:21:27 -08:00
|
|
|
e.write(e.Writer.SaveCursorPosition())
|
|
|
|
e.write(e.Writer.CarriageForward())
|
|
|
|
e.write(e.Writer.GetCursorForRightWrite(e.rpromptLength, 0))
|
2022-12-08 02:30:21 -08:00
|
|
|
e.write(e.rprompt)
|
2023-01-03 03:21:27 -08:00
|
|
|
e.write(e.Writer.RestoreCursorPosition())
|
2022-12-08 02:30:21 -08:00
|
|
|
// escape double quotes contained in the prompt
|
|
|
|
prompt := fmt.Sprintf("PS1=\"%s\"", strings.ReplaceAll(e.string(), `"`, `\"`))
|
|
|
|
return prompt
|
|
|
|
}
|
2021-05-21 13:10:20 -07:00
|
|
|
// escape double quotes contained in the prompt
|
2022-04-14 12:12:09 -07:00
|
|
|
prompt := fmt.Sprintf("PS1=\"%s\"", strings.ReplaceAll(e.string(), `"`, `\"`))
|
2021-05-21 13:10:20 -07:00
|
|
|
prompt += fmt.Sprintf("\nRPROMPT=\"%s\"", e.rprompt)
|
|
|
|
return prompt
|
2023-01-03 03:21:27 -08:00
|
|
|
case shell.PWSH, shell.PWSH5, shell.GENERIC, shell.NU:
|
2023-01-02 07:33:25 -08:00
|
|
|
if !e.canWriteRightBlock(true) {
|
2021-05-21 13:10:20 -07:00
|
|
|
break
|
2020-12-17 23:59:45 -08:00
|
|
|
}
|
2023-01-03 03:21:27 -08:00
|
|
|
e.write(e.Writer.SaveCursorPosition())
|
|
|
|
e.write(e.Writer.CarriageForward())
|
|
|
|
e.write(e.Writer.GetCursorForRightWrite(e.rpromptLength, 0))
|
2021-05-21 13:10:20 -07:00
|
|
|
e.write(e.rprompt)
|
2023-01-03 03:21:27 -08:00
|
|
|
e.write(e.Writer.RestoreCursorPosition())
|
2022-06-12 10:55:57 -07:00
|
|
|
case shell.BASH:
|
2023-01-02 07:33:25 -08:00
|
|
|
if !e.canWriteRightBlock(true) {
|
2022-06-12 10:55:57 -07:00
|
|
|
break
|
|
|
|
}
|
|
|
|
// in bash, the entire rprompt needs to be escaped for the prompt to be interpreted correctly
|
2022-12-28 08:30:48 -08:00
|
|
|
// see https://github.com/jandedobbeleer/oh-my-posh/pull/2398
|
2023-01-04 11:44:29 -08:00
|
|
|
writer := &ansi.Writer{}
|
2023-01-03 03:21:27 -08:00
|
|
|
writer.Init(shell.GENERIC)
|
|
|
|
prompt := writer.SaveCursorPosition()
|
|
|
|
prompt += writer.CarriageForward()
|
|
|
|
prompt += writer.GetCursorForRightWrite(e.rpromptLength, 0)
|
2022-06-12 10:55:57 -07:00
|
|
|
prompt += e.rprompt
|
2023-01-03 03:21:27 -08:00
|
|
|
prompt += writer.RestoreCursorPosition()
|
|
|
|
prompt = e.Writer.FormatText(prompt)
|
2022-06-12 10:55:57 -07:00
|
|
|
e.write(prompt)
|
2020-12-15 05:58:15 -08:00
|
|
|
}
|
2022-12-17 13:30:23 -08:00
|
|
|
|
2021-04-20 12:30:46 -07:00
|
|
|
return e.string()
|
2019-03-13 04:14:30 -07:00
|
|
|
}
|
2021-06-05 07:14:44 -07:00
|
|
|
|
2022-03-12 13:04:08 -08:00
|
|
|
func (e *Engine) PrintTooltip(tip string) string {
|
2021-06-05 07:14:44 -07:00
|
|
|
tip = strings.Trim(tip, " ")
|
|
|
|
var tooltip *Segment
|
2022-01-26 23:38:46 -08:00
|
|
|
for _, tp := range e.Config.Tooltips {
|
2021-06-05 07:14:44 -07:00
|
|
|
if !tp.shouldInvokeWithTip(tip) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
tooltip = tp
|
|
|
|
}
|
|
|
|
if tooltip == nil {
|
|
|
|
return ""
|
|
|
|
}
|
2022-01-26 23:38:46 -08:00
|
|
|
if err := tooltip.mapSegmentWithWriter(e.Env); err != nil {
|
2021-06-05 07:14:44 -07:00
|
|
|
return ""
|
|
|
|
}
|
2022-02-02 03:16:39 -08:00
|
|
|
if !tooltip.writer.Enabled() {
|
2021-06-05 07:14:44 -07:00
|
|
|
return ""
|
|
|
|
}
|
2022-05-07 01:12:22 -07:00
|
|
|
tooltip.Enabled = true
|
2021-06-05 07:14:44 -07:00
|
|
|
// little hack to reuse the current logic
|
|
|
|
block := &Block{
|
|
|
|
Alignment: Right,
|
|
|
|
Segments: []*Segment{tooltip},
|
|
|
|
}
|
2022-01-26 23:38:46 -08:00
|
|
|
switch e.Env.Shell() {
|
2023-01-03 03:21:27 -08:00
|
|
|
case shell.ZSH, shell.CMD, shell.FISH, shell.GENERIC:
|
2023-01-11 04:36:25 -08:00
|
|
|
block.Init(e.Env, e.Writer)
|
2022-05-12 05:13:09 -07:00
|
|
|
if !block.Enabled() {
|
|
|
|
return ""
|
|
|
|
}
|
2022-05-07 01:12:22 -07:00
|
|
|
text, _ := block.RenderSegments()
|
2022-02-03 08:36:37 -08:00
|
|
|
return text
|
2022-03-21 23:41:36 -07:00
|
|
|
case shell.PWSH, shell.PWSH5:
|
2022-05-05 23:41:58 -07:00
|
|
|
block.InitPlain(e.Env, e.Config)
|
2022-05-12 05:13:09 -07:00
|
|
|
if !block.Enabled() {
|
|
|
|
return ""
|
|
|
|
}
|
2022-05-07 01:12:22 -07:00
|
|
|
text, length := block.RenderSegments()
|
2023-01-03 03:21:27 -08:00
|
|
|
e.write(e.Writer.ClearAfter())
|
|
|
|
e.write(e.Writer.CarriageForward())
|
|
|
|
e.write(e.Writer.GetCursorForRightWrite(length, 0))
|
2022-02-03 08:36:37 -08:00
|
|
|
e.write(text)
|
2021-06-05 07:14:44 -07:00
|
|
|
return e.string()
|
|
|
|
}
|
2022-05-12 05:13:09 -07:00
|
|
|
return ""
|
2021-06-05 07:14:44 -07:00
|
|
|
}
|
2021-06-15 12:23:08 -07:00
|
|
|
|
2022-02-19 07:49:26 -08:00
|
|
|
type ExtraPromptType int
|
|
|
|
|
|
|
|
const (
|
|
|
|
Transient ExtraPromptType = iota
|
|
|
|
Valid
|
|
|
|
Error
|
2022-02-20 04:56:28 -08:00
|
|
|
Secondary
|
2022-03-15 12:16:04 -07:00
|
|
|
Debug
|
2022-02-19 07:49:26 -08:00
|
|
|
)
|
|
|
|
|
2022-03-12 13:04:08 -08:00
|
|
|
func (e *Engine) PrintExtraPrompt(promptType ExtraPromptType) string {
|
2022-08-02 22:25:42 -07:00
|
|
|
// populate env with latest context
|
|
|
|
e.Env.LoadTemplateCache()
|
2022-03-27 06:38:12 -07:00
|
|
|
var prompt *Segment
|
2022-02-19 07:49:26 -08:00
|
|
|
switch promptType {
|
2022-03-15 12:16:04 -07:00
|
|
|
case Debug:
|
|
|
|
prompt = e.Config.DebugPrompt
|
2022-02-19 07:49:26 -08:00
|
|
|
case Transient:
|
|
|
|
prompt = e.Config.TransientPrompt
|
|
|
|
case Valid:
|
|
|
|
prompt = e.Config.ValidLine
|
|
|
|
case Error:
|
|
|
|
prompt = e.Config.ErrorLine
|
2022-02-20 04:56:28 -08:00
|
|
|
case Secondary:
|
|
|
|
prompt = e.Config.SecondaryPrompt
|
2022-02-19 07:49:26 -08:00
|
|
|
}
|
|
|
|
if prompt == nil {
|
2022-03-27 06:38:12 -07:00
|
|
|
prompt = &Segment{}
|
2021-09-09 11:02:30 -07:00
|
|
|
}
|
2022-02-19 07:49:26 -08:00
|
|
|
getTemplate := func(template string) string {
|
|
|
|
if len(template) != 0 {
|
|
|
|
return template
|
|
|
|
}
|
2022-08-04 23:33:02 -07:00
|
|
|
switch promptType { //nolint: exhaustive
|
2022-03-15 12:16:04 -07:00
|
|
|
case Debug:
|
|
|
|
return "[DBG]: "
|
2022-02-19 07:49:26 -08:00
|
|
|
case Transient:
|
|
|
|
return "{{ .Shell }}> "
|
2022-02-20 04:56:28 -08:00
|
|
|
case Secondary:
|
|
|
|
return "> "
|
2022-02-19 07:49:26 -08:00
|
|
|
default:
|
|
|
|
return ""
|
|
|
|
}
|
2021-06-15 12:23:08 -07:00
|
|
|
}
|
2022-01-26 06:54:36 -08:00
|
|
|
tmpl := &template.Text{
|
2022-02-19 07:49:26 -08:00
|
|
|
Template: getTemplate(prompt.Template),
|
2022-01-26 23:38:46 -08:00
|
|
|
Env: e.Env,
|
2021-06-15 12:23:08 -07:00
|
|
|
}
|
2022-02-19 07:49:26 -08:00
|
|
|
promptText, err := tmpl.Render()
|
2022-01-12 14:39:34 -08:00
|
|
|
if err != nil {
|
2022-02-19 07:49:26 -08:00
|
|
|
promptText = err.Error()
|
2022-01-12 14:39:34 -08:00
|
|
|
}
|
2022-07-08 02:47:08 -07:00
|
|
|
foreground := prompt.ForegroundTemplates.FirstMatch(nil, e.Env, prompt.Foreground)
|
|
|
|
background := prompt.BackgroundTemplates.FirstMatch(nil, e.Env, prompt.Background)
|
2022-03-24 04:53:20 -07:00
|
|
|
e.Writer.SetColors(background, foreground)
|
|
|
|
e.Writer.Write(background, foreground, promptText)
|
2022-01-26 23:38:46 -08:00
|
|
|
switch e.Env.Shell() {
|
2022-03-21 23:41:36 -07:00
|
|
|
case shell.ZSH:
|
2021-07-03 09:38:23 -07:00
|
|
|
// escape double quotes contained in the prompt
|
2022-02-03 08:36:37 -08:00
|
|
|
str, _ := e.Writer.String()
|
2022-02-20 04:56:28 -08:00
|
|
|
if promptType == Transient {
|
|
|
|
prompt := fmt.Sprintf("PS1=\"%s\"", strings.ReplaceAll(str, "\"", "\"\""))
|
|
|
|
// empty RPROMPT
|
|
|
|
prompt += "\nRPROMPT=\"\""
|
|
|
|
return prompt
|
|
|
|
}
|
|
|
|
return str
|
2023-01-03 03:21:27 -08:00
|
|
|
case shell.PWSH, shell.PWSH5, shell.CMD, shell.BASH, shell.FISH, shell.NU, shell.GENERIC:
|
2022-12-17 13:30:23 -08:00
|
|
|
// Return the string and empty our buffer
|
2022-02-03 08:36:37 -08:00
|
|
|
str, _ := e.Writer.String()
|
|
|
|
return str
|
2021-06-23 13:00:40 -07:00
|
|
|
}
|
2021-07-03 09:38:23 -07:00
|
|
|
return ""
|
2021-06-15 12:23:08 -07:00
|
|
|
}
|
2021-11-13 10:35:15 -08:00
|
|
|
|
2022-03-12 13:04:08 -08:00
|
|
|
func (e *Engine) PrintRPrompt() string {
|
2021-11-13 10:35:15 -08:00
|
|
|
filterRPromptBlock := func(blocks []*Block) *Block {
|
|
|
|
for _, block := range blocks {
|
|
|
|
if block.Type == RPrompt {
|
|
|
|
return block
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2022-01-26 23:38:46 -08:00
|
|
|
block := filterRPromptBlock(e.Config.Blocks)
|
2021-11-13 10:35:15 -08:00
|
|
|
if block == nil {
|
|
|
|
return ""
|
|
|
|
}
|
2023-01-11 04:36:25 -08:00
|
|
|
block.Init(e.Env, e.Writer)
|
2022-05-05 23:41:58 -07:00
|
|
|
if !block.Enabled() {
|
2021-11-13 10:35:15 -08:00
|
|
|
return ""
|
|
|
|
}
|
2022-05-07 01:12:22 -07:00
|
|
|
text, length := block.RenderSegments()
|
2022-02-03 08:36:37 -08:00
|
|
|
e.rpromptLength = length
|
|
|
|
return text
|
2021-11-13 10:35:15 -08:00
|
|
|
}
|