mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2025-01-29 20:10:56 -08:00
feat: cache template environment data
This commit is contained in:
parent
9e77d0f939
commit
e5dd07fb9a
|
@ -1,7 +1,6 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -57,11 +56,17 @@ func TestGetConsoleTitle(t *testing.T) {
|
|||
env.On("getcwd").Return(tc.Cwd)
|
||||
env.On("homeDir").Return("/usr/home")
|
||||
env.On("getPathSeperator").Return(tc.PathSeperator)
|
||||
env.On("isRunningAsRoot").Return(tc.Root)
|
||||
env.On("getShellName").Return(tc.ShellName)
|
||||
env.On("getenv", "USERDOMAIN").Return("MyCompany")
|
||||
env.On("getCurrentUser").Return("MyUser")
|
||||
env.On("getHostName").Return("MyHost", nil)
|
||||
env.On("templateCache").Return(&templateCache{
|
||||
Env: map[string]string{
|
||||
"USERDOMAIN": "MyCompany",
|
||||
},
|
||||
Shell: tc.ShellName,
|
||||
UserName: "MyUser",
|
||||
Root: tc.Root,
|
||||
HostName: "MyHost",
|
||||
PWD: tc.Cwd,
|
||||
Folder: base(tc.Cwd, env),
|
||||
})
|
||||
env.onTemplate()
|
||||
ansi := &ansiUtils{}
|
||||
ansi.init(tc.ShellName)
|
||||
|
@ -112,12 +117,15 @@ func TestGetConsoleTitleIfGethostnameReturnsError(t *testing.T) {
|
|||
env := new(MockedEnvironment)
|
||||
env.On("getcwd").Return(tc.Cwd)
|
||||
env.On("homeDir").Return("/usr/home")
|
||||
env.On("getPathSeperator").Return(tc.PathSeperator)
|
||||
env.On("isRunningAsRoot").Return(tc.Root)
|
||||
env.On("getShellName").Return(tc.ShellName)
|
||||
env.On("getenv", "USERDOMAIN").Return("MyCompany")
|
||||
env.On("getCurrentUser").Return("MyUser")
|
||||
env.On("getHostName").Return("", fmt.Errorf("I have a bad feeling about this"))
|
||||
env.On("templateCache").Return(&templateCache{
|
||||
Env: map[string]string{
|
||||
"USERDOMAIN": "MyCompany",
|
||||
},
|
||||
Shell: tc.ShellName,
|
||||
UserName: "MyUser",
|
||||
Root: tc.Root,
|
||||
HostName: "",
|
||||
})
|
||||
env.onTemplate()
|
||||
ansi := &ansiUtils{}
|
||||
ansi.init(tc.ShellName)
|
||||
|
|
|
@ -90,7 +90,6 @@ type wifiInfo struct {
|
|||
|
||||
type Environment interface {
|
||||
getenv(key string) string
|
||||
environ() map[string]string
|
||||
getcwd() string
|
||||
homeDir() string
|
||||
hasFiles(pattern string) bool
|
||||
|
@ -128,6 +127,7 @@ type Environment interface {
|
|||
convertToLinuxPath(path string) string
|
||||
convertToWindowsPath(path string) string
|
||||
getWifiNetwork() (*wifiInfo, error)
|
||||
templateCache() *templateCache
|
||||
}
|
||||
|
||||
type commandCache struct {
|
||||
|
@ -155,13 +155,13 @@ const (
|
|||
)
|
||||
|
||||
type environment struct {
|
||||
args *args
|
||||
cwd string
|
||||
cmdCache *commandCache
|
||||
fileCache *fileCache
|
||||
environCache map[string]string
|
||||
logBuilder strings.Builder
|
||||
debug bool
|
||||
args *args
|
||||
cwd string
|
||||
cmdCache *commandCache
|
||||
fileCache *fileCache
|
||||
tmplCache *templateCache
|
||||
logBuilder strings.Builder
|
||||
debug bool
|
||||
}
|
||||
|
||||
func (env *environment) init(args *args) {
|
||||
|
@ -176,18 +176,6 @@ func (env *environment) init(args *args) {
|
|||
}
|
||||
env.fileCache = &fileCache{}
|
||||
env.fileCache.init(env.getCachePath())
|
||||
env.environCache = make(map[string]string)
|
||||
const separator = "="
|
||||
values := os.Environ()
|
||||
for value := range values {
|
||||
splitted := strings.Split(values[value], separator)
|
||||
if len(splitted) != 2 {
|
||||
continue
|
||||
}
|
||||
key := splitted[0]
|
||||
val := splitted[1:]
|
||||
env.environCache[key] = strings.Join(val, separator)
|
||||
}
|
||||
}
|
||||
|
||||
func (env *environment) resolveConfigPath() {
|
||||
|
@ -236,11 +224,6 @@ func (env *environment) getenv(key string) string {
|
|||
return val
|
||||
}
|
||||
|
||||
func (env *environment) environ() map[string]string {
|
||||
defer env.trace(time.Now(), "environ")
|
||||
return env.environCache
|
||||
}
|
||||
|
||||
func (env *environment) getcwd() string {
|
||||
defer env.trace(time.Now(), "getcwd")
|
||||
if env.cwd != "" {
|
||||
|
@ -563,6 +546,42 @@ func (env *environment) logs() string {
|
|||
return env.logBuilder.String()
|
||||
}
|
||||
|
||||
func (env *environment) templateCache() *templateCache {
|
||||
defer env.trace(time.Now(), "templateCache")
|
||||
if env.tmplCache != nil {
|
||||
return env.tmplCache
|
||||
}
|
||||
tmplCache := &templateCache{
|
||||
Root: env.isRunningAsRoot(),
|
||||
Shell: env.getShellName(),
|
||||
Code: env.lastErrorCode(),
|
||||
}
|
||||
tmplCache.Env = make(map[string]string)
|
||||
const separator = "="
|
||||
values := os.Environ()
|
||||
for value := range values {
|
||||
splitted := strings.Split(values[value], separator)
|
||||
if len(splitted) != 2 {
|
||||
continue
|
||||
}
|
||||
key := splitted[0]
|
||||
val := splitted[1:]
|
||||
tmplCache.Env[key] = strings.Join(val, separator)
|
||||
}
|
||||
pwd := env.getcwd()
|
||||
pwd = strings.Replace(pwd, env.homeDir(), "~", 1)
|
||||
tmplCache.PWD = pwd
|
||||
tmplCache.Folder = base(pwd, env)
|
||||
tmplCache.UserName = env.getCurrentUser()
|
||||
if host, err := env.getHostName(); err == nil {
|
||||
tmplCache.HostName = host
|
||||
}
|
||||
goos := env.getRuntimeGOOS()
|
||||
tmplCache.OS = goos
|
||||
env.tmplCache = tmplCache
|
||||
return env.tmplCache
|
||||
}
|
||||
|
||||
func cleanHostName(hostName string) string {
|
||||
garbage := []string{
|
||||
".lan",
|
||||
|
|
|
@ -53,6 +53,9 @@ func (env *environment) getTerminalWidth() (int, error) {
|
|||
}
|
||||
|
||||
func (env *environment) getPlatform() string {
|
||||
if wsl := env.getenv("WSL_DISTRO_NAME"); len(wsl) != 0 {
|
||||
return strings.ToLower(wsl)
|
||||
}
|
||||
p, _, _, _ := host.PlatformInformation()
|
||||
return p
|
||||
}
|
||||
|
|
11
src/main.go
11
src/main.go
|
@ -336,18 +336,9 @@ func getConsoleBackgroundColor(env Environment, backgroundColorTemplate string)
|
|||
if len(backgroundColorTemplate) == 0 {
|
||||
return backgroundColorTemplate
|
||||
}
|
||||
context := struct {
|
||||
Env map[string]string
|
||||
}{
|
||||
Env: map[string]string{},
|
||||
}
|
||||
matches := findAllNamedRegexMatch(templateEnvRegex, backgroundColorTemplate)
|
||||
for _, match := range matches {
|
||||
context.Env[match["ENV"]] = env.getenv(match["ENV"])
|
||||
}
|
||||
template := &textTemplate{
|
||||
Template: backgroundColorTemplate,
|
||||
Context: context,
|
||||
Context: nil,
|
||||
Env: env,
|
||||
}
|
||||
text, err := template.render()
|
||||
|
|
|
@ -18,7 +18,11 @@ func TestConsoleBackgroundColorTemplate(t *testing.T) {
|
|||
|
||||
for _, tc := range cases {
|
||||
env := new(MockedEnvironment)
|
||||
env.On("getenv", "TERM_PROGRAM").Return(tc.Term)
|
||||
env.On("templateCache").Return(&templateCache{
|
||||
Env: map[string]string{
|
||||
"TERM_PROGRAM": tc.Term,
|
||||
},
|
||||
})
|
||||
env.onTemplate()
|
||||
color := getConsoleBackgroundColor(env, "{{ if eq \"vscode\" .Env.TERM_PROGRAM }}#123456{{end}}")
|
||||
assert.Equal(t, tc.Expected, color, tc.Case)
|
||||
|
|
|
@ -70,6 +70,8 @@ func TestGetBatteryColors(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
env := new(MockedEnvironment)
|
||||
env.onTemplate()
|
||||
batt := &batt{
|
||||
Percentage: tc.Percentage,
|
||||
}
|
||||
|
@ -78,6 +80,7 @@ func TestGetBatteryColors(t *testing.T) {
|
|||
}
|
||||
segment := &Segment{
|
||||
writer: batt,
|
||||
env: env,
|
||||
}
|
||||
segment.Foreground = tc.DefaultColor
|
||||
segment.ForegroundTemplates = tc.Templates
|
||||
|
|
|
@ -77,6 +77,9 @@ func TestExitWriterTemplateString(t *testing.T) {
|
|||
for _, tc := range cases {
|
||||
env := new(MockedEnvironment)
|
||||
env.On("lastErrorCode").Return(tc.ExitCode)
|
||||
env.On("templateCache").Return(&templateCache{
|
||||
Code: tc.ExitCode,
|
||||
})
|
||||
env.onTemplate()
|
||||
props := properties{
|
||||
SegmentTemplate: tc.Template,
|
||||
|
|
|
@ -738,6 +738,9 @@ func TestGitTemplateString(t *testing.T) {
|
|||
props := properties{
|
||||
FetchStatus: true,
|
||||
}
|
||||
env := new(MockedEnvironment)
|
||||
env.onTemplate()
|
||||
tc.Git.env = env
|
||||
tc.Git.props = props
|
||||
assert.Equal(t, tc.Expected, tc.Git.templateString(tc.Template), tc.Case)
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type osInfo struct {
|
||||
|
@ -79,17 +78,14 @@ func (n *osInfo) string() string {
|
|||
n.os = darwinPlatform
|
||||
return n.props.getString(MacOS, "\uF179")
|
||||
case linuxPlatform:
|
||||
wsl := n.env.getenv("WSL_DISTRO_NAME")
|
||||
p := n.env.getPlatform()
|
||||
if len(wsl) == 0 {
|
||||
n.os = p
|
||||
return n.getDistroName(p, "")
|
||||
n.os = n.env.getPlatform()
|
||||
if !n.env.isWsl() {
|
||||
return n.getDistroName(n.os, "")
|
||||
}
|
||||
n.os = strings.ToLower(wsl)
|
||||
return fmt.Sprintf("%s%s%s",
|
||||
n.props.getString(WSL, "WSL"),
|
||||
n.props.getString(WSLSeparator, " - "),
|
||||
n.getDistroName(p, wsl))
|
||||
n.getDistroName(n.os, n.os))
|
||||
default:
|
||||
n.os = goos
|
||||
return goos
|
||||
|
|
|
@ -11,7 +11,7 @@ func TestOSInfo(t *testing.T) {
|
|||
Case string
|
||||
ExpectedString string
|
||||
GOOS string
|
||||
WSLDistro string
|
||||
IsWSL bool
|
||||
Platform string
|
||||
DisplayDistroName bool
|
||||
}{
|
||||
|
@ -19,14 +19,14 @@ func TestOSInfo(t *testing.T) {
|
|||
Case: "WSL debian - icon",
|
||||
ExpectedString: "WSL at \uf306",
|
||||
GOOS: "linux",
|
||||
WSLDistro: "debian",
|
||||
IsWSL: true,
|
||||
Platform: "debian",
|
||||
},
|
||||
{
|
||||
Case: "WSL debian - name",
|
||||
ExpectedString: "WSL at burps",
|
||||
ExpectedString: "WSL at debian",
|
||||
GOOS: "linux",
|
||||
WSLDistro: "burps",
|
||||
IsWSL: true,
|
||||
Platform: "debian",
|
||||
DisplayDistroName: true,
|
||||
},
|
||||
|
@ -62,7 +62,7 @@ func TestOSInfo(t *testing.T) {
|
|||
for _, tc := range cases {
|
||||
env := new(MockedEnvironment)
|
||||
env.On("getRuntimeGOOS").Return(tc.GOOS)
|
||||
env.On("getenv", "WSL_DISTRO_NAME").Return(tc.WSLDistro)
|
||||
env.On("isWsl").Return(tc.IsWSL)
|
||||
env.On("getPlatform").Return(tc.Platform)
|
||||
osInfo := &osInfo{
|
||||
env: env,
|
||||
|
@ -75,9 +75,7 @@ func TestOSInfo(t *testing.T) {
|
|||
},
|
||||
}
|
||||
assert.Equal(t, tc.ExpectedString, osInfo.string(), tc.Case)
|
||||
if tc.WSLDistro != "" {
|
||||
assert.Equal(t, tc.WSLDistro, osInfo.os, tc.Case)
|
||||
} else if tc.Platform != "" {
|
||||
if tc.Platform != "" {
|
||||
assert.Equal(t, tc.Platform, osInfo.os, tc.Case)
|
||||
} else {
|
||||
assert.Equal(t, tc.GOOS, osInfo.os, tc.Case)
|
||||
|
|
|
@ -19,11 +19,6 @@ func (env *MockedEnvironment) getenv(key string) string {
|
|||
return args.String(0)
|
||||
}
|
||||
|
||||
func (env *MockedEnvironment) environ() map[string]string {
|
||||
args := env.Called()
|
||||
return args.Get(0).(map[string]string)
|
||||
}
|
||||
|
||||
func (env *MockedEnvironment) getcwd() string {
|
||||
args := env.Called()
|
||||
return args.String(0)
|
||||
|
@ -208,38 +203,20 @@ func (env *MockedEnvironment) getWifiNetwork() (*wifiInfo, error) {
|
|||
return args.Get(0).(*wifiInfo), args.Error(1)
|
||||
}
|
||||
|
||||
func (env *MockedEnvironment) templateCache() *templateCache {
|
||||
args := env.Called()
|
||||
return args.Get(0).(*templateCache)
|
||||
}
|
||||
|
||||
func (env *MockedEnvironment) onTemplate() {
|
||||
patchMethodIfNotSpecified := func(method string, returnArguments ...interface{}) {
|
||||
for _, call := range env.Mock.ExpectedCalls {
|
||||
if call.Method == method {
|
||||
return
|
||||
}
|
||||
for _, call := range env.Mock.ExpectedCalls {
|
||||
if call.Method == "templateCache" {
|
||||
return
|
||||
}
|
||||
env.On(method).Return(returnArguments...)
|
||||
}
|
||||
patchEnvVars := func() map[string]string {
|
||||
keyValueArray := make(map[string]string)
|
||||
for _, call := range env.Mock.ExpectedCalls {
|
||||
if call.Method == "getenv" {
|
||||
keyValueArray[call.Arguments.String(0)] = call.ReturnArguments.String(0)
|
||||
}
|
||||
}
|
||||
return keyValueArray
|
||||
}
|
||||
patchMethodIfNotSpecified("isRunningAsRoot", false)
|
||||
patchMethodIfNotSpecified("getcwd", "/usr/home/dev/my-app")
|
||||
patchMethodIfNotSpecified("homeDir", "/usr/home/dev")
|
||||
patchMethodIfNotSpecified("getPathSeperator", "/")
|
||||
patchMethodIfNotSpecified("getShellName", "pwsh")
|
||||
patchMethodIfNotSpecified("getCurrentUser", "dev")
|
||||
patchMethodIfNotSpecified("getHostName", "laptop", nil)
|
||||
patchMethodIfNotSpecified("lastErrorCode", 0)
|
||||
patchMethodIfNotSpecified("getRuntimeGOOS", darwinPlatform)
|
||||
if env.getRuntimeGOOS() == linuxPlatform {
|
||||
env.On("getenv", "WSL_DISTRO_NAME").Return("ubuntu")
|
||||
env.On("getPlatform").Return("ubuntu")
|
||||
}
|
||||
patchMethodIfNotSpecified("environ", patchEnvVars())
|
||||
env.On("templateCache").Return(&templateCache{
|
||||
Env: make(map[string]string),
|
||||
})
|
||||
}
|
||||
|
||||
const (
|
||||
|
|
|
@ -328,6 +328,9 @@ func TestPlasticTemplateString(t *testing.T) {
|
|||
FetchStatus: true,
|
||||
}
|
||||
tc.Plastic.props = props
|
||||
env := new(MockedEnvironment)
|
||||
env.onTemplate()
|
||||
tc.Plastic.env = env
|
||||
assert.Equal(t, tc.Expected, tc.Plastic.templateString(tc.Template), tc.Case)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,9 +105,17 @@ func TestSessionSegmentTemplate(t *testing.T) {
|
|||
}
|
||||
env.On("getenv", "SSH_CONNECTION").Return(SSHSession)
|
||||
env.On("getenv", "SSH_CLIENT").Return(SSHSession)
|
||||
env.On("isRunningAsRoot").Return(tc.Root)
|
||||
env.On("getenv", defaultUserEnvVar).Return(tc.DefaultUserName)
|
||||
env.onTemplate()
|
||||
env.On("templateCache").Return(&templateCache{
|
||||
UserName: tc.UserName,
|
||||
HostName: tc.ComputerName,
|
||||
Env: map[string]string{
|
||||
"SSH_CONNECTION": SSHSession,
|
||||
"SSH_CLIENT": SSHSession,
|
||||
defaultUserEnvVar: tc.DefaultUserName,
|
||||
},
|
||||
Root: tc.Root,
|
||||
})
|
||||
session := &session{
|
||||
env: env,
|
||||
props: properties{
|
||||
|
|
|
@ -190,11 +190,14 @@ func TestGetColors(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
env := new(MockedEnvironment)
|
||||
env.onTemplate()
|
||||
segment := &Segment{
|
||||
writer: &aws{
|
||||
Profile: tc.Profile,
|
||||
Region: tc.Region,
|
||||
},
|
||||
env: env,
|
||||
}
|
||||
if tc.Background {
|
||||
segment.Background = tc.DefaultColor
|
||||
|
|
|
@ -24,16 +24,18 @@ func TestTextSegment(t *testing.T) {
|
|||
|
||||
for _, tc := range cases {
|
||||
env := new(MockedEnvironment)
|
||||
env.On("getcwd").Return("/usr/home/posh")
|
||||
env.On("homeDir").Return("/usr/home")
|
||||
env.On("getPathSeperator").Return("/")
|
||||
env.On("isRunningAsRoot").Return(true)
|
||||
env.On("getShellName").Return("terminal")
|
||||
env.On("getenv", "HELLO").Return("hello")
|
||||
env.On("getenv", "WORLD").Return("")
|
||||
env.On("getCurrentUser").Return("Posh")
|
||||
env.On("getHostName").Return("MyHost", nil)
|
||||
env.onTemplate()
|
||||
env.On("templateCache").Return(&templateCache{
|
||||
UserName: "Posh",
|
||||
Env: map[string]string{
|
||||
"HELLO": "hello",
|
||||
"WORLD": "",
|
||||
},
|
||||
HostName: "MyHost",
|
||||
Shell: "terminal",
|
||||
Root: true,
|
||||
Folder: base("/usr/home/posh", env),
|
||||
})
|
||||
txt := &text{
|
||||
env: env,
|
||||
props: properties{
|
||||
|
|
|
@ -12,9 +12,6 @@ const (
|
|||
// Errors to show when the template handling fails
|
||||
invalidTemplate = "invalid template text"
|
||||
incorrectTemplate = "unable to create text based on template"
|
||||
// nostruct = "unable to create map from non-struct type"
|
||||
|
||||
templateEnvRegex = `\.Env\.(?P<ENV>[^ \.}]*)`
|
||||
)
|
||||
|
||||
type textTemplate struct {
|
||||
|
@ -26,6 +23,13 @@ type textTemplate struct {
|
|||
type Data interface{}
|
||||
|
||||
type Context struct {
|
||||
templateCache
|
||||
|
||||
// Simple container to hold ANY object
|
||||
Data
|
||||
}
|
||||
|
||||
type templateCache struct {
|
||||
Root bool
|
||||
PWD string
|
||||
Folder string
|
||||
|
@ -35,37 +39,14 @@ type Context struct {
|
|||
Code int
|
||||
Env map[string]string
|
||||
OS string
|
||||
|
||||
// Simple container to hold ANY object
|
||||
Data
|
||||
}
|
||||
|
||||
func (c *Context) init(t *textTemplate) {
|
||||
c.Data = t.Context
|
||||
if t.Env == nil {
|
||||
if cache := t.Env.templateCache(); cache != nil {
|
||||
c.templateCache = *cache
|
||||
return
|
||||
}
|
||||
c.Root = t.Env.isRunningAsRoot()
|
||||
pwd := t.Env.getcwd()
|
||||
pwd = strings.Replace(pwd, t.Env.homeDir(), "~", 1)
|
||||
c.PWD = pwd
|
||||
c.Folder = base(c.PWD, t.Env)
|
||||
c.Shell = t.Env.getShellName()
|
||||
c.UserName = t.Env.getCurrentUser()
|
||||
if host, err := t.Env.getHostName(); err == nil {
|
||||
c.HostName = host
|
||||
}
|
||||
c.Code = t.Env.lastErrorCode()
|
||||
c.Env = t.Env.environ()
|
||||
goos := t.Env.getRuntimeGOOS()
|
||||
if goos == linuxPlatform {
|
||||
wsl := t.Env.getenv("WSL_DISTRO_NAME")
|
||||
goos = t.Env.getPlatform()
|
||||
if len(wsl) != 0 {
|
||||
goos = strings.ToLower(wsl)
|
||||
}
|
||||
}
|
||||
c.OS = goos
|
||||
}
|
||||
|
||||
func (t *textTemplate) render() (string, error) {
|
||||
|
|
|
@ -121,10 +121,9 @@ func TestRenderTemplateEnvVar(t *testing.T) {
|
|||
}
|
||||
for _, tc := range cases {
|
||||
env := &MockedEnvironment{}
|
||||
for name, value := range tc.Env {
|
||||
env.On("getenv", name).Return(value)
|
||||
}
|
||||
env.onTemplate()
|
||||
env.On("templateCache").Return(&templateCache{
|
||||
Env: tc.Env,
|
||||
})
|
||||
template := &textTemplate{
|
||||
Template: tc.Template,
|
||||
Context: tc.Context,
|
||||
|
|
Loading…
Reference in a new issue