mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2025-03-05 20:49:04 -08:00
refactor: remove env from template/text
This commit is contained in:
parent
701cd499df
commit
cefe985bf7
10
src/cache/template.go
vendored
10
src/cache/template.go
vendored
|
@ -1,13 +1,10 @@
|
||||||
package cache
|
package cache
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/maps"
|
"github.com/jandedobbeleer/oh-my-posh/src/maps"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Template struct {
|
type Template struct {
|
||||||
Env map[string]string
|
|
||||||
SegmentsCache maps.Simple
|
SegmentsCache maps.Simple
|
||||||
Segments *maps.Concurrent
|
Segments *maps.Concurrent
|
||||||
Var maps.Simple
|
Var maps.Simple
|
||||||
|
@ -24,10 +21,9 @@ type Template struct {
|
||||||
PromptCount int
|
PromptCount int
|
||||||
SHLVL int
|
SHLVL int
|
||||||
Jobs int
|
Jobs int
|
||||||
sync.RWMutex
|
WSL bool
|
||||||
WSL bool
|
Root bool
|
||||||
Root bool
|
Initialized bool
|
||||||
Initialized bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Template) AddSegmentData(key string, value any) {
|
func (t *Template) AddSegmentData(key string, value any) {
|
||||||
|
|
|
@ -69,7 +69,7 @@ Exports the config to an image file using customized output options.`,
|
||||||
env.Var = cfg.Var
|
env.Var = cfg.Var
|
||||||
|
|
||||||
terminal.Init(shell.GENERIC)
|
terminal.Init(shell.GENERIC)
|
||||||
terminal.BackgroundColor = cfg.TerminalBackground.ResolveTemplate(env)
|
terminal.BackgroundColor = cfg.TerminalBackground.ResolveTemplate()
|
||||||
terminal.Colors = cfg.MakeColors()
|
terminal.Colors = cfg.MakeColors()
|
||||||
|
|
||||||
eng := &prompt.Engine{
|
eng := &prompt.Engine{
|
||||||
|
|
|
@ -55,7 +55,7 @@ func createDebugCmd() *cobra.Command {
|
||||||
env.Var = cfg.Var
|
env.Var = cfg.Var
|
||||||
|
|
||||||
terminal.Init(shell.GENERIC)
|
terminal.Init(shell.GENERIC)
|
||||||
terminal.BackgroundColor = cfg.TerminalBackground.ResolveTemplate(env)
|
terminal.BackgroundColor = cfg.TerminalBackground.ResolveTemplate()
|
||||||
terminal.Colors = cfg.MakeColors()
|
terminal.Colors = cfg.MakeColors()
|
||||||
terminal.Plain = plain
|
terminal.Plain = plain
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/config"
|
"github.com/jandedobbeleer/oh-my-posh/src/config"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/shell"
|
"github.com/jandedobbeleer/oh-my-posh/src/shell"
|
||||||
|
"github.com/jandedobbeleer/oh-my-posh/src/template"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -67,6 +68,8 @@ See the documentation to initialize your shell: https://ohmyposh.dev/docs/instal
|
||||||
env.Init()
|
env.Init()
|
||||||
defer env.Close()
|
defer env.Close()
|
||||||
|
|
||||||
|
template.Init(env)
|
||||||
|
|
||||||
cfg := config.Load(env)
|
cfg := config.Load(env)
|
||||||
|
|
||||||
feats := cfg.Features()
|
feats := cfg.Features()
|
||||||
|
|
|
@ -120,7 +120,7 @@ func (c Ansi) ToForeground() Ansi {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Ansi) ResolveTemplate(env runtime.Environment) Ansi {
|
func (c Ansi) ResolveTemplate() Ansi {
|
||||||
if c.IsEmpty() {
|
if c.IsEmpty() {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
@ -132,7 +132,6 @@ func (c Ansi) ResolveTemplate(env runtime.Environment) Ansi {
|
||||||
tmpl := &template.Text{
|
tmpl := &template.Text{
|
||||||
Template: string(c),
|
Template: string(c),
|
||||||
Context: nil,
|
Context: nil,
|
||||||
Env: env,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
text, err := tmpl.Render()
|
text, err := tmpl.Render()
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
cache_ "github.com/jandedobbeleer/oh-my-posh/src/cache/mock"
|
cache_ "github.com/jandedobbeleer/oh-my-posh/src/cache/mock"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
||||||
|
"github.com/jandedobbeleer/oh-my-posh/src/template"
|
||||||
|
|
||||||
testify_ "github.com/stretchr/testify/mock"
|
testify_ "github.com/stretchr/testify/mock"
|
||||||
)
|
)
|
||||||
|
@ -81,15 +82,14 @@ func TestAnsiRender(t *testing.T) {
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
env := new(mock.Environment)
|
env := new(mock.Environment)
|
||||||
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
||||||
env.On("TemplateCache").Return(&cache.Template{
|
env.On("TemplateCache").Return(&cache.Template{})
|
||||||
Env: map[string]string{
|
env.On("Getenv", "TERM_PROGRAM").Return(tc.Term)
|
||||||
"TERM_PROGRAM": tc.Term,
|
env.On("Shell").Return("foo")
|
||||||
},
|
|
||||||
})
|
template.Init(env)
|
||||||
env.On("Flags").Return(&runtime.Flags{})
|
|
||||||
|
|
||||||
ansi := Ansi("{{ if eq \"vscode\" .Env.TERM_PROGRAM }}#123456{{end}}")
|
ansi := Ansi("{{ if eq \"vscode\" .Env.TERM_PROGRAM }}#123456{{end}}")
|
||||||
got := ansi.ResolveTemplate(env)
|
got := ansi.ResolveTemplate()
|
||||||
|
|
||||||
assert.Equal(t, tc.Expected, got, tc.Case)
|
assert.Equal(t, tc.Expected, got, tc.Case)
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,6 @@ func (cfg *Config) getPalette() color.Palette {
|
||||||
|
|
||||||
tmpl := &template.Text{
|
tmpl := &template.Text{
|
||||||
Template: cfg.Palettes.Template,
|
Template: cfg.Palettes.Template,
|
||||||
Env: cfg.env,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
key, err := tmpl.Render()
|
key, err := tmpl.Render()
|
||||||
|
|
|
@ -5,8 +5,8 @@ import (
|
||||||
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/cache"
|
"github.com/jandedobbeleer/oh-my-posh/src/cache"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/color"
|
"github.com/jandedobbeleer/oh-my-posh/src/color"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
||||||
|
"github.com/jandedobbeleer/oh-my-posh/src/template"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
testify_ "github.com/stretchr/testify/mock"
|
testify_ "github.com/stretchr/testify/mock"
|
||||||
|
@ -93,11 +93,12 @@ func TestGetPalette(t *testing.T) {
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
env := &mock.Environment{}
|
env := &mock.Environment{}
|
||||||
env.On("TemplateCache").Return(&cache.Template{
|
env.On("TemplateCache").Return(&cache.Template{
|
||||||
Env: map[string]string{},
|
|
||||||
Shell: "bash",
|
Shell: "bash",
|
||||||
})
|
})
|
||||||
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
||||||
env.On("Flags").Return(&runtime.Flags{})
|
env.On("Shell").Return("bash")
|
||||||
|
|
||||||
|
template.Init(env)
|
||||||
|
|
||||||
cfg := &Config{
|
cfg := &Config{
|
||||||
env: env,
|
env: env,
|
||||||
|
|
|
@ -20,17 +20,19 @@ import (
|
||||||
// SegmentStyle the style of segment, for more information, see the constants
|
// SegmentStyle the style of segment, for more information, see the constants
|
||||||
type SegmentStyle string
|
type SegmentStyle string
|
||||||
|
|
||||||
func (s *SegmentStyle) resolve(env runtime.Environment, context any) SegmentStyle {
|
func (s *SegmentStyle) resolve(context any) SegmentStyle {
|
||||||
txtTemplate := &template.Text{
|
txtTemplate := &template.Text{
|
||||||
Context: context,
|
Context: context,
|
||||||
Env: env,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
txtTemplate.Template = string(*s)
|
txtTemplate.Template = string(*s)
|
||||||
value, err := txtTemplate.Render()
|
value, err := txtTemplate.Render()
|
||||||
|
|
||||||
// default to Plain
|
// default to Plain
|
||||||
if err != nil || len(value) == 0 {
|
if err != nil || len(value) == 0 {
|
||||||
return Plain
|
return Plain
|
||||||
}
|
}
|
||||||
|
|
||||||
return SegmentStyle(value)
|
return SegmentStyle(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,7 +220,7 @@ func (segment *Segment) SetText() {
|
||||||
|
|
||||||
func (segment *Segment) string() string {
|
func (segment *Segment) string() string {
|
||||||
if !segment.Templates.Empty() {
|
if !segment.Templates.Empty() {
|
||||||
templatesResult := segment.Templates.Resolve(segment.writer, segment.env, "", segment.TemplatesLogic)
|
templatesResult := segment.Templates.Resolve(segment.writer, "", segment.TemplatesLogic)
|
||||||
if len(segment.Template) == 0 {
|
if len(segment.Template) == 0 {
|
||||||
return templatesResult
|
return templatesResult
|
||||||
}
|
}
|
||||||
|
@ -231,7 +233,6 @@ func (segment *Segment) string() string {
|
||||||
tmpl := &template.Text{
|
tmpl := &template.Text{
|
||||||
Template: segment.Template,
|
Template: segment.Template,
|
||||||
Context: segment.writer,
|
Context: segment.writer,
|
||||||
Env: segment.env,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
text, err := tmpl.Render()
|
text, err := tmpl.Render()
|
||||||
|
@ -282,7 +283,7 @@ func (segment *Segment) cwdExcluded() bool {
|
||||||
|
|
||||||
func (segment *Segment) ResolveForeground() color.Ansi {
|
func (segment *Segment) ResolveForeground() color.Ansi {
|
||||||
if len(segment.ForegroundTemplates) != 0 {
|
if len(segment.ForegroundTemplates) != 0 {
|
||||||
match := segment.ForegroundTemplates.FirstMatch(segment.writer, segment.env, segment.Foreground.String())
|
match := segment.ForegroundTemplates.FirstMatch(segment.writer, segment.Foreground.String())
|
||||||
segment.Foreground = color.Ansi(match)
|
segment.Foreground = color.Ansi(match)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,7 +292,7 @@ func (segment *Segment) ResolveForeground() color.Ansi {
|
||||||
|
|
||||||
func (segment *Segment) ResolveBackground() color.Ansi {
|
func (segment *Segment) ResolveBackground() color.Ansi {
|
||||||
if len(segment.BackgroundTemplates) != 0 {
|
if len(segment.BackgroundTemplates) != 0 {
|
||||||
match := segment.BackgroundTemplates.FirstMatch(segment.writer, segment.env, segment.Background.String())
|
match := segment.BackgroundTemplates.FirstMatch(segment.writer, segment.Background.String())
|
||||||
segment.Background = color.Ansi(match)
|
segment.Background = color.Ansi(match)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,7 +304,7 @@ func (segment *Segment) ResolveStyle() SegmentStyle {
|
||||||
return segment.styleCache
|
return segment.styleCache
|
||||||
}
|
}
|
||||||
|
|
||||||
segment.styleCache = segment.Style.resolve(segment.env, segment.writer)
|
segment.styleCache = segment.Style.resolve(segment.writer)
|
||||||
|
|
||||||
return segment.styleCache
|
return segment.styleCache
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/cache"
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/color"
|
"github.com/jandedobbeleer/oh-my-posh/src/color"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
||||||
|
@ -12,7 +11,6 @@ import (
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/segments"
|
"github.com/jandedobbeleer/oh-my-posh/src/segments"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
testify_ "github.com/stretchr/testify/mock"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -144,19 +142,11 @@ func TestGetColors(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
env := new(mock.Environment)
|
|
||||||
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
|
||||||
env.On("TemplateCache").Return(&cache.Template{
|
|
||||||
Env: make(map[string]string),
|
|
||||||
})
|
|
||||||
env.On("Flags").Return(&runtime.Flags{})
|
|
||||||
|
|
||||||
segment := &Segment{
|
segment := &Segment{
|
||||||
writer: &segments.Aws{
|
writer: &segments.Aws{
|
||||||
Profile: tc.Profile,
|
Profile: tc.Profile,
|
||||||
Region: tc.Region,
|
Region: tc.Region,
|
||||||
},
|
},
|
||||||
env: env,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if tc.Background {
|
if tc.Background {
|
||||||
|
|
|
@ -86,7 +86,6 @@ func (e *Engine) pwd() {
|
||||||
// Allow template logic to define when to enable the PWD (when supported)
|
// Allow template logic to define when to enable the PWD (when supported)
|
||||||
tmpl := &template.Text{
|
tmpl := &template.Text{
|
||||||
Template: e.Config.PWD,
|
Template: e.Config.PWD,
|
||||||
Env: e.Env,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pwdType, err := tmpl.Render()
|
pwdType, err := tmpl.Render()
|
||||||
|
@ -159,7 +158,6 @@ func (e *Engine) shouldFill(filler string, padLength int) (string, bool) {
|
||||||
func (e *Engine) getTitleTemplateText() string {
|
func (e *Engine) getTitleTemplateText() string {
|
||||||
tmpl := &template.Text{
|
tmpl := &template.Text{
|
||||||
Template: e.Config.ConsoleTitleTemplate,
|
Template: e.Config.ConsoleTitleTemplate,
|
||||||
Env: e.Env,
|
|
||||||
}
|
}
|
||||||
if text, err := tmpl.Render(); err == nil {
|
if text, err := tmpl.Render(); err == nil {
|
||||||
return text
|
return text
|
||||||
|
@ -520,11 +518,13 @@ func New(flags *runtime.Flags) *Engine {
|
||||||
env.Init()
|
env.Init()
|
||||||
cfg := config.Load(env)
|
cfg := config.Load(env)
|
||||||
|
|
||||||
|
template.Init(env)
|
||||||
|
|
||||||
env.Var = cfg.Var
|
env.Var = cfg.Var
|
||||||
flags.HasTransient = cfg.TransientPrompt != nil
|
flags.HasTransient = cfg.TransientPrompt != nil
|
||||||
|
|
||||||
terminal.Init(env.Shell())
|
terminal.Init(env.Shell())
|
||||||
terminal.BackgroundColor = cfg.TerminalBackground.ResolveTemplate(env)
|
terminal.BackgroundColor = cfg.TerminalBackground.ResolveTemplate()
|
||||||
terminal.Colors = cfg.MakeColors()
|
terminal.Colors = cfg.MakeColors()
|
||||||
terminal.Plain = flags.Plain
|
terminal.Plain = flags.Plain
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/shell"
|
"github.com/jandedobbeleer/oh-my-posh/src/shell"
|
||||||
|
"github.com/jandedobbeleer/oh-my-posh/src/template"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/terminal"
|
"github.com/jandedobbeleer/oh-my-posh/src/terminal"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -92,12 +93,11 @@ func TestPrintPWD(t *testing.T) {
|
||||||
env.On("Host").Return("host", nil)
|
env.On("Host").Return("host", nil)
|
||||||
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
||||||
env.On("TemplateCache").Return(&cache.Template{
|
env.On("TemplateCache").Return(&cache.Template{
|
||||||
Env: make(map[string]string),
|
|
||||||
Shell: "shell",
|
Shell: "shell",
|
||||||
})
|
})
|
||||||
env.On("Flags").Return(&runtime.Flags{})
|
|
||||||
|
|
||||||
terminal.Init(shell.GENERIC)
|
terminal.Init(shell.GENERIC)
|
||||||
|
template.Init(env)
|
||||||
|
|
||||||
engine := &Engine{
|
engine := &Engine{
|
||||||
Env: env,
|
Env: env,
|
||||||
|
@ -127,7 +127,7 @@ func engineRender() {
|
||||||
cfg := config.Load(env)
|
cfg := config.Load(env)
|
||||||
|
|
||||||
terminal.Init(shell.GENERIC)
|
terminal.Init(shell.GENERIC)
|
||||||
terminal.BackgroundColor = cfg.TerminalBackground.ResolveTemplate(env)
|
terminal.BackgroundColor = cfg.TerminalBackground.ResolveTemplate()
|
||||||
terminal.Colors = cfg.MakeColors()
|
terminal.Colors = cfg.MakeColors()
|
||||||
|
|
||||||
engine := &Engine{
|
engine := &Engine{
|
||||||
|
@ -185,11 +185,7 @@ func TestGetTitle(t *testing.T) {
|
||||||
env.On("Home").Return("/usr/home")
|
env.On("Home").Return("/usr/home")
|
||||||
env.On("PathSeparator").Return(tc.PathSeparator)
|
env.On("PathSeparator").Return(tc.PathSeparator)
|
||||||
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
||||||
env.On("Flags").Return(&runtime.Flags{})
|
|
||||||
env.On("TemplateCache").Return(&cache.Template{
|
env.On("TemplateCache").Return(&cache.Template{
|
||||||
Env: map[string]string{
|
|
||||||
"USERDOMAIN": "MyCompany",
|
|
||||||
},
|
|
||||||
Shell: tc.ShellName,
|
Shell: tc.ShellName,
|
||||||
UserName: "MyUser",
|
UserName: "MyUser",
|
||||||
Root: tc.Root,
|
Root: tc.Root,
|
||||||
|
@ -197,8 +193,11 @@ func TestGetTitle(t *testing.T) {
|
||||||
PWD: tc.Cwd,
|
PWD: tc.Cwd,
|
||||||
Folder: "vagrant",
|
Folder: "vagrant",
|
||||||
})
|
})
|
||||||
|
env.On("Getenv", "USERDOMAIN").Return("MyCompany")
|
||||||
|
env.On("Shell").Return(tc.ShellName)
|
||||||
|
|
||||||
terminal.Init(shell.GENERIC)
|
terminal.Init(shell.GENERIC)
|
||||||
|
template.Init(env)
|
||||||
|
|
||||||
engine := &Engine{
|
engine := &Engine{
|
||||||
Config: &config.Config{
|
Config: &config.Config{
|
||||||
|
@ -249,18 +248,17 @@ func TestGetConsoleTitleIfGethostnameReturnsError(t *testing.T) {
|
||||||
env.On("Pwd").Return(tc.Cwd)
|
env.On("Pwd").Return(tc.Cwd)
|
||||||
env.On("Home").Return("/usr/home")
|
env.On("Home").Return("/usr/home")
|
||||||
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
||||||
env.On("Flags").Return(&runtime.Flags{})
|
|
||||||
env.On("TemplateCache").Return(&cache.Template{
|
env.On("TemplateCache").Return(&cache.Template{
|
||||||
Env: map[string]string{
|
|
||||||
"USERDOMAIN": "MyCompany",
|
|
||||||
},
|
|
||||||
Shell: tc.ShellName,
|
Shell: tc.ShellName,
|
||||||
UserName: "MyUser",
|
UserName: "MyUser",
|
||||||
Root: tc.Root,
|
Root: tc.Root,
|
||||||
HostName: "",
|
HostName: "",
|
||||||
})
|
})
|
||||||
|
env.On("Getenv", "USERDOMAIN").Return("MyCompany")
|
||||||
|
env.On("Shell").Return(tc.ShellName)
|
||||||
|
|
||||||
terminal.Init(shell.GENERIC)
|
terminal.Init(shell.GENERIC)
|
||||||
|
template.Init(env)
|
||||||
|
|
||||||
engine := &Engine{
|
engine := &Engine{
|
||||||
Config: &config.Config{
|
Config: &config.Config{
|
||||||
|
|
|
@ -60,7 +60,6 @@ func (e *Engine) ExtraPrompt(promptType ExtraPromptType) string {
|
||||||
|
|
||||||
tmpl := &template.Text{
|
tmpl := &template.Text{
|
||||||
Template: getTemplate(prompt.Template),
|
Template: getTemplate(prompt.Template),
|
||||||
Env: e.Env,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
promptText, err := tmpl.Render()
|
promptText, err := tmpl.Render()
|
||||||
|
@ -78,8 +77,8 @@ func (e *Engine) ExtraPrompt(promptType ExtraPromptType) string {
|
||||||
e.write(terminal.PromptStart())
|
e.write(terminal.PromptStart())
|
||||||
}
|
}
|
||||||
|
|
||||||
foreground := color.Ansi(prompt.ForegroundTemplates.FirstMatch(nil, e.Env, string(prompt.Foreground)))
|
foreground := color.Ansi(prompt.ForegroundTemplates.FirstMatch(nil, string(prompt.Foreground)))
|
||||||
background := color.Ansi(prompt.BackgroundTemplates.FirstMatch(nil, e.Env, string(prompt.Background)))
|
background := color.Ansi(prompt.BackgroundTemplates.FirstMatch(nil, string(prompt.Background)))
|
||||||
terminal.SetColors(background, foreground)
|
terminal.SetColors(background, foreground)
|
||||||
terminal.Write(background, foreground, promptText)
|
terminal.Write(background, foreground, promptText)
|
||||||
|
|
||||||
|
|
|
@ -641,8 +641,6 @@ func (term *Terminal) Logs() string {
|
||||||
func (term *Terminal) TemplateCache() *cache.Template {
|
func (term *Terminal) TemplateCache() *cache.Template {
|
||||||
defer term.Trace(time.Now())
|
defer term.Trace(time.Now())
|
||||||
tmplCache := term.tmplCache
|
tmplCache := term.tmplCache
|
||||||
tmplCache.Lock()
|
|
||||||
defer tmplCache.Unlock()
|
|
||||||
|
|
||||||
if tmplCache.Initialized {
|
if tmplCache.Initialized {
|
||||||
return tmplCache
|
return tmplCache
|
||||||
|
@ -655,7 +653,6 @@ func (term *Terminal) TemplateCache() *cache.Template {
|
||||||
tmplCache.WSL = term.IsWsl()
|
tmplCache.WSL = term.IsWsl()
|
||||||
tmplCache.Segments = maps.NewConcurrent()
|
tmplCache.Segments = maps.NewConcurrent()
|
||||||
tmplCache.PromptCount = term.CmdFlags.PromptCount
|
tmplCache.PromptCount = term.CmdFlags.PromptCount
|
||||||
tmplCache.Env = make(map[string]string)
|
|
||||||
tmplCache.Var = make(map[string]any)
|
tmplCache.Var = make(map[string]any)
|
||||||
tmplCache.Jobs = term.CmdFlags.JobCount
|
tmplCache.Jobs = term.CmdFlags.JobCount
|
||||||
|
|
||||||
|
@ -663,17 +660,6 @@ func (term *Terminal) TemplateCache() *cache.Template {
|
||||||
tmplCache.Var = term.Var
|
tmplCache.Var = term.Var
|
||||||
}
|
}
|
||||||
|
|
||||||
const separator = "="
|
|
||||||
values := os.Environ()
|
|
||||||
term.DebugF("environment: %v", values)
|
|
||||||
for value := range values {
|
|
||||||
key, val, valid := strings.Cut(values[value], separator)
|
|
||||||
if !valid {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
tmplCache.Env[key] = val
|
|
||||||
}
|
|
||||||
|
|
||||||
pwd := term.Pwd()
|
pwd := term.Pwd()
|
||||||
tmplCache.PWD = ReplaceHomeDirPrefixWithTilde(term, pwd)
|
tmplCache.PWD = ReplaceHomeDirPrefixWithTilde(term, pwd)
|
||||||
|
|
||||||
|
|
|
@ -261,14 +261,16 @@ func (l *language) buildVersionURL() {
|
||||||
if len(versionURLTemplate) == 0 {
|
if len(versionURLTemplate) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpl := &template.Text{
|
tmpl := &template.Text{
|
||||||
Template: versionURLTemplate,
|
Template: versionURLTemplate,
|
||||||
Context: l.version,
|
Context: l.version,
|
||||||
Env: l.env,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
url, err := tmpl.Render()
|
url, err := tmpl.Render()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
l.version.URL = url
|
l.version.URL = url
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,13 +3,11 @@ package segments
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/cache"
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
testify_ "github.com/stretchr/testify/mock"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -60,12 +58,6 @@ func bootStrapLanguageTest(args *languageArgs) *language {
|
||||||
|
|
||||||
env.On("Pwd").Return(cwd)
|
env.On("Pwd").Return(cwd)
|
||||||
env.On("Home").Return(home)
|
env.On("Home").Return(home)
|
||||||
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
|
||||||
env.On("Flags").Return(&runtime.Flags{})
|
|
||||||
|
|
||||||
env.On("TemplateCache").Return(&cache.Template{
|
|
||||||
Env: make(map[string]string),
|
|
||||||
})
|
|
||||||
|
|
||||||
if args.properties == nil {
|
if args.properties == nil {
|
||||||
args.properties = properties.Map{}
|
args.properties = properties.Map{}
|
||||||
|
@ -549,11 +541,6 @@ func getMockedLanguageEnv(params *mockedLanguageParams) (*mock.Environment, prop
|
||||||
env.On("HasFiles", params.extension).Return(true)
|
env.On("HasFiles", params.extension).Return(true)
|
||||||
env.On("Pwd").Return("/usr/home/project")
|
env.On("Pwd").Return("/usr/home/project")
|
||||||
env.On("Home").Return("/usr/home")
|
env.On("Home").Return("/usr/home")
|
||||||
env.On("TemplateCache").Return(&cache.Template{
|
|
||||||
Env: make(map[string]string),
|
|
||||||
})
|
|
||||||
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
|
||||||
env.On("Flags").Return(&runtime.Flags{})
|
|
||||||
|
|
||||||
props := properties.Map{
|
props := properties.Map{
|
||||||
properties.FetchVersion: true,
|
properties.FetchVersion: true,
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/cache"
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -26,19 +25,18 @@ func TestGetNodePackageVersion(t *testing.T) {
|
||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
var env = new(mock.Environment)
|
var env = new(mock.Environment)
|
||||||
// mock getVersion methods
|
|
||||||
env.On("Pwd").Return("posh")
|
env.On("Pwd").Return("posh")
|
||||||
path := filepath.Join("posh", "node_modules", "nx")
|
path := filepath.Join("posh", "node_modules", "nx")
|
||||||
env.On("HasFilesInDir", path, "package.json").Return(!tc.NoFiles)
|
env.On("HasFilesInDir", path, "package.json").Return(!tc.NoFiles)
|
||||||
env.On("FileContent", filepath.Join(path, "package.json")).Return(tc.PackageJSON)
|
env.On("FileContent", filepath.Join(path, "package.json")).Return(tc.PackageJSON)
|
||||||
env.On("TemplateCache").Return(&cache.Template{
|
|
||||||
Env: make(map[string]string),
|
|
||||||
})
|
|
||||||
got, err := getNodePackageVersion(env, "nx")
|
got, err := getNodePackageVersion(env, "nx")
|
||||||
|
|
||||||
if tc.ShouldFail {
|
if tc.ShouldFail {
|
||||||
assert.Error(t, err, tc.Case)
|
assert.Error(t, err, tc.Case)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Nil(t, err, tc.Case)
|
assert.Nil(t, err, tc.Case)
|
||||||
assert.Equal(t, tc.Version, got, tc.Case)
|
assert.Equal(t, tc.Version, got, tc.Case)
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,7 +90,6 @@ func TestOSInfo(t *testing.T) {
|
||||||
env.On("GOOS").Return(tc.GOOS)
|
env.On("GOOS").Return(tc.GOOS)
|
||||||
env.On("Platform").Return(tc.Platform)
|
env.On("Platform").Return(tc.Platform)
|
||||||
env.On("TemplateCache").Return(&cache.Template{
|
env.On("TemplateCache").Return(&cache.Template{
|
||||||
Env: make(map[string]string),
|
|
||||||
WSL: tc.IsWSL,
|
WSL: tc.IsWSL,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -247,7 +247,6 @@ func (pt *Path) getMaxWidth() int {
|
||||||
tmpl := &template.Text{
|
tmpl := &template.Text{
|
||||||
Template: width,
|
Template: width,
|
||||||
Context: pt,
|
Context: pt,
|
||||||
Env: pt.env,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
text, err := tmpl.Render()
|
text, err := tmpl.Render()
|
||||||
|
@ -279,7 +278,6 @@ func (pt *Path) getFolderSeparator() string {
|
||||||
tmpl := &template.Text{
|
tmpl := &template.Text{
|
||||||
Template: separatorTemplate,
|
Template: separatorTemplate,
|
||||||
Context: pt,
|
Context: pt,
|
||||||
Env: pt.env,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
text, err := tmpl.Render()
|
text, err := tmpl.Render()
|
||||||
|
@ -573,7 +571,6 @@ func (pt *Path) setMappedLocations() {
|
||||||
tmpl := &template.Text{
|
tmpl := &template.Text{
|
||||||
Template: key,
|
Template: key,
|
||||||
Context: pt,
|
Context: pt,
|
||||||
Env: pt.env,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
path, err := tmpl.Render()
|
path, err := tmpl.Render()
|
||||||
|
|
|
@ -33,25 +33,28 @@ func renderTemplateNoTrimSpace(env *mock.Environment, segmentTemplate string, co
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !found {
|
if !found {
|
||||||
env.On("TemplateCache").Return(&cache.Template{
|
env.On("TemplateCache").Return(&cache.Template{})
|
||||||
Env: make(map[string]string),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
env.On("Error", testify_.Anything)
|
env.On("Error", testify_.Anything)
|
||||||
env.On("Debug", testify_.Anything)
|
env.On("Debug", testify_.Anything)
|
||||||
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
||||||
env.On("Flags").Return(&runtime.Flags{})
|
env.On("Shell").Return("foo")
|
||||||
|
|
||||||
|
template.Init(env)
|
||||||
|
|
||||||
tmpl := &template.Text{
|
tmpl := &template.Text{
|
||||||
Template: segmentTemplate,
|
Template: segmentTemplate,
|
||||||
Context: context,
|
Context: context,
|
||||||
Env: env,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
text, err := tmpl.Render()
|
text, err := tmpl.Render()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err.Error()
|
return err.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
return text
|
return text
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,7 +160,9 @@ func TestParent(t *testing.T) {
|
||||||
FolderSeparatorIcon: tc.FolderSeparatorIcon,
|
FolderSeparatorIcon: tc.FolderSeparatorIcon,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
path.setPaths()
|
path.setPaths()
|
||||||
|
|
||||||
got := path.Parent()
|
got := path.Parent()
|
||||||
assert.EqualValues(t, tc.Expected, got, tc.Case)
|
assert.EqualValues(t, tc.Expected, got, tc.Case)
|
||||||
}
|
}
|
||||||
|
@ -947,7 +952,7 @@ func TestFullPathCustomMappedLocations(t *testing.T) {
|
||||||
PathSeparator string
|
PathSeparator string
|
||||||
Expected string
|
Expected string
|
||||||
}{
|
}{
|
||||||
{Pwd: abcd, MappedLocations: map[string]string{"{{ .Env.HOME }}/d": "#"}, Expected: "#"},
|
{Pwd: homeDir + "/d", MappedLocations: map[string]string{"{{ .Env.HOME }}/d": "#"}, Expected: "#"},
|
||||||
{Pwd: abcd, MappedLocations: map[string]string{abcd: "#"}, Expected: "#"},
|
{Pwd: abcd, MappedLocations: map[string]string{abcd: "#"}, Expected: "#"},
|
||||||
{Pwd: "\\a\\b\\c\\d", MappedLocations: map[string]string{"\\a\\b": "#"}, GOOS: runtime.WINDOWS, PathSeparator: "\\", Expected: "#\\c\\d"},
|
{Pwd: "\\a\\b\\c\\d", MappedLocations: map[string]string{"\\a\\b": "#"}, GOOS: runtime.WINDOWS, PathSeparator: "\\", Expected: "#\\c\\d"},
|
||||||
{Pwd: abcd, MappedLocations: map[string]string{"/a/b": "#"}, Expected: "#/c/d"},
|
{Pwd: abcd, MappedLocations: map[string]string{"/a/b": "#"}, Expected: "#/c/d"},
|
||||||
|
@ -980,11 +985,10 @@ func TestFullPathCustomMappedLocations(t *testing.T) {
|
||||||
env.On("Flags").Return(args)
|
env.On("Flags").Return(args)
|
||||||
env.On("Shell").Return(shell.GENERIC)
|
env.On("Shell").Return(shell.GENERIC)
|
||||||
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
||||||
env.On("TemplateCache").Return(&cache.Template{
|
env.On("TemplateCache").Return(&cache.Template{})
|
||||||
Env: map[string]string{
|
env.On("Getenv", "HOME").Return(homeDir)
|
||||||
"HOME": "/a/b/c",
|
|
||||||
},
|
template.Init(env)
|
||||||
})
|
|
||||||
|
|
||||||
path := &Path{
|
path := &Path{
|
||||||
env: env,
|
env: env,
|
||||||
|
@ -997,6 +1001,7 @@ func TestFullPathCustomMappedLocations(t *testing.T) {
|
||||||
|
|
||||||
path.setPaths()
|
path.setPaths()
|
||||||
path.setStyle()
|
path.setStyle()
|
||||||
|
|
||||||
got := renderTemplateNoTrimSpace(env, "{{ .Path }}", path)
|
got := renderTemplateNoTrimSpace(env, "{{ .Path }}", path)
|
||||||
assert.Equal(t, tc.Expected, got)
|
assert.Equal(t, tc.Expected, got)
|
||||||
}
|
}
|
||||||
|
@ -1015,6 +1020,9 @@ func TestFolderPathCustomMappedLocations(t *testing.T) {
|
||||||
env.On("Flags").Return(args)
|
env.On("Flags").Return(args)
|
||||||
env.On("Shell").Return(shell.GENERIC)
|
env.On("Shell").Return(shell.GENERIC)
|
||||||
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
||||||
|
|
||||||
|
template.Init(env)
|
||||||
|
|
||||||
path := &Path{
|
path := &Path{
|
||||||
env: env,
|
env: env,
|
||||||
props: properties.Map{
|
props: properties.Map{
|
||||||
|
@ -1024,8 +1032,10 @@ func TestFolderPathCustomMappedLocations(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
path.setPaths()
|
path.setPaths()
|
||||||
path.setStyle()
|
path.setStyle()
|
||||||
|
|
||||||
got := renderTemplateNoTrimSpace(env, "{{ .Path }}", path)
|
got := renderTemplateNoTrimSpace(env, "{{ .Path }}", path)
|
||||||
assert.Equal(t, "#", got)
|
assert.Equal(t, "#", got)
|
||||||
}
|
}
|
||||||
|
@ -1404,6 +1414,9 @@ func TestGetPwd(t *testing.T) {
|
||||||
env.On("Flags").Return(args)
|
env.On("Flags").Return(args)
|
||||||
env.On("Shell").Return(shell.PWSH)
|
env.On("Shell").Return(shell.PWSH)
|
||||||
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
||||||
|
|
||||||
|
template.Init(env)
|
||||||
|
|
||||||
path := &Path{
|
path := &Path{
|
||||||
env: env,
|
env: env,
|
||||||
props: properties.Map{
|
props: properties.Map{
|
||||||
|
@ -1413,6 +1426,7 @@ func TestGetPwd(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
path.setPaths()
|
path.setPaths()
|
||||||
assert.Equal(t, tc.Expected, path.pwd)
|
assert.Equal(t, tc.Expected, path.pwd)
|
||||||
}
|
}
|
||||||
|
@ -1437,7 +1451,9 @@ func TestGetFolderSeparator(t *testing.T) {
|
||||||
env.On("Error", testify_.Anything)
|
env.On("Error", testify_.Anything)
|
||||||
env.On("Debug", testify_.Anything)
|
env.On("Debug", testify_.Anything)
|
||||||
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
||||||
env.On("Flags").Return(&runtime.Flags{})
|
env.On("Shell").Return(shell.GENERIC)
|
||||||
|
|
||||||
|
template.Init(env)
|
||||||
|
|
||||||
path := &Path{
|
path := &Path{
|
||||||
env: env,
|
env: env,
|
||||||
|
@ -1455,7 +1471,6 @@ func TestGetFolderSeparator(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
env.On("TemplateCache").Return(&cache.Template{
|
env.On("TemplateCache").Return(&cache.Template{
|
||||||
Env: make(map[string]string),
|
|
||||||
Shell: "bash",
|
Shell: "bash",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1626,7 +1641,8 @@ func TestReplaceMappedLocations(t *testing.T) {
|
||||||
env.On("GOOS").Return(runtime.DARWIN)
|
env.On("GOOS").Return(runtime.DARWIN)
|
||||||
env.On("Home").Return("/a/b/k")
|
env.On("Home").Return("/a/b/k")
|
||||||
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
||||||
env.On("Flags").Return(&runtime.Flags{})
|
|
||||||
|
template.Init(env)
|
||||||
|
|
||||||
path := &Path{
|
path := &Path{
|
||||||
env: env,
|
env: env,
|
||||||
|
@ -1750,13 +1766,11 @@ func TestGetMaxWidth(t *testing.T) {
|
||||||
env := new(mock.Environment)
|
env := new(mock.Environment)
|
||||||
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
||||||
env.On("Error", testify_.Anything).Return(nil)
|
env.On("Error", testify_.Anything).Return(nil)
|
||||||
env.On("Flags").Return(&runtime.Flags{})
|
env.On("TemplateCache").Return(&cache.Template{})
|
||||||
env.On("TemplateCache").Return(&cache.Template{
|
env.On("Getenv", "MAX_WIDTH").Return("120")
|
||||||
Env: map[string]string{
|
env.On("Shell").Return(shell.BASH)
|
||||||
"MAX_WIDTH": "120",
|
|
||||||
},
|
template.Init(env)
|
||||||
Shell: "bash",
|
|
||||||
})
|
|
||||||
|
|
||||||
path := &Path{
|
path := &Path{
|
||||||
env: env,
|
env: env,
|
||||||
|
|
|
@ -117,21 +117,20 @@ func TestSessionSegmentTemplate(t *testing.T) {
|
||||||
env.On("User").Return(tc.UserName)
|
env.On("User").Return(tc.UserName)
|
||||||
env.On("GOOS").Return("burp")
|
env.On("GOOS").Return("burp")
|
||||||
env.On("Host").Return(tc.ComputerName, nil)
|
env.On("Host").Return(tc.ComputerName, nil)
|
||||||
|
|
||||||
var SSHSession string
|
var SSHSession string
|
||||||
if tc.SSHSession {
|
if tc.SSHSession {
|
||||||
SSHSession = "zezzion"
|
SSHSession = "zezzion"
|
||||||
}
|
}
|
||||||
|
|
||||||
env.On("Getenv", "SSH_CONNECTION").Return(SSHSession)
|
env.On("Getenv", "SSH_CONNECTION").Return(SSHSession)
|
||||||
env.On("Getenv", "SSH_CLIENT").Return(SSHSession)
|
env.On("Getenv", "SSH_CLIENT").Return(SSHSession)
|
||||||
|
env.On("Getenv", "POSH_SESSION_DEFAULT_USER").Return(tc.DefaultUserName)
|
||||||
|
|
||||||
env.On("TemplateCache").Return(&cache.Template{
|
env.On("TemplateCache").Return(&cache.Template{
|
||||||
UserName: tc.UserName,
|
UserName: tc.UserName,
|
||||||
HostName: tc.ComputerName,
|
HostName: tc.ComputerName,
|
||||||
Env: map[string]string{
|
Root: tc.Root,
|
||||||
"SSH_CONNECTION": SSHSession,
|
|
||||||
"SSH_CLIENT": SSHSession,
|
|
||||||
"POSH_SESSION_DEFAULT_USER": tc.DefaultUserName,
|
|
||||||
},
|
|
||||||
Root: tc.Root,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
env.On("Platform").Return(tc.Platform)
|
env.On("Platform").Return(tc.Platform)
|
||||||
|
@ -147,6 +146,7 @@ func TestSessionSegmentTemplate(t *testing.T) {
|
||||||
env: env,
|
env: env,
|
||||||
props: properties.Map{},
|
props: properties.Map{},
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = session.Enabled()
|
_ = session.Enabled()
|
||||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, tc.Template, session), tc.Case)
|
assert.Equal(t, tc.ExpectedString, renderTemplate(env, tc.Template, session), tc.Case)
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,6 @@ func (s *Status) Init(props properties.Properties, env runtime.Environment) {
|
||||||
statusTemplate := s.props.GetString(StatusTemplate, "{{ .Code }}")
|
statusTemplate := s.props.GetString(StatusTemplate, "{{ .Code }}")
|
||||||
s.template = &template.Text{
|
s.template = &template.Text{
|
||||||
Template: statusTemplate,
|
Template: statusTemplate,
|
||||||
Env: s.env,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,21 +93,13 @@ func TestFormatStatus(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
env := new(mock.Environment)
|
|
||||||
env.On("TemplateCache").Return(&cache.Template{
|
|
||||||
Code: 133,
|
|
||||||
})
|
|
||||||
env.On("Error", testify_.Anything).Return(nil)
|
|
||||||
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
|
||||||
env.On("Flags").Return(&runtime.Flags{})
|
|
||||||
|
|
||||||
props := properties.Map{
|
props := properties.Map{
|
||||||
StatusTemplate: tc.Template,
|
StatusTemplate: tc.Template,
|
||||||
StatusSeparator: tc.Separator,
|
StatusSeparator: tc.Separator,
|
||||||
}
|
}
|
||||||
|
|
||||||
s := &Status{}
|
s := &Status{}
|
||||||
s.Init(props, env)
|
s.Init(props, new(mock.Environment))
|
||||||
|
|
||||||
assert.Equal(t, tc.Expected, s.formatStatus(tc.Status, tc.PipeStatus), tc.Case)
|
assert.Equal(t, tc.Expected, s.formatStatus(tc.Status, tc.PipeStatus), tc.Case)
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,15 +30,14 @@ func TestTextSegment(t *testing.T) {
|
||||||
env.On("PathSeparator").Return("/")
|
env.On("PathSeparator").Return("/")
|
||||||
env.On("TemplateCache").Return(&cache.Template{
|
env.On("TemplateCache").Return(&cache.Template{
|
||||||
UserName: "Posh",
|
UserName: "Posh",
|
||||||
Env: map[string]string{
|
|
||||||
"HELLO": "hello",
|
|
||||||
"WORLD": "",
|
|
||||||
},
|
|
||||||
HostName: "MyHost",
|
HostName: "MyHost",
|
||||||
Shell: "terminal",
|
Shell: "terminal",
|
||||||
Root: true,
|
Root: true,
|
||||||
Folder: "posh",
|
Folder: "posh",
|
||||||
})
|
})
|
||||||
|
env.On("Getenv", "HELLO").Return("hello")
|
||||||
|
env.On("Getenv", "WORLD").Return("")
|
||||||
|
|
||||||
txt := &Text{
|
txt := &Text{
|
||||||
env: env,
|
env: env,
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,6 @@ func (w *Wakatime) getURL() (string, error) {
|
||||||
tmpl := &template.Text{
|
tmpl := &template.Text{
|
||||||
Template: url,
|
Template: url,
|
||||||
Context: w,
|
Context: w,
|
||||||
Env: w.env,
|
|
||||||
}
|
}
|
||||||
return tmpl.Render()
|
return tmpl.Render()
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,13 +5,10 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/cache"
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
testify_ "github.com/stretchr/testify/mock"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestWTTrackedTime(t *testing.T) {
|
func TestWTTrackedTime(t *testing.T) {
|
||||||
|
@ -68,13 +65,6 @@ func TestWTTrackedTime(t *testing.T) {
|
||||||
|
|
||||||
env.On("HTTPRequest", FAKEAPIURL).Return([]byte(response), tc.Error)
|
env.On("HTTPRequest", FAKEAPIURL).Return([]byte(response), tc.Error)
|
||||||
|
|
||||||
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
|
||||||
env.On("Flags").Return(&runtime.Flags{})
|
|
||||||
|
|
||||||
env.On("TemplateCache").Return(&cache.Template{
|
|
||||||
Env: map[string]string{"HELLO": "hello"},
|
|
||||||
})
|
|
||||||
|
|
||||||
w := &Wakatime{
|
w := &Wakatime{
|
||||||
props: properties.Map{
|
props: properties.Map{
|
||||||
URL: FAKEAPIURL,
|
URL: FAKEAPIURL,
|
||||||
|
@ -86,54 +76,3 @@ func TestWTTrackedTime(t *testing.T) {
|
||||||
assert.Equal(t, tc.Expected, renderTemplate(env, w.Template(), w), tc.Case+" - String")
|
assert.Equal(t, tc.Expected, renderTemplate(env, w.Template(), w), tc.Case+" - String")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWTGetUrl(t *testing.T) {
|
|
||||||
cases := []struct {
|
|
||||||
Case string
|
|
||||||
Expected string
|
|
||||||
URL string
|
|
||||||
ShouldError bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
Case: "no template",
|
|
||||||
Expected: "test",
|
|
||||||
URL: "test",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Case: "template",
|
|
||||||
URL: "{{ .Env.HELLO }} world",
|
|
||||||
Expected: "hello world",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Case: "error",
|
|
||||||
URL: "{{ .BURR }}",
|
|
||||||
ShouldError: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range cases {
|
|
||||||
env := &mock.Environment{}
|
|
||||||
|
|
||||||
env.On("Error", testify_.Anything)
|
|
||||||
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
|
||||||
env.On("TemplateCache").Return(&cache.Template{
|
|
||||||
Env: map[string]string{"HELLO": "hello"},
|
|
||||||
})
|
|
||||||
env.On("Flags").Return(&runtime.Flags{})
|
|
||||||
|
|
||||||
w := &Wakatime{
|
|
||||||
props: properties.Map{
|
|
||||||
URL: tc.URL,
|
|
||||||
},
|
|
||||||
env: env,
|
|
||||||
}
|
|
||||||
|
|
||||||
got, err := w.getURL()
|
|
||||||
|
|
||||||
if tc.ShouldError {
|
|
||||||
assert.Error(t, err, tc.Case)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
assert.Equal(t, tc.Expected, got, tc.Case)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/cache"
|
"github.com/jandedobbeleer/oh-my-posh/src/cache"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -25,16 +24,15 @@ func TestGlob(t *testing.T) {
|
||||||
|
|
||||||
env := &mock.Environment{}
|
env := &mock.Environment{}
|
||||||
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
||||||
env.On("TemplateCache").Return(&cache.Template{
|
env.On("TemplateCache").Return(&cache.Template{})
|
||||||
Env: make(map[string]string),
|
env.On("Shell").Return("foo")
|
||||||
})
|
|
||||||
env.On("Flags").Return(&runtime.Flags{})
|
Init(env)
|
||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
tmpl := &Text{
|
tmpl := &Text{
|
||||||
Template: tc.Template,
|
Template: tc.Template,
|
||||||
Context: nil,
|
Context: nil,
|
||||||
Env: env,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
text, err := tmpl.Render()
|
text, err := tmpl.Render()
|
||||||
|
|
85
src/template/init.go
Normal file
85
src/template/init.go
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
package template
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"sync"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Errors to show when the template handling fails
|
||||||
|
InvalidTemplate = "invalid template text"
|
||||||
|
IncorrectTemplate = "unable to create text based on template"
|
||||||
|
|
||||||
|
globalRef = ".$"
|
||||||
|
|
||||||
|
elvish = "elvish"
|
||||||
|
xonsh = "xonsh"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
shell string
|
||||||
|
tmplFunc *template.Template
|
||||||
|
contextPool sync.Pool
|
||||||
|
buffPool sync.Pool
|
||||||
|
env runtime.Environment
|
||||||
|
knownVariables []string
|
||||||
|
)
|
||||||
|
|
||||||
|
type buff bytes.Buffer
|
||||||
|
|
||||||
|
func (b *buff) release() {
|
||||||
|
(*bytes.Buffer)(b).Reset()
|
||||||
|
buffPool.Put(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *buff) Write(p []byte) (n int, err error) {
|
||||||
|
return (*bytes.Buffer)(b).Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *buff) String() string {
|
||||||
|
return (*bytes.Buffer)(b).String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Init(environment runtime.Environment) {
|
||||||
|
env = environment
|
||||||
|
shell = env.Shell()
|
||||||
|
|
||||||
|
tmplFunc = template.New("cache").Funcs(funcMap())
|
||||||
|
|
||||||
|
contextPool = sync.Pool{
|
||||||
|
New: func() any {
|
||||||
|
return &context{}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
buffPool = sync.Pool{
|
||||||
|
New: func() any {
|
||||||
|
return &buff{}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
knownVariables = []string{
|
||||||
|
"Root",
|
||||||
|
"PWD",
|
||||||
|
"AbsolutePWD",
|
||||||
|
"Folder",
|
||||||
|
"Shell",
|
||||||
|
"ShellVersion",
|
||||||
|
"UserName",
|
||||||
|
"HostName",
|
||||||
|
"Code",
|
||||||
|
"Env",
|
||||||
|
"OS",
|
||||||
|
"WSL",
|
||||||
|
"PromptCount",
|
||||||
|
"Segments",
|
||||||
|
"SHLVL",
|
||||||
|
"Templates",
|
||||||
|
"Var",
|
||||||
|
"Data",
|
||||||
|
"Jobs",
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/cache"
|
"github.com/jandedobbeleer/oh-my-posh/src/cache"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -23,25 +22,26 @@ func TestUrl(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
env := &mock.Environment{}
|
env := &mock.Environment{}
|
||||||
env.On("TemplateCache").Return(&cache.Template{
|
env.On("TemplateCache").Return(&cache.Template{})
|
||||||
Env: make(map[string]string),
|
|
||||||
})
|
|
||||||
env.On("Error", testify_.Anything)
|
env.On("Error", testify_.Anything)
|
||||||
env.On("Debug", testify_.Anything)
|
env.On("Debug", testify_.Anything)
|
||||||
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
||||||
env.On("Flags").Return(&runtime.Flags{})
|
env.On("Shell").Return("foo")
|
||||||
|
|
||||||
|
Init(env)
|
||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
tmpl := &Text{
|
tmpl := &Text{
|
||||||
Template: tc.Template,
|
Template: tc.Template,
|
||||||
Context: nil,
|
Context: nil,
|
||||||
Env: env,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
text, err := tmpl.Render()
|
text, err := tmpl.Render()
|
||||||
if tc.ShouldError {
|
if tc.ShouldError {
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(t, tc.Expected, text, tc.Case)
|
assert.Equal(t, tc.Expected, text, tc.Case)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,18 +55,10 @@ func TestPath(t *testing.T) {
|
||||||
{Case: "valid path", Expected: "<LINK>file:/test/test<TEXT>link</TEXT></LINK>", Template: `{{ path "link" "/test/test" }}`},
|
{Case: "valid path", Expected: "<LINK>file:/test/test<TEXT>link</TEXT></LINK>", Template: `{{ path "link" "/test/test" }}`},
|
||||||
}
|
}
|
||||||
|
|
||||||
env := &mock.Environment{}
|
|
||||||
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
|
||||||
env.On("TemplateCache").Return(&cache.Template{
|
|
||||||
Env: make(map[string]string),
|
|
||||||
})
|
|
||||||
env.On("Flags").Return(&runtime.Flags{})
|
|
||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
tmpl := &Text{
|
tmpl := &Text{
|
||||||
Template: tc.Template,
|
Template: tc.Template,
|
||||||
Context: nil,
|
Context: nil,
|
||||||
Env: env,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
text, _ := tmpl.Render()
|
text, _ := tmpl.Render()
|
||||||
|
|
|
@ -2,8 +2,6 @@ package template
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Logic string
|
type Logic string
|
||||||
|
@ -19,25 +17,24 @@ func (l List) Empty() bool {
|
||||||
return len(l) == 0
|
return len(l) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l List) Resolve(context any, env runtime.Environment, defaultValue string, logic Logic) string {
|
func (l List) Resolve(context any, defaultValue string, logic Logic) string {
|
||||||
switch logic {
|
switch logic {
|
||||||
case FirstMatch:
|
case FirstMatch:
|
||||||
return l.FirstMatch(context, env, defaultValue)
|
return l.FirstMatch(context, defaultValue)
|
||||||
case Join:
|
case Join:
|
||||||
fallthrough
|
fallthrough
|
||||||
default:
|
default:
|
||||||
return l.Join(context, env)
|
return l.Join(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l List) Join(context any, env runtime.Environment) string {
|
func (l List) Join(context any) string {
|
||||||
if len(l) == 0 {
|
if len(l) == 0 {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
txtTemplate := &Text{
|
txtTemplate := &Text{
|
||||||
Context: context,
|
Context: context,
|
||||||
Env: env,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var buffer strings.Builder
|
var buffer strings.Builder
|
||||||
|
@ -54,14 +51,13 @@ func (l List) Join(context any, env runtime.Environment) string {
|
||||||
return buffer.String()
|
return buffer.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l List) FirstMatch(context any, env runtime.Environment, defaultValue string) string {
|
func (l List) FirstMatch(context any, defaultValue string) string {
|
||||||
if len(l) == 0 {
|
if len(l) == 0 {
|
||||||
return defaultValue
|
return defaultValue
|
||||||
}
|
}
|
||||||
|
|
||||||
txtTemplate := &Text{
|
txtTemplate := &Text{
|
||||||
Context: context,
|
Context: context,
|
||||||
Env: env,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tmpl := range l {
|
for _, tmpl := range l {
|
||||||
|
|
|
@ -3,12 +3,7 @@ package template
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/cache"
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
testify_ "github.com/stretchr/testify/mock"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHResult(t *testing.T) {
|
func TestHResult(t *testing.T) {
|
||||||
|
@ -22,20 +17,10 @@ func TestHResult(t *testing.T) {
|
||||||
{Case: "Not a number", Template: `{{ hresult "no number" }}`, ShouldError: true},
|
{Case: "Not a number", Template: `{{ hresult "no number" }}`, ShouldError: true},
|
||||||
}
|
}
|
||||||
|
|
||||||
env := &mock.Environment{}
|
|
||||||
env.On("TemplateCache").Return(&cache.Template{
|
|
||||||
Env: make(map[string]string),
|
|
||||||
})
|
|
||||||
env.On("Error", testify_.Anything)
|
|
||||||
env.On("Debug", testify_.Anything)
|
|
||||||
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
|
||||||
env.On("Flags").Return(&runtime.Flags{})
|
|
||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
tmpl := &Text{
|
tmpl := &Text{
|
||||||
Template: tc.Template,
|
Template: tc.Template,
|
||||||
Context: nil,
|
Context: nil,
|
||||||
Env: env,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
text, err := tmpl.Render()
|
text, err := tmpl.Render()
|
||||||
|
|
|
@ -3,12 +3,7 @@ package template
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/cache"
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
testify_ "github.com/stretchr/testify/mock"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRoundSeconds(t *testing.T) {
|
func TestRoundSeconds(t *testing.T) {
|
||||||
|
@ -29,20 +24,10 @@ func TestRoundSeconds(t *testing.T) {
|
||||||
{Case: "error", Expected: "", Template: "{{ secondsRound foo }}", ShouldError: true},
|
{Case: "error", Expected: "", Template: "{{ secondsRound foo }}", ShouldError: true},
|
||||||
}
|
}
|
||||||
|
|
||||||
env := &mock.Environment{}
|
|
||||||
env.On("TemplateCache").Return(&cache.Template{
|
|
||||||
Env: make(map[string]string),
|
|
||||||
})
|
|
||||||
env.On("Error", testify_.Anything)
|
|
||||||
env.On("Debug", testify_.Anything)
|
|
||||||
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
|
||||||
env.On("Flags").Return(&runtime.Flags{})
|
|
||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
tmpl := &Text{
|
tmpl := &Text{
|
||||||
Template: tc.Template,
|
Template: tc.Template,
|
||||||
Context: nil,
|
Context: nil,
|
||||||
Env: env,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
text, err := tmpl.Render()
|
text, err := tmpl.Render()
|
||||||
|
|
|
@ -3,12 +3,7 @@ package template
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/cache"
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
testify_ "github.com/stretchr/testify/mock"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestTrunc(t *testing.T) {
|
func TestTrunc(t *testing.T) {
|
||||||
|
@ -26,20 +21,10 @@ func TestTrunc(t *testing.T) {
|
||||||
{Case: "negative", Expected: "ld", Template: `{{ trunc -2 "Hello World" }}`},
|
{Case: "negative", Expected: "ld", Template: `{{ trunc -2 "Hello World" }}`},
|
||||||
}
|
}
|
||||||
|
|
||||||
env := &mock.Environment{}
|
|
||||||
env.On("TemplateCache").Return(&cache.Template{
|
|
||||||
Env: make(map[string]string),
|
|
||||||
})
|
|
||||||
env.On("Error", testify_.Anything)
|
|
||||||
env.On("Debug", testify_.Anything)
|
|
||||||
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
|
||||||
env.On("Flags").Return(&runtime.Flags{})
|
|
||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
tmpl := &Text{
|
tmpl := &Text{
|
||||||
Template: tc.Template,
|
Template: tc.Template,
|
||||||
Context: nil,
|
Context: nil,
|
||||||
Env: env,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
text, err := tmpl.Render()
|
text, err := tmpl.Render()
|
||||||
|
|
|
@ -1,98 +1,26 @@
|
||||||
package template
|
package template
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
"text/template"
|
|
||||||
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/cache"
|
"github.com/jandedobbeleer/oh-my-posh/src/cache"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/regex"
|
"github.com/jandedobbeleer/oh-my-posh/src/regex"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
// Errors to show when the template handling fails
|
|
||||||
InvalidTemplate = "invalid template text"
|
|
||||||
IncorrectTemplate = "unable to create text based on template"
|
|
||||||
|
|
||||||
globalRef = ".$"
|
|
||||||
|
|
||||||
elvish = "elvish"
|
|
||||||
xonsh = "xonsh"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
knownVariables = []string{
|
|
||||||
"Root",
|
|
||||||
"PWD",
|
|
||||||
"AbsolutePWD",
|
|
||||||
"PSWD",
|
|
||||||
"Folder",
|
|
||||||
"Shell",
|
|
||||||
"ShellVersion",
|
|
||||||
"UserName",
|
|
||||||
"HostName",
|
|
||||||
"Code",
|
|
||||||
"Env",
|
|
||||||
"OS",
|
|
||||||
"WSL",
|
|
||||||
"PromptCount",
|
|
||||||
"Segments",
|
|
||||||
"SHLVL",
|
|
||||||
"Templates",
|
|
||||||
"Var",
|
|
||||||
"Data",
|
|
||||||
"Jobs",
|
|
||||||
}
|
|
||||||
|
|
||||||
shell string
|
|
||||||
|
|
||||||
tmplFunc = template.New("cache").Funcs(funcMap())
|
|
||||||
|
|
||||||
contextPool = sync.Pool{
|
|
||||||
New: func() any {
|
|
||||||
return &context{}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
buffPool = sync.Pool{
|
|
||||||
New: func() any {
|
|
||||||
return &buff{}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
type buff bytes.Buffer
|
|
||||||
|
|
||||||
func (b *buff) release() {
|
|
||||||
(*bytes.Buffer)(b).Reset()
|
|
||||||
buffPool.Put(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *buff) Write(p []byte) (n int, err error) {
|
|
||||||
return (*bytes.Buffer)(b).Write(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *buff) String() string {
|
|
||||||
return (*bytes.Buffer)(b).String()
|
|
||||||
}
|
|
||||||
|
|
||||||
type Text struct {
|
type Text struct {
|
||||||
Template string
|
|
||||||
Context any
|
Context any
|
||||||
Env runtime.Environment
|
Template string
|
||||||
}
|
}
|
||||||
|
|
||||||
type Data any
|
type Data any
|
||||||
|
|
||||||
type context struct {
|
type context struct {
|
||||||
*cache.Template
|
|
||||||
|
|
||||||
// Simple container to hold ANY object
|
|
||||||
Data
|
Data
|
||||||
|
Getenv func(string) string
|
||||||
|
cache.Template
|
||||||
initialized bool
|
initialized bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,9 +31,8 @@ func (c *context) init(t *Text) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if tmplCache := t.Env.TemplateCache(); tmplCache != nil {
|
c.Getenv = env.Getenv
|
||||||
c.Template = tmplCache
|
c.Template = *env.TemplateCache()
|
||||||
}
|
|
||||||
|
|
||||||
c.initialized = true
|
c.initialized = true
|
||||||
}
|
}
|
||||||
|
@ -116,19 +43,17 @@ func (c *context) release() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Text) Render() (string, error) {
|
func (t *Text) Render() (string, error) {
|
||||||
t.Env.DebugF("rendering template: %s", t.Template)
|
env.DebugF("rendering template: %s", t.Template)
|
||||||
|
|
||||||
shell = t.Env.Flags().Shell
|
|
||||||
|
|
||||||
if !strings.Contains(t.Template, "{{") || !strings.Contains(t.Template, "}}") {
|
if !strings.Contains(t.Template, "{{") || !strings.Contains(t.Template, "}}") {
|
||||||
return t.Template, nil
|
return t.Template, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
t.cleanTemplate()
|
t.patchTemplate()
|
||||||
|
|
||||||
tmpl, err := tmplFunc.Parse(t.Template)
|
tmpl, err := tmplFunc.Parse(t.Template)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Env.Error(err)
|
env.Error(err)
|
||||||
return "", errors.New(InvalidTemplate)
|
return "", errors.New(InvalidTemplate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +66,7 @@ func (t *Text) Render() (string, error) {
|
||||||
|
|
||||||
err = tmpl.Execute(buffer, context)
|
err = tmpl.Execute(buffer, context)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Env.Error(err)
|
env.Error(err)
|
||||||
msg := regex.FindNamedRegexMatch(`at (?P<MSG><.*)$`, err.Error())
|
msg := regex.FindNamedRegexMatch(`at (?P<MSG><.*)$`, err.Error())
|
||||||
if len(msg) == 0 {
|
if len(msg) == 0 {
|
||||||
return "", errors.New(IncorrectTemplate)
|
return "", errors.New(IncorrectTemplate)
|
||||||
|
@ -158,7 +83,7 @@ func (t *Text) Render() (string, error) {
|
||||||
return text, nil
|
return text, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Text) cleanTemplate() {
|
func (t *Text) patchTemplate() {
|
||||||
isKnownVariable := func(variable string) bool {
|
isKnownVariable := func(variable string) bool {
|
||||||
variable = strings.TrimPrefix(variable, ".")
|
variable = strings.TrimPrefix(variable, ".")
|
||||||
splitted := strings.Split(variable, ".")
|
splitted := strings.Split(variable, ".")
|
||||||
|
@ -233,6 +158,11 @@ func (t *Text) cleanTemplate() {
|
||||||
// the list of segments so they can be accessed directly
|
// the list of segments so they can be accessed directly
|
||||||
property = strings.Replace(property, ".Segments", ".Segments.ToSimple", 1)
|
property = strings.Replace(property, ".Segments", ".Segments.ToSimple", 1)
|
||||||
result += property
|
result += property
|
||||||
|
case strings.HasPrefix(property, ".Env."):
|
||||||
|
// we need to replace the property with the getEnv function
|
||||||
|
// so we can access the environment variables directly
|
||||||
|
property = strings.TrimPrefix(property, ".Env.")
|
||||||
|
result += fmt.Sprintf(`(call .Getenv "%s")`, property)
|
||||||
default:
|
default:
|
||||||
// check if we have the same property in Data
|
// check if we have the same property in Data
|
||||||
// and replace it with the Data property so it
|
// and replace it with the Data property so it
|
||||||
|
@ -240,6 +170,7 @@ func (t *Text) cleanTemplate() {
|
||||||
if fields.hasField(property) {
|
if fields.hasField(property) {
|
||||||
property = ".Data" + property
|
property = ".Data" + property
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove the global reference so we can use it directly
|
// remove the global reference so we can use it directly
|
||||||
property = strings.TrimPrefix(property, globalRef)
|
property = strings.TrimPrefix(property, globalRef)
|
||||||
result += property
|
result += property
|
||||||
|
|
|
@ -157,19 +157,10 @@ func TestRenderTemplate(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
env := &mock.Environment{}
|
|
||||||
env.On("TemplateCache").Return(&cache.Template{
|
|
||||||
Env: make(map[string]string),
|
|
||||||
})
|
|
||||||
env.On("Error", testify_.Anything)
|
|
||||||
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
|
||||||
env.On("Flags").Return(&runtime.Flags{})
|
|
||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
tmpl := &Text{
|
tmpl := &Text{
|
||||||
Template: tc.Template,
|
Template: tc.Template,
|
||||||
Context: tc.Context,
|
Context: tc.Context,
|
||||||
Env: env,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
text, err := tmpl.Render()
|
text, err := tmpl.Render()
|
||||||
|
@ -247,18 +238,23 @@ func TestRenderTemplateEnvVar(t *testing.T) {
|
||||||
}
|
}
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
env := &mock.Environment{}
|
env := &mock.Environment{}
|
||||||
env.On("TemplateCache").Return(&cache.Template{
|
|
||||||
Env: tc.Env,
|
|
||||||
OS: "darwin",
|
|
||||||
})
|
|
||||||
env.On("Error", testify_.Anything)
|
env.On("Error", testify_.Anything)
|
||||||
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
||||||
env.On("Flags").Return(&runtime.Flags{})
|
env.On("Flags").Return(&runtime.Flags{})
|
||||||
|
env.On("Shell").Return("foo")
|
||||||
|
env.On("TemplateCache").Return(&cache.Template{
|
||||||
|
OS: "darwin",
|
||||||
|
})
|
||||||
|
|
||||||
|
for k, v := range tc.Env {
|
||||||
|
env.On("Getenv", k).Return(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
Init(env)
|
||||||
|
|
||||||
tmpl := &Text{
|
tmpl := &Text{
|
||||||
Template: tc.Template,
|
Template: tc.Template,
|
||||||
Context: tc.Context,
|
Context: tc.Context,
|
||||||
Env: env,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
text, err := tmpl.Render()
|
text, err := tmpl.Render()
|
||||||
|
@ -271,7 +267,7 @@ func TestRenderTemplateEnvVar(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCleanTemplate(t *testing.T) {
|
func TestPatchTemplate(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
Case string
|
Case string
|
||||||
Expected string
|
Expected string
|
||||||
|
@ -294,27 +290,27 @@ func TestCleanTemplate(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Case: "Same prefix",
|
Case: "Same prefix",
|
||||||
Expected: "{{ .Env.HELLO }} {{ .Data.World }} {{ .Data.WorldTrend }}",
|
Expected: "{{ (call .Getenv \"HELLO\") }} {{ .Data.World }} {{ .Data.WorldTrend }}",
|
||||||
Template: "{{ .Env.HELLO }} {{ .World }} {{ .WorldTrend }}",
|
Template: "{{ .Env.HELLO }} {{ .World }} {{ .WorldTrend }}",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Case: "Double use of property with different child",
|
Case: "Double use of property with different child",
|
||||||
Expected: "{{ .Env.HELLO }} {{ .Data.World.Trend }} {{ .Data.World.Hello }} {{ .Data.World }}",
|
Expected: "{{ (call .Getenv \"HELLO\") }} {{ .Data.World.Trend }} {{ .Data.World.Hello }} {{ .Data.World }}",
|
||||||
Template: "{{ .Env.HELLO }} {{ .World.Trend }} {{ .World.Hello }} {{ .World }}",
|
Template: "{{ .Env.HELLO }} {{ .World.Trend }} {{ .World.Hello }} {{ .World }}",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Case: "Hello world",
|
Case: "Hello world",
|
||||||
Expected: "{{.Env.HELLO}} {{.Data.World}}",
|
Expected: "{{(call .Getenv \"HELLO\")}} {{.Data.World}}",
|
||||||
Template: "{{.Env.HELLO}} {{.World}}",
|
Template: "{{.Env.HELLO}} {{.World}}",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Case: "Multiple vars",
|
Case: "Multiple vars",
|
||||||
Expected: "{{.Env.HELLO}} {{.Data.World}} {{.Data.World}}",
|
Expected: "{{(call .Getenv \"HELLO\")}} {{.Data.World}} {{.Data.World}}",
|
||||||
Template: "{{.Env.HELLO}} {{.World}} {{.World}}",
|
Template: "{{.Env.HELLO}} {{.World}} {{.World}}",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Case: "Multiple vars with spaces",
|
Case: "Multiple vars with spaces",
|
||||||
Expected: "{{ .Env.HELLO }} {{ .Data.World }} {{ .Data.World }}",
|
Expected: "{{ (call .Getenv \"HELLO\") }} {{ .Data.World }} {{ .Data.World }}",
|
||||||
Template: "{{ .Env.HELLO }} {{ .World }} {{ .World }}",
|
Template: "{{ .Env.HELLO }} {{ .World }} {{ .World }}",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -343,12 +339,19 @@ func TestCleanTemplate(t *testing.T) {
|
||||||
Template: `{{.Segments.Git.Repo}}`,
|
Template: `{{.Segments.Git.Repo}}`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
env := &mock.Environment{}
|
||||||
|
env.On("Shell").Return("foo")
|
||||||
|
|
||||||
|
Init(env)
|
||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
tmpl := &Text{
|
tmpl := &Text{
|
||||||
Template: tc.Template,
|
Template: tc.Template,
|
||||||
Context: map[string]any{"OS": "posh"},
|
Context: map[string]any{"OS": "posh"},
|
||||||
}
|
}
|
||||||
tmpl.cleanTemplate()
|
|
||||||
|
tmpl.patchTemplate()
|
||||||
assert.Equal(t, tc.Expected, tmpl.Template, tc.Case)
|
assert.Equal(t, tc.Expected, tmpl.Template, tc.Case)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -368,16 +371,16 @@ func TestSegmentContains(t *testing.T) {
|
||||||
segments.Set("Git", "foo")
|
segments.Set("Git", "foo")
|
||||||
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
||||||
env.On("TemplateCache").Return(&cache.Template{
|
env.On("TemplateCache").Return(&cache.Template{
|
||||||
Env: make(map[string]string),
|
|
||||||
Segments: segments,
|
Segments: segments,
|
||||||
})
|
})
|
||||||
env.On("Flags").Return(&runtime.Flags{})
|
env.On("Shell").Return("foo")
|
||||||
|
|
||||||
|
Init(env)
|
||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
tmpl := &Text{
|
tmpl := &Text{
|
||||||
Template: tc.Template,
|
Template: tc.Template,
|
||||||
Context: nil,
|
Context: nil,
|
||||||
Env: env,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
text, _ := tmpl.Render()
|
text, _ := tmpl.Render()
|
||||||
|
|
Loading…
Reference in a new issue