refactor(segments): string() to template()

moves templating engine to Segment
This commit is contained in:
Jan De Dobbeleer 2022-01-23 21:37:51 +01:00 committed by Jan De Dobbeleer
parent 0987cafad0
commit f7a07c6b62
114 changed files with 1208 additions and 1718 deletions

View file

@ -9,7 +9,7 @@ import (
// MakeColors creates instance of AnsiColors to use in AnsiWriter according to // MakeColors creates instance of AnsiColors to use in AnsiWriter according to
// environment and configuration. // environment and configuration.
func MakeColors(env Environment, cfg *Config) AnsiColors { func MakeColors(env Environment, cfg *Config) AnsiColors {
cacheDisabled := env.getenv("OMP_CACHE_DISABLED") == "1" cacheDisabled := env.Getenv("OMP_CACHE_DISABLED") == "1"
return makeColors(cfg.Palette, !cacheDisabled) return makeColors(cfg.Palette, !cacheDisabled)
} }

View file

@ -66,8 +66,8 @@ func GetConfig(env Environment) *Config {
func loadConfig(env Environment) (*Config, error) { func loadConfig(env Environment) (*Config, error) {
var cfg Config var cfg Config
configFile := *env.getArgs().Config configFile := *env.Args().Config
eval := *env.getArgs().Eval eval := *env.Args().Eval
if configFile == "" { if configFile == "" {
return nil, errors.New("NO CONFIG") return nil, errors.New("NO CONFIG")
} }
@ -247,7 +247,7 @@ func getDefaultConfig(info string) *Config {
Background: "#ffffff", Background: "#ffffff",
Foreground: "#111111", Foreground: "#111111",
Properties: properties{ Properties: properties{
TextProperty: info, SegmentTemplate: info,
}, },
}, },
{ {

View file

@ -51,7 +51,7 @@ func (t *consoleTitle) getTemplateText() string {
} }
func (t *consoleTitle) getPwd() string { func (t *consoleTitle) getPwd() string {
pwd := t.env.pwd() pwd := t.env.Pwd()
pwd = strings.Replace(pwd, t.env.homeDir(), "~", 1) pwd = strings.Replace(pwd, t.env.Home(), "~", 1)
return pwd return pwd
} }

View file

@ -53,10 +53,10 @@ func TestGetConsoleTitle(t *testing.T) {
ConsoleTitleTemplate: tc.Template, ConsoleTitleTemplate: tc.Template,
} }
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("pwd").Return(tc.Cwd) env.On("Pwd").Return(tc.Cwd)
env.On("homeDir").Return("/usr/home") env.On("Home").Return("/usr/home")
env.On("getPathSeperator").Return(tc.PathSeperator) env.On("PathSeperator").Return(tc.PathSeperator)
env.On("templateCache").Return(&templateCache{ env.On("TemplateCache").Return(&TemplateCache{
Env: map[string]string{ Env: map[string]string{
"USERDOMAIN": "MyCompany", "USERDOMAIN": "MyCompany",
}, },
@ -67,7 +67,6 @@ func TestGetConsoleTitle(t *testing.T) {
PWD: tc.Cwd, PWD: tc.Cwd,
Folder: base(tc.Cwd, env), Folder: base(tc.Cwd, env),
}) })
env.onTemplate()
ansi := &ansiUtils{} ansi := &ansiUtils{}
ansi.init(tc.ShellName) ansi.init(tc.ShellName)
ct := &consoleTitle{ ct := &consoleTitle{
@ -115,9 +114,9 @@ func TestGetConsoleTitleIfGethostnameReturnsError(t *testing.T) {
ConsoleTitleTemplate: tc.Template, ConsoleTitleTemplate: tc.Template,
} }
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("pwd").Return(tc.Cwd) env.On("Pwd").Return(tc.Cwd)
env.On("homeDir").Return("/usr/home") env.On("Home").Return("/usr/home")
env.On("templateCache").Return(&templateCache{ env.On("TemplateCache").Return(&TemplateCache{
Env: map[string]string{ Env: map[string]string{
"USERDOMAIN": "MyCompany", "USERDOMAIN": "MyCompany",
}, },
@ -126,7 +125,6 @@ func TestGetConsoleTitleIfGethostnameReturnsError(t *testing.T) {
Root: tc.Root, Root: tc.Root,
HostName: "", HostName: "",
}) })
env.onTemplate()
ansi := &ansiUtils{} ansi := &ansiUtils{}
ansi.init(tc.ShellName) ansi.init(tc.ShellName)
ct := &consoleTitle{ ct := &consoleTitle{

View file

@ -35,7 +35,7 @@ func (e *engine) string() string {
func (e *engine) canWriteRPrompt() bool { func (e *engine) canWriteRPrompt() bool {
prompt := e.string() prompt := e.string()
consoleWidth, err := e.env.getTerminalWidth() consoleWidth, err := e.env.TerminalWidth()
if err != nil || consoleWidth == 0 { if err != nil || consoleWidth == 0 {
return true return true
} }
@ -66,7 +66,7 @@ func (e *engine) render() string {
if !e.config.OSC99 { if !e.config.OSC99 {
return e.print() return e.print()
} }
cwd := e.env.pwd() cwd := e.env.Pwd()
e.writeANSI(e.ansi.consolePwd(cwd)) e.writeANSI(e.ansi.consolePwd(cwd))
return e.print() return e.print()
} }
@ -74,7 +74,7 @@ func (e *engine) render() string {
func (e *engine) renderBlock(block *Block) { func (e *engine) renderBlock(block *Block) {
// when in bash, for rprompt blocks we need to write plain // when in bash, for rprompt blocks we need to write plain
// and wrap in escaped mode or the prompt will not render correctly // and wrap in escaped mode or the prompt will not render correctly
if block.Type == RPrompt && e.env.getShellName() == bash { if block.Type == RPrompt && e.env.Shell() == bash {
block.initPlain(e.env, e.config) block.initPlain(e.env, e.config)
} else { } else {
block.init(e.env, e.writer, e.ansi) block.init(e.env, e.writer, e.ansi)
@ -107,7 +107,7 @@ func (e *engine) renderBlock(block *Block) {
} }
case RPrompt: case RPrompt:
blockText := block.renderSegments() blockText := block.renderSegments()
if e.env.getShellName() == bash { if e.env.Shell() == bash {
blockText = fmt.Sprintf(e.ansi.bashFormat, blockText) blockText = fmt.Sprintf(e.ansi.bashFormat, blockText)
} }
e.rprompt = blockText e.rprompt = blockText
@ -161,16 +161,16 @@ func (e *engine) debug() string {
e.write(fmt.Sprintf("%-*s - %3d ms - %s\n", largestSegmentNameLength, segmentName, duration, segment.stringValue)) e.write(fmt.Sprintf("%-*s - %3d ms - %s\n", largestSegmentNameLength, segmentName, duration, segment.stringValue))
} }
e.write(fmt.Sprintf("\n\x1b[1mRun duration:\x1b[0m %s\n", time.Since(start))) e.write(fmt.Sprintf("\n\x1b[1mRun duration:\x1b[0m %s\n", time.Since(start)))
e.write(fmt.Sprintf("\n\x1b[1mCache path:\x1b[0m %s\n", e.env.getCachePath())) e.write(fmt.Sprintf("\n\x1b[1mCache path:\x1b[0m %s\n", e.env.CachePath()))
e.write("\n\x1b[1mLogs:\x1b[0m\n\n") e.write("\n\x1b[1mLogs:\x1b[0m\n\n")
e.write(e.env.logs()) e.write(e.env.Logs())
return e.string() return e.string()
} }
func (e *engine) print() string { func (e *engine) print() string {
switch e.env.getShellName() { switch e.env.Shell() {
case zsh: case zsh:
if !*e.env.getArgs().Eval { if !*e.env.Args().Eval {
break break
} }
// escape double quotes contained in the prompt // escape double quotes contained in the prompt
@ -214,7 +214,7 @@ func (e *engine) renderTooltip(tip string) string {
Alignment: Right, Alignment: Right,
Segments: []*Segment{tooltip}, Segments: []*Segment{tooltip},
} }
switch e.env.getShellName() { switch e.env.Shell() {
case zsh, winCMD: case zsh, winCMD:
block.init(e.env, e.writer, e.ansi) block.init(e.env, e.writer, e.ansi)
return block.renderSegments() return block.renderSegments()
@ -248,7 +248,7 @@ func (e *engine) renderTransientPrompt() string {
} }
e.writer.setColors(e.config.TransientPrompt.Background, e.config.TransientPrompt.Foreground) e.writer.setColors(e.config.TransientPrompt.Background, e.config.TransientPrompt.Foreground)
e.writer.write(e.config.TransientPrompt.Background, e.config.TransientPrompt.Foreground, prompt) e.writer.write(e.config.TransientPrompt.Background, e.config.TransientPrompt.Foreground, prompt)
switch e.env.getShellName() { switch e.env.Shell() {
case zsh: case zsh:
// escape double quotes contained in the prompt // escape double quotes contained in the prompt
prompt := fmt.Sprintf("PS1=\"%s\"", strings.ReplaceAll(e.writer.string(), "\"", "\"\"")) prompt := fmt.Sprintf("PS1=\"%s\"", strings.ReplaceAll(e.writer.string(), "\"", "\"\""))

View file

@ -30,7 +30,7 @@ func TestCanWriteRPrompt(t *testing.T) {
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("getTerminalWidth").Return(tc.TerminalWidth, tc.TerminalWidthError) env.On("TerminalWidth").Return(tc.TerminalWidth, tc.TerminalWidthError)
ansi := &ansiUtils{} ansi := &ansiUtils{}
ansi.init(plain) ansi.init(plain)
engine := &engine{ engine := &engine{
@ -73,7 +73,7 @@ func engineRender(configPath string) error {
execTime = 917.0 execTime = 917.0
) )
args := &args{ args := &Args{
Debug: &debug, Debug: &debug,
Config: &configPath, Config: &configPath,
Eval: &eval, Eval: &eval,
@ -87,13 +87,13 @@ func engineRender(configPath string) error {
env := &environment{} env := &environment{}
env.init(args) env.init(args)
defer env.close() defer env.Close()
cfg := GetConfig(env) cfg := GetConfig(env)
defer testClearDefaultConfig() defer testClearDefaultConfig()
ansi := &ansiUtils{} ansi := &ansiUtils{}
ansi.init(env.getShellName()) ansi.init(env.Shell())
writerColors := MakeColors(env, cfg) writerColors := MakeColors(env, cfg)
writer := &AnsiWriter{ writer := &AnsiWriter{
ansi: ansi, ansi: ansi,

View file

@ -41,18 +41,18 @@ func (m *noBatteryError) Error() string {
return "no battery" return "no battery"
} }
type fileInfo struct { type FileInfo struct {
parentFolder string ParentFolder string
path string Path string
isDir bool IsDir bool
} }
type cache interface { type Cache interface {
init(home string) Init(home string)
close() Close()
get(key string) (string, bool) Get(key string) (string, bool)
// ttl in minutes // ttl in minutes
set(key, value string, ttl int) Set(key, value string, ttl int)
} }
type HTTPRequestModifier func(request *http.Request) type HTTPRequestModifier func(request *http.Request)
@ -65,7 +65,7 @@ const (
regString regString
) )
type windowsRegistryValue struct { type WindowsRegistryValue struct {
valueType windowsRegistryValueType valueType windowsRegistryValueType
qword uint64 qword uint64
dword uint32 dword uint32
@ -74,7 +74,7 @@ type windowsRegistryValue struct {
type WifiType string type WifiType string
type wifiInfo struct { type WifiInfo struct {
SSID string SSID string
Interface string Interface string
RadioType WifiType RadioType WifiType
@ -89,45 +89,45 @@ type wifiInfo struct {
} }
type Environment interface { type Environment interface {
getenv(key string) string Getenv(key string) string
pwd() string Pwd() string
homeDir() string Home() string
hasFiles(pattern string) bool User() string
hasFilesInDir(dir, pattern string) bool Root() bool
hasFolder(folder string) bool Host() (string, error)
getFileContent(file string) string GOOS() string
getFoldersList(path string) []string Shell() string
getPathSeperator() string Platform() string
getCurrentUser() string ErrorCode() int
isRunningAsRoot() bool PathSeperator() string
getHostName() (string, error) HasFiles(pattern string) bool
getRuntimeGOOS() string HasFilesInDir(dir, pattern string) bool
getPlatform() string HasFolder(folder string) bool
hasCommand(command string) bool HasParentFilePath(path string) (fileInfo *FileInfo, err error)
runCommand(command string, args ...string) (string, error) HasCommand(command string) bool
runShellCommand(shell, command string) string FileContent(file string) string
lastErrorCode() int FolderList(path string) []string
executionTime() float64 RunCommand(command string, args ...string) (string, error)
getArgs() *args RunShellCommand(shell, command string) string
getBatteryInfo() ([]*battery.Battery, error) ExecutionTime() float64
getShellName() string Args() *Args
getWindowTitle(imageName, windowTitleRegex string) (string, error) BatteryInfo() ([]*battery.Battery, error)
getWindowsRegistryKeyValue(path string) (*windowsRegistryValue, error) WindowTitle(imageName, windowTitleRegex string) (string, error)
WindowsRegistryKeyValue(path string) (*WindowsRegistryValue, error)
HTTPRequest(url string, timeout int, requestModifiers ...HTTPRequestModifier) ([]byte, error) HTTPRequest(url string, timeout int, requestModifiers ...HTTPRequestModifier) ([]byte, error)
hasParentFilePath(path string) (fileInfo *fileInfo, err error) IsWsl() bool
isWsl() bool IsWsl2() bool
isWsl2() bool StackCount() int
stackCount() int TerminalWidth() (int, error)
getTerminalWidth() (int, error) CachePath() string
getCachePath() string Cache() Cache
cache() cache Close()
close() Logs() string
logs() string InWSLSharedDrive() bool
inWSLSharedDrive() bool ConvertToLinuxPath(path string) string
convertToLinuxPath(path string) string ConvertToWindowsPath(path string) string
convertToWindowsPath(path string) string WifiNetwork() (*WifiInfo, error)
getWifiNetwork() (*wifiInfo, error) TemplateCache() *TemplateCache
templateCache() *templateCache
} }
type commandCache struct { type commandCache struct {
@ -155,19 +155,19 @@ const (
) )
type environment struct { type environment struct {
args *args args *Args
cwd string cwd string
cmdCache *commandCache cmdCache *commandCache
fileCache *fileCache fileCache *fileCache
tmplCache *templateCache tmplCache *TemplateCache
logBuilder strings.Builder logBuilder strings.Builder
debug bool debug bool
} }
func (env *environment) init(args *args) { func (env *environment) init(args *Args) {
env.args = args env.args = args
env.fileCache = &fileCache{} env.fileCache = &fileCache{}
env.fileCache.init(env.getCachePath()) env.fileCache.Init(env.CachePath())
env.resolveConfigPath() env.resolveConfigPath()
env.cmdCache = &commandCache{ env.cmdCache = &commandCache{
commands: newConcurrentMap(), commands: newConcurrentMap(),
@ -184,13 +184,13 @@ func (env *environment) resolveConfigPath() {
} }
// Cygwin path always needs the full path as we're on Windows but not really. // Cygwin path always needs the full path as we're on Windows but not really.
// Doing filepath actions will convert it to a Windows path and break the init script. // Doing filepath actions will convert it to a Windows path and break the init script.
if env.getPlatform() == windowsPlatform && env.getShellName() == bash { if env.Platform() == windowsPlatform && env.Shell() == bash {
return return
} }
configFile := *env.args.Config configFile := *env.args.Config
if strings.HasPrefix(configFile, "~") { if strings.HasPrefix(configFile, "~") {
configFile = strings.TrimPrefix(configFile, "~") configFile = strings.TrimPrefix(configFile, "~")
configFile = filepath.Join(env.homeDir(), configFile) configFile = filepath.Join(env.Home(), configFile)
} }
if !filepath.IsAbs(configFile) { if !filepath.IsAbs(configFile) {
if absConfigFile, err := filepath.Abs(configFile); err == nil { if absConfigFile, err := filepath.Abs(configFile); err == nil {
@ -217,17 +217,17 @@ func (env *environment) log(lt logType, function, message string) {
log.Println(trace) log.Println(trace)
} }
func (env *environment) getenv(key string) string { func (env *environment) Getenv(key string) string {
defer env.trace(time.Now(), "getenv", key) defer env.trace(time.Now(), "Getenv", key)
val := os.Getenv(key) val := os.Getenv(key)
env.log(Debug, "getenv", val) env.log(Debug, "Getenv", val)
return val return val
} }
func (env *environment) pwd() string { func (env *environment) Pwd() string {
defer env.trace(time.Now(), "pwd") defer env.trace(time.Now(), "Pwd")
defer func() { defer func() {
env.log(Debug, "pwd", env.cwd) env.log(Debug, "Pwd", env.cwd)
}() }()
if env.cwd != "" { if env.cwd != "" {
return env.cwd return env.cwd
@ -243,57 +243,57 @@ func (env *environment) pwd() string {
} }
dir, err := os.Getwd() dir, err := os.Getwd()
if err != nil { if err != nil {
env.log(Error, "pwd", err.Error()) env.log(Error, "Pwd", err.Error())
return "" return ""
} }
env.cwd = correctPath(dir) env.cwd = correctPath(dir)
return env.cwd return env.cwd
} }
func (env *environment) hasFiles(pattern string) bool { func (env *environment) HasFiles(pattern string) bool {
defer env.trace(time.Now(), "hasFiles", pattern) defer env.trace(time.Now(), "HasFiles", pattern)
cwd := env.pwd() cwd := env.Pwd()
pattern = cwd + env.getPathSeperator() + pattern pattern = cwd + env.PathSeperator() + pattern
matches, err := filepath.Glob(pattern) matches, err := filepath.Glob(pattern)
if err != nil { if err != nil {
env.log(Error, "hasFiles", err.Error()) env.log(Error, "HasFiles", err.Error())
return false return false
} }
return len(matches) > 0 return len(matches) > 0
} }
func (env *environment) hasFilesInDir(dir, pattern string) bool { func (env *environment) HasFilesInDir(dir, pattern string) bool {
defer env.trace(time.Now(), "hasFilesInDir", pattern) defer env.trace(time.Now(), "HasFilesInDir", pattern)
pattern = dir + env.getPathSeperator() + pattern pattern = dir + env.PathSeperator() + pattern
matches, err := filepath.Glob(pattern) matches, err := filepath.Glob(pattern)
if err != nil { if err != nil {
env.log(Error, "hasFilesInDir", err.Error()) env.log(Error, "HasFilesInDir", err.Error())
return false return false
} }
return len(matches) > 0 return len(matches) > 0
} }
func (env *environment) hasFolder(folder string) bool { func (env *environment) HasFolder(folder string) bool {
defer env.trace(time.Now(), "hasFolder", folder) defer env.trace(time.Now(), "HasFolder", folder)
_, err := os.Stat(folder) _, err := os.Stat(folder)
return !os.IsNotExist(err) return !os.IsNotExist(err)
} }
func (env *environment) getFileContent(file string) string { func (env *environment) FileContent(file string) string {
defer env.trace(time.Now(), "getFileContent", file) defer env.trace(time.Now(), "FileContent", file)
content, err := ioutil.ReadFile(file) content, err := ioutil.ReadFile(file)
if err != nil { if err != nil {
env.log(Error, "getFileContent", err.Error()) env.log(Error, "FileContent", err.Error())
return "" return ""
} }
return string(content) return string(content)
} }
func (env *environment) getFoldersList(path string) []string { func (env *environment) FolderList(path string) []string {
defer env.trace(time.Now(), "getFoldersList", path) defer env.trace(time.Now(), "FolderList", path)
content, err := os.ReadDir(path) content, err := os.ReadDir(path)
if err != nil { if err != nil {
env.log(Error, "getFoldersList", err.Error()) env.log(Error, "FolderList", err.Error())
return nil return nil
} }
var folderNames []string var folderNames []string
@ -305,13 +305,13 @@ func (env *environment) getFoldersList(path string) []string {
return folderNames return folderNames
} }
func (env *environment) getPathSeperator() string { func (env *environment) PathSeperator() string {
defer env.trace(time.Now(), "getPathSeperator") defer env.trace(time.Now(), "PathSeperator")
return string(os.PathSeparator) return string(os.PathSeparator)
} }
func (env *environment) getCurrentUser() string { func (env *environment) User() string {
defer env.trace(time.Now(), "getCurrentUser") defer env.trace(time.Now(), "User")
user := os.Getenv("USER") user := os.Getenv("USER")
if user == "" { if user == "" {
user = os.Getenv("USERNAME") user = os.Getenv("USERNAME")
@ -319,23 +319,23 @@ func (env *environment) getCurrentUser() string {
return user return user
} }
func (env *environment) getHostName() (string, error) { func (env *environment) Host() (string, error) {
defer env.trace(time.Now(), "getHostName") defer env.trace(time.Now(), "Host")
hostName, err := os.Hostname() hostName, err := os.Hostname()
if err != nil { if err != nil {
env.log(Error, "getHostName", err.Error()) env.log(Error, "Host", err.Error())
return "", err return "", err
} }
return cleanHostName(hostName), nil return cleanHostName(hostName), nil
} }
func (env *environment) getRuntimeGOOS() string { func (env *environment) GOOS() string {
defer env.trace(time.Now(), "getRuntimeGOOS") defer env.trace(time.Now(), "GOOS")
return runtime.GOOS return runtime.GOOS
} }
func (env *environment) runCommand(command string, args ...string) (string, error) { func (env *environment) RunCommand(command string, args ...string) (string, error) {
defer env.trace(time.Now(), "runCommand", append([]string{command}, args...)...) defer env.trace(time.Now(), "RunCommand", append([]string{command}, args...)...)
if cmd, ok := env.cmdCache.get(command); ok { if cmd, ok := env.cmdCache.get(command); ok {
command = cmd command = cmd
} }
@ -348,22 +348,22 @@ func (env *environment) runCommand(command string, args ...string) (string, erro
if cmdErr != nil { if cmdErr != nil {
output := err.String() output := err.String()
errorStr := fmt.Sprintf("cmd.Start() failed with '%s'", output) errorStr := fmt.Sprintf("cmd.Start() failed with '%s'", output)
env.log(Error, "runCommand", errorStr) env.log(Error, "RunCommand", errorStr)
return output, cmdErr return output, cmdErr
} }
output := strings.TrimSuffix(out.String(), "\n") output := strings.TrimSuffix(out.String(), "\n")
env.log(Debug, "runCommand", output) env.log(Debug, "RunCommand", output)
return output, nil return output, nil
} }
func (env *environment) runShellCommand(shell, command string) string { func (env *environment) RunShellCommand(shell, command string) string {
defer env.trace(time.Now(), "runShellCommand", shell, command) defer env.trace(time.Now(), "RunShellCommand", shell, command)
out, _ := env.runCommand(shell, "-c", command) out, _ := env.RunCommand(shell, "-c", command)
return out return out
} }
func (env *environment) hasCommand(command string) bool { func (env *environment) HasCommand(command string) bool {
defer env.trace(time.Now(), "hasCommand", command) defer env.trace(time.Now(), "HasCommand", command)
if _, ok := env.cmdCache.get(command); ok { if _, ok := env.cmdCache.get(command); ok {
return true return true
} }
@ -372,34 +372,34 @@ func (env *environment) hasCommand(command string) bool {
env.cmdCache.set(command, path) env.cmdCache.set(command, path)
return true return true
} }
env.log(Error, "hasCommand", err.Error()) env.log(Error, "HasCommand", err.Error())
return false return false
} }
func (env *environment) lastErrorCode() int { func (env *environment) ErrorCode() int {
defer env.trace(time.Now(), "lastErrorCode") defer env.trace(time.Now(), "ErrorCode")
return *env.args.ErrorCode return *env.args.ErrorCode
} }
func (env *environment) executionTime() float64 { func (env *environment) ExecutionTime() float64 {
defer env.trace(time.Now(), "executionTime") defer env.trace(time.Now(), "ExecutionTime")
if *env.args.ExecutionTime < 0 { if *env.args.ExecutionTime < 0 {
return 0 return 0
} }
return *env.args.ExecutionTime return *env.args.ExecutionTime
} }
func (env *environment) getArgs() *args { func (env *environment) Args() *Args {
defer env.trace(time.Now(), "getArgs") defer env.trace(time.Now(), "Args")
return env.args return env.args
} }
func (env *environment) getBatteryInfo() ([]*battery.Battery, error) { func (env *environment) BatteryInfo() ([]*battery.Battery, error) {
defer env.trace(time.Now(), "getBatteryInfo") defer env.trace(time.Now(), "BatteryInfo")
batteries, err := battery.GetAll() batteries, err := battery.GetAll()
// actual error, return it // actual error, return it
if err != nil && len(batteries) == 0 { if err != nil && len(batteries) == 0 {
env.log(Error, "getBatteryInfo", err.Error()) env.log(Error, "BatteryInfo", err.Error())
return nil, err return nil, err
} }
// there are no batteries found // there are no batteries found
@ -447,15 +447,15 @@ func (env *environment) getBatteryInfo() ([]*battery.Battery, error) {
} }
// another error occurred (possibly unmapped use-case), return it // another error occurred (possibly unmapped use-case), return it
if fatalErr != nil { if fatalErr != nil {
env.log(Error, "getBatteryInfo", fatalErr.Error()) env.log(Error, "BatteryInfo", fatalErr.Error())
return nil, fatalErr return nil, fatalErr
} }
// everything is fine // everything is fine
return validBatteries, nil return validBatteries, nil
} }
func (env *environment) getShellName() string { func (env *environment) Shell() string {
defer env.trace(time.Now(), "getShellName") defer env.trace(time.Now(), "Shell")
if *env.args.Shell != "" { if *env.args.Shell != "" {
return *env.args.Shell return *env.args.Shell
} }
@ -463,7 +463,7 @@ func (env *environment) getShellName() string {
p, _ := process.NewProcess(int32(pid)) p, _ := process.NewProcess(int32(pid))
name, err := p.Name() name, err := p.Name()
if err != nil { if err != nil {
env.log(Error, "getShellName", err.Error()) env.log(Error, "Shell", err.Error())
return unknown return unknown
} }
if name == "cmd.exe" { if name == "cmd.exe" {
@ -471,7 +471,7 @@ func (env *environment) getShellName() string {
name, err = p.Name() name, err = p.Name()
} }
if err != nil { if err != nil {
env.log(Error, "getShellName", err.Error()) env.log(Error, "Shell", err.Error())
return unknown return unknown
} }
// Cache the shell value to speed things up. // Cache the shell value to speed things up.
@ -504,17 +504,17 @@ func (env *environment) HTTPRequest(url string, timeout int, requestModifiers ..
return body, nil return body, nil
} }
func (env *environment) hasParentFilePath(path string) (*fileInfo, error) { func (env *environment) HasParentFilePath(path string) (*FileInfo, error) {
defer env.trace(time.Now(), "hasParentFilePath", path) defer env.trace(time.Now(), "HasParentFilePath", path)
currentFolder := env.pwd() currentFolder := env.Pwd()
for { for {
searchPath := filepath.Join(currentFolder, path) searchPath := filepath.Join(currentFolder, path)
info, err := os.Stat(searchPath) info, err := os.Stat(searchPath)
if err == nil { if err == nil {
return &fileInfo{ return &FileInfo{
parentFolder: currentFolder, ParentFolder: currentFolder,
path: searchPath, Path: searchPath,
isDir: info.IsDir(), IsDir: info.IsDir(),
}, nil }, nil
} }
if !os.IsNotExist(err) { if !os.IsNotExist(err) {
@ -524,41 +524,41 @@ func (env *environment) hasParentFilePath(path string) (*fileInfo, error) {
currentFolder = dir currentFolder = dir
continue continue
} }
env.log(Error, "hasParentFilePath", err.Error()) env.log(Error, "HasParentFilePath", err.Error())
return nil, errors.New("no match at root level") return nil, errors.New("no match at root level")
} }
} }
func (env *environment) stackCount() int { func (env *environment) StackCount() int {
defer env.trace(time.Now(), "stackCount") defer env.trace(time.Now(), "StackCount")
if *env.args.StackCount < 0 { if *env.args.StackCount < 0 {
return 0 return 0
} }
return *env.args.StackCount return *env.args.StackCount
} }
func (env *environment) cache() cache { func (env *environment) Cache() Cache {
return env.fileCache return env.fileCache
} }
func (env *environment) close() { func (env *environment) Close() {
env.fileCache.close() env.fileCache.Close()
} }
func (env *environment) logs() string { func (env *environment) Logs() string {
return env.logBuilder.String() return env.logBuilder.String()
} }
func (env *environment) templateCache() *templateCache { func (env *environment) TemplateCache() *TemplateCache {
defer env.trace(time.Now(), "templateCache") defer env.trace(time.Now(), "TemplateCache")
if env.tmplCache != nil { if env.tmplCache != nil {
return env.tmplCache return env.tmplCache
} }
tmplCache := &templateCache{ tmplCache := &TemplateCache{
Root: env.isRunningAsRoot(), Root: env.Root(),
Shell: env.getShellName(), Shell: env.Shell(),
Code: env.lastErrorCode(), Code: env.ErrorCode(),
WSL: env.isWsl(), WSL: env.IsWsl(),
} }
tmplCache.Env = make(map[string]string) tmplCache.Env = make(map[string]string)
const separator = "=" const separator = "="
@ -572,15 +572,15 @@ func (env *environment) templateCache() *templateCache {
val := splitted[1:] val := splitted[1:]
tmplCache.Env[key] = strings.Join(val, separator) tmplCache.Env[key] = strings.Join(val, separator)
} }
pwd := env.pwd() pwd := env.Pwd()
pwd = strings.Replace(pwd, env.homeDir(), "~", 1) pwd = strings.Replace(pwd, env.Home(), "~", 1)
tmplCache.PWD = pwd tmplCache.PWD = pwd
tmplCache.Folder = base(pwd, env) tmplCache.Folder = base(pwd, env)
tmplCache.UserName = env.getCurrentUser() tmplCache.UserName = env.User()
if host, err := env.getHostName(); err == nil { if host, err := env.Host(); err == nil {
tmplCache.HostName = host tmplCache.HostName = host
} }
goos := env.getRuntimeGOOS() goos := env.GOOS()
tmplCache.OS = goos tmplCache.OS = goos
env.tmplCache = tmplCache env.tmplCache = tmplCache
return env.tmplCache return env.tmplCache

View file

@ -21,7 +21,7 @@ type fileCache struct {
cachePath string cachePath string
} }
func (fc *fileCache) init(cachePath string) { func (fc *fileCache) Init(cachePath string) {
fc.cache = newConcurrentMap() fc.cache = newConcurrentMap()
fc.cachePath = cachePath fc.cachePath = cachePath
content, err := ioutil.ReadFile(fc.cachePath + fileName) content, err := ioutil.ReadFile(fc.cachePath + fileName)
@ -39,7 +39,7 @@ func (fc *fileCache) init(cachePath string) {
} }
} }
func (fc *fileCache) close() { func (fc *fileCache) Close() {
cache := fc.cache.list() cache := fc.cache.list()
if len(cache) == 0 { if len(cache) == 0 {
return return
@ -51,7 +51,7 @@ func (fc *fileCache) close() {
// returns the value for the given key as long as // returns the value for the given key as long as
// the TTL (minutes) is not expired // the TTL (minutes) is not expired
func (fc *fileCache) get(key string) (string, bool) { func (fc *fileCache) Get(key string) (string, bool) {
val, found := fc.cache.get(key) val, found := fc.cache.get(key)
if !found { if !found {
return "", false return "", false
@ -72,7 +72,7 @@ func (fc *fileCache) get(key string) (string, bool) {
} }
// sets the value for the given key with a TTL (minutes) // sets the value for the given key with a TTL (minutes)
func (fc *fileCache) set(key, value string, ttl int) { func (fc *fileCache) Set(key, value string, ttl int) {
fc.cache.set(key, &cacheObject{ fc.cache.set(key, &cacheObject{
Value: value, Value: value,
Timestamp: time.Now().Unix(), Timestamp: time.Now().Unix(),

View file

@ -8,12 +8,12 @@ type MockedCache struct {
} }
// close provides a mock function with given fields: // close provides a mock function with given fields:
func (_m *MockedCache) close() { func (_m *MockedCache) Close() {
_m.Called() _m.Called()
} }
// get provides a mock function with given fields: key // get provides a mock function with given fields: key
func (_m *MockedCache) get(key string) (string, bool) { func (_m *MockedCache) Get(key string) (string, bool) {
ret := _m.Called(key) ret := _m.Called(key)
var r0 string var r0 string
@ -34,11 +34,11 @@ func (_m *MockedCache) get(key string) (string, bool) {
} }
// init provides a mock function with given fields: home // init provides a mock function with given fields: home
func (_m *MockedCache) init(home string) { func (_m *MockedCache) Init(home string) {
_m.Called(home) _m.Called(home)
} }
// set provides a mock function with given fields: key, value, ttl // set provides a mock function with given fields: key, value, ttl
func (_m *MockedCache) set(key, value string, ttl int) { func (_m *MockedCache) Set(key, value string, ttl int) {
_m.Called(key, value, ttl) _m.Called(key, value, ttl)
} }

View file

@ -37,10 +37,10 @@ func TestWindowsPathWithDriveLetter(t *testing.T) {
} }
for _, tc := range cases { for _, tc := range cases {
env := &environment{ env := &environment{
args: &args{ args: &Args{
PWD: &tc.CWD, PWD: &tc.CWD,
}, },
} }
assert.Equal(t, env.pwd(), tc.Expected) assert.Equal(t, env.Pwd(), tc.Expected)
} }
} }

View file

@ -12,56 +12,56 @@ import (
terminal "github.com/wayneashleyberry/terminal-dimensions" terminal "github.com/wayneashleyberry/terminal-dimensions"
) )
func (env *environment) isRunningAsRoot() bool { func (env *environment) Root() bool {
defer env.trace(time.Now(), "isRunningAsRoot") defer env.trace(time.Now(), "Root")
return os.Geteuid() == 0 return os.Geteuid() == 0
} }
func (env *environment) homeDir() string { func (env *environment) Home() string {
return os.Getenv("HOME") return os.Getenv("HOME")
} }
func (env *environment) getWindowTitle(imageName, windowTitleRegex string) (string, error) { func (env *environment) WindowTitle(imageName, windowTitleRegex string) (string, error) {
return "", errors.New("not implemented") return "", errors.New("not implemented")
} }
func (env *environment) isWsl() bool { func (env *environment) IsWsl() bool {
defer env.trace(time.Now(), "isWsl") defer env.trace(time.Now(), "IsWsl")
// one way to check // one way to check
// version := env.getFileContent("/proc/version") // version := env.FileContent("/proc/version")
// return strings.Contains(version, "microsoft") // return strings.Contains(version, "microsoft")
// using env variable // using env variable
return env.getenv("WSL_DISTRO_NAME") != "" return env.Getenv("WSL_DISTRO_NAME") != ""
} }
func (env *environment) isWsl2() bool { func (env *environment) IsWsl2() bool {
defer env.trace(time.Now(), "isWsl2") defer env.trace(time.Now(), "IsWsl2")
if !env.isWsl() { if !env.IsWsl() {
return false return false
} }
uname := env.getFileContent("/proc/sys/kernel/osrelease") uname := env.FileContent("/proc/sys/kernel/osrelease")
return strings.Contains(uname, "WSL2") return strings.Contains(uname, "WSL2")
} }
func (env *environment) getTerminalWidth() (int, error) { func (env *environment) TerminalWidth() (int, error) {
defer env.trace(time.Now(), "getTerminalWidth") defer env.trace(time.Now(), "TerminalWidth")
width, err := terminal.Width() width, err := terminal.Width()
if err != nil { if err != nil {
env.log(Error, "runCommand", err.Error()) env.log(Error, "RunCommand", err.Error())
} }
return int(width), err return int(width), err
} }
func (env *environment) getPlatform() string { func (env *environment) Platform() string {
const key = "environment_platform" const key = "environment_platform"
if val, found := env.cache().get(key); found { if val, found := env.Cache().Get(key); found {
return val return val
} }
var platform string var platform string
defer func() { defer func() {
env.cache().set(key, platform, -1) env.Cache().Set(key, platform, -1)
}() }()
if wsl := env.getenv("WSL_DISTRO_NAME"); len(wsl) != 0 { if wsl := env.Getenv("WSL_DISTRO_NAME"); len(wsl) != 0 {
platform = strings.ToLower(wsl) platform = strings.ToLower(wsl)
return platform return platform
} }
@ -69,43 +69,43 @@ func (env *environment) getPlatform() string {
return platform return platform
} }
func (env *environment) getCachePath() string { func (env *environment) CachePath() string {
defer env.trace(time.Now(), "getCachePath") defer env.trace(time.Now(), "CachePath")
// get XDG_CACHE_HOME if present // get XDG_CACHE_HOME if present
if cachePath := returnOrBuildCachePath(env.getenv("XDG_CACHE_HOME")); len(cachePath) != 0 { if cachePath := returnOrBuildCachePath(env.Getenv("XDG_CACHE_HOME")); len(cachePath) != 0 {
return cachePath return cachePath
} }
// HOME cache folder // HOME cache folder
if cachePath := returnOrBuildCachePath(env.homeDir() + "/.cache"); len(cachePath) != 0 { if cachePath := returnOrBuildCachePath(env.Home() + "/.cache"); len(cachePath) != 0 {
return cachePath return cachePath
} }
return env.homeDir() return env.Home()
} }
func (env *environment) getWindowsRegistryKeyValue(path string) (*windowsRegistryValue, error) { func (env *environment) WindowsRegistryKeyValue(path string) (*WindowsRegistryValue, error) {
return nil, errors.New("not implemented") return nil, errors.New("not implemented")
} }
func (env *environment) inWSLSharedDrive() bool { func (env *environment) InWSLSharedDrive() bool {
return env.isWsl() && strings.HasPrefix(env.pwd(), "/mnt/") return env.IsWsl() && strings.HasPrefix(env.Pwd(), "/mnt/")
} }
func (env *environment) convertToWindowsPath(path string) string { func (env *environment) ConvertToWindowsPath(path string) string {
windowsPath, err := env.runCommand("wslpath", "-w", path) windowsPath, err := env.RunCommand("wslpath", "-w", path)
if err == nil { if err == nil {
return windowsPath return windowsPath
} }
return path return path
} }
func (env *environment) convertToLinuxPath(path string) string { func (env *environment) ConvertToLinuxPath(path string) string {
linuxPath, err := env.runCommand("wslpath", "-u", path) linuxPath, err := env.RunCommand("wslpath", "-u", path)
if err == nil { if err == nil {
return linuxPath return linuxPath
} }
return path return path
} }
func (env *environment) getWifiNetwork() (*wifiInfo, error) { func (env *environment) WifiNetwork() (*WifiInfo, error) {
return nil, errors.New("not implemented") return nil, errors.New("not implemented")
} }

View file

@ -16,8 +16,8 @@ import (
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
) )
func (env *environment) isRunningAsRoot() bool { func (env *environment) Root() bool {
defer env.trace(time.Now(), "isRunningAsRoot") defer env.trace(time.Now(), "Root")
var sid *windows.SID var sid *windows.SID
// Although this looks scary, it is directly copied from the // Although this looks scary, it is directly copied from the
@ -32,7 +32,7 @@ func (env *environment) isRunningAsRoot() bool {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
&sid) &sid)
if err != nil { if err != nil {
env.log(Error, "isRunningAsRoot", err.Error()) env.log(Error, "Root", err.Error())
return false return false
} }
defer func() { defer func() {
@ -46,17 +46,17 @@ func (env *environment) isRunningAsRoot() bool {
member, err := token.IsMember(sid) member, err := token.IsMember(sid)
if err != nil { if err != nil {
env.log(Error, "isRunningAsRoot", err.Error()) env.log(Error, "Root", err.Error())
return false return false
} }
return member return member
} }
func (env *environment) homeDir() string { func (env *environment) Home() string {
home := os.Getenv("HOME") home := os.Getenv("HOME")
defer func() { defer func() {
env.log(Debug, "homeDir", home) env.log(Debug, "Home", home)
}() }()
if len(home) > 0 { if len(home) > 0 {
return home return home
@ -69,48 +69,48 @@ func (env *environment) homeDir() string {
return home return home
} }
func (env *environment) getWindowTitle(imageName, windowTitleRegex string) (string, error) { func (env *environment) WindowTitle(imageName, windowTitleRegex string) (string, error) {
defer env.trace(time.Now(), "getWindowTitle", imageName, windowTitleRegex) defer env.trace(time.Now(), "WindowTitle", imageName, windowTitleRegex)
return getWindowTitle(imageName, windowTitleRegex) return WindowTitle(imageName, windowTitleRegex)
} }
func (env *environment) isWsl() bool { func (env *environment) IsWsl() bool {
defer env.trace(time.Now(), "isWsl") defer env.trace(time.Now(), "IsWsl")
return false return false
} }
func (env *environment) isWsl2() bool { func (env *environment) IsWsl2() bool {
defer env.trace(time.Now(), "isWsl2") defer env.trace(time.Now(), "IsWsl2")
return false return false
} }
func (env *environment) getTerminalWidth() (int, error) { func (env *environment) TerminalWidth() (int, error) {
defer env.trace(time.Now(), "getTerminalWidth") defer env.trace(time.Now(), "TerminalWidth")
handle, err := syscall.Open("CONOUT$", syscall.O_RDWR, 0) handle, err := syscall.Open("CONOUT$", syscall.O_RDWR, 0)
if err != nil { if err != nil {
env.log(Error, "getTerminalWidth", err.Error()) env.log(Error, "TerminalWidth", err.Error())
return 0, err return 0, err
} }
info, err := winterm.GetConsoleScreenBufferInfo(uintptr(handle)) info, err := winterm.GetConsoleScreenBufferInfo(uintptr(handle))
if err != nil { if err != nil {
env.log(Error, "getTerminalWidth", err.Error()) env.log(Error, "TerminalWidth", err.Error())
return 0, err return 0, err
} }
// return int(float64(info.Size.X) * 0.57), nil // return int(float64(info.Size.X) * 0.57), nil
return int(info.Size.X), nil return int(info.Size.X), nil
} }
func (env *environment) getPlatform() string { func (env *environment) Platform() string {
return windowsPlatform return windowsPlatform
} }
func (env *environment) getCachePath() string { func (env *environment) CachePath() string {
defer env.trace(time.Now(), "getCachePath") defer env.trace(time.Now(), "CachePath")
// get LOCALAPPDATA if present // get LOCALAPPDATA if present
if cachePath := returnOrBuildCachePath(env.getenv("LOCALAPPDATA")); len(cachePath) != 0 { if cachePath := returnOrBuildCachePath(env.Getenv("LOCALAPPDATA")); len(cachePath) != 0 {
return cachePath return cachePath
} }
return env.homeDir() return env.Home()
} }
// //
@ -123,8 +123,8 @@ func (env *environment) getCachePath() string {
// //
// Returns a variant type if successful; nil and an error if not. // Returns a variant type if successful; nil and an error if not.
// //
func (env *environment) getWindowsRegistryKeyValue(path string) (*windowsRegistryValue, error) { func (env *environment) WindowsRegistryKeyValue(path string) (*windowsRegistryValue, error) {
env.trace(time.Now(), "getWindowsRegistryKeyValue", path) env.trace(time.Now(), "WindowsRegistryKeyValue", path)
// Format: // Format:
// "HKLM\Software\Microsoft\Windows NT\CurrentVersion\EditionID" // "HKLM\Software\Microsoft\Windows NT\CurrentVersion\EditionID"
@ -142,14 +142,14 @@ func (env *environment) getWindowsRegistryKeyValue(path string) (*windowsRegistr
if len(regPathParts) < 2 { if len(regPathParts) < 2 {
errorLogMsg := fmt.Sprintf("Error, malformed registry path: '%s'", path) errorLogMsg := fmt.Sprintf("Error, malformed registry path: '%s'", path)
env.log(Error, "getWindowsRegistryKeyValue", errorLogMsg) env.log(Error, "WindowsRegistryKeyValue", errorLogMsg)
return nil, errors.New(errorLogMsg) return nil, errors.New(errorLogMsg)
} }
regRootHKeyHandle := getHKEYHandleFromAbbrString(regPathParts[0]) regRootHKeyHandle := getHKEYHandleFromAbbrString(regPathParts[0])
if regRootHKeyHandle == 0 { if regRootHKeyHandle == 0 {
errorLogMsg := fmt.Sprintf("Error, Supplied root HKEY value not valid: '%s'", regPathParts[0]) errorLogMsg := fmt.Sprintf("Error, Supplied root HKEY value not valid: '%s'", regPathParts[0])
env.log(Error, "getWindowsRegistryKeyValue", errorLogMsg) env.log(Error, "WindowsRegistryKeyValue", errorLogMsg)
return nil, errors.New(errorLogMsg) return nil, errors.New(errorLogMsg)
} }
@ -158,7 +158,7 @@ func (env *environment) getWindowsRegistryKeyValue(path string) (*windowsRegistr
if lastSlash < 0 { if lastSlash < 0 {
errorLogMsg := fmt.Sprintf("Error, malformed registry path: '%s'", path) errorLogMsg := fmt.Sprintf("Error, malformed registry path: '%s'", path)
env.log(Error, "getWindowsRegistryKeyValue", errorLogMsg) env.log(Error, "WindowsRegistryKeyValue", errorLogMsg)
return nil, errors.New(errorLogMsg) return nil, errors.New(errorLogMsg)
} }
@ -170,13 +170,13 @@ func (env *environment) getWindowsRegistryKeyValue(path string) (*windowsRegistr
if len(regKeyLogged) == 0 { if len(regKeyLogged) == 0 {
regKeyLogged = "(Default)" regKeyLogged = "(Default)"
} }
env.log(Debug, "getWindowsRegistryKeyValue", fmt.Sprintf("getWindowsRegistryKeyValue: root:\"%s\", path:\"%s\", key:\"%s\"", regPathParts[0], regPath, regKeyLogged)) env.log(Debug, "WindowsRegistryKeyValue", fmt.Sprintf("WindowsRegistryKeyValue: root:\"%s\", path:\"%s\", key:\"%s\"", regPathParts[0], regPath, regKeyLogged))
// Second part of split is registry path after HK part - needs to be UTF16 to pass to the windows. API // Second part of split is registry path after HK part - needs to be UTF16 to pass to the windows. API
regPathUTF16, err := windows.UTF16FromString(regPath) regPathUTF16, err := windows.UTF16FromString(regPath)
if err != nil { if err != nil {
errorLogMsg := fmt.Sprintf("Error, Could not convert supplied path '%s' to UTF16, error: '%s'", regPath, err) errorLogMsg := fmt.Sprintf("Error, Could not convert supplied path '%s' to UTF16, error: '%s'", regPath, err)
env.log(Error, "getWindowsRegistryKeyValue", errorLogMsg) env.log(Error, "WindowsRegistryKeyValue", errorLogMsg)
return nil, errors.New(errorLogMsg) return nil, errors.New(errorLogMsg)
} }
@ -185,14 +185,14 @@ func (env *environment) getWindowsRegistryKeyValue(path string) (*windowsRegistr
regOpenErr := windows.RegOpenKeyEx(regRootHKeyHandle, &regPathUTF16[0], 0, windows.KEY_READ, &hKeyHandle) regOpenErr := windows.RegOpenKeyEx(regRootHKeyHandle, &regPathUTF16[0], 0, windows.KEY_READ, &hKeyHandle)
if regOpenErr != nil { if regOpenErr != nil {
errorLogMsg := fmt.Sprintf("Error RegOpenKeyEx opening registry path to '%s', error: '%s'", regPath, regOpenErr) errorLogMsg := fmt.Sprintf("Error RegOpenKeyEx opening registry path to '%s', error: '%s'", regPath, regOpenErr)
env.log(Error, "getWindowsRegistryKeyValue", errorLogMsg) env.log(Error, "WindowsRegistryKeyValue", errorLogMsg)
return nil, errors.New(errorLogMsg) return nil, errors.New(errorLogMsg)
} }
// Success - from here on out, when returning make sure to close that reg key with a deferred call to close: // Success - from here on out, when returning make sure to close that reg key with a deferred call to close:
defer func() { defer func() {
err := windows.RegCloseKey(hKeyHandle) err := windows.RegCloseKey(hKeyHandle)
if err != nil { if err != nil {
env.log(Error, "getWindowsRegistryKeyValue", fmt.Sprintf("Error closing registry key: %s", err)) env.log(Error, "WindowsRegistryKeyValue", fmt.Sprintf("Error closing registry key: %s", err))
} }
}() }()
@ -200,7 +200,7 @@ func (env *environment) getWindowsRegistryKeyValue(path string) (*windowsRegistr
regKeyUTF16, err := windows.UTF16FromString(regKey) regKeyUTF16, err := windows.UTF16FromString(regKey)
if err != nil { if err != nil {
errorLogMsg := fmt.Sprintf("Error, could not convert supplied key '%s' to UTF16, error: '%s'", regKey, err) errorLogMsg := fmt.Sprintf("Error, could not convert supplied key '%s' to UTF16, error: '%s'", regKey, err)
env.log(Error, "getWindowsRegistryKeyValue", errorLogMsg) env.log(Error, "WindowsRegistryKeyValue", errorLogMsg)
return nil, errors.New(errorLogMsg) return nil, errors.New(errorLogMsg)
} }
@ -211,7 +211,7 @@ func (env *environment) getWindowsRegistryKeyValue(path string) (*windowsRegistr
regQueryErr := windows.RegQueryValueEx(hKeyHandle, &regKeyUTF16[0], nil, &keyBufType, nil, &keyBufSize) regQueryErr := windows.RegQueryValueEx(hKeyHandle, &regKeyUTF16[0], nil, &keyBufType, nil, &keyBufSize)
if regQueryErr != nil { if regQueryErr != nil {
errorLogMsg := fmt.Sprintf("Error calling RegQueryValueEx to retrieve key data size with error '%s'", regQueryErr) errorLogMsg := fmt.Sprintf("Error calling RegQueryValueEx to retrieve key data size with error '%s'", regQueryErr)
env.log(Error, "getWindowsRegistryKeyValue", errorLogMsg) env.log(Error, "WindowsRegistryKeyValue", errorLogMsg)
return nil, errors.New(errorLogMsg) return nil, errors.New(errorLogMsg)
} }
@ -221,7 +221,7 @@ func (env *environment) getWindowsRegistryKeyValue(path string) (*windowsRegistr
regQueryErr = windows.RegQueryValueEx(hKeyHandle, &regKeyUTF16[0], nil, &keyBufType, &keyBuf[0], &keyBufSize) regQueryErr = windows.RegQueryValueEx(hKeyHandle, &regKeyUTF16[0], nil, &keyBufType, &keyBuf[0], &keyBufSize)
if regQueryErr != nil { if regQueryErr != nil {
errorLogMsg := fmt.Sprintf("Error calling RegQueryValueEx to retrieve key data with error '%s'", regQueryErr) errorLogMsg := fmt.Sprintf("Error calling RegQueryValueEx to retrieve key data with error '%s'", regQueryErr)
env.log(Error, "getWindowsRegistryKeyValue", errorLogMsg) env.log(Error, "WindowsRegistryKeyValue", errorLogMsg)
return nil, errors.New(errorLogMsg) return nil, errors.New(errorLogMsg)
} }
@ -232,20 +232,20 @@ func (env *environment) getWindowsRegistryKeyValue(path string) (*windowsRegistr
uint16p = (*uint16)(unsafe.Pointer(&keyBuf[0])) // nasty casty uint16p = (*uint16)(unsafe.Pointer(&keyBuf[0])) // nasty casty
valueString := windows.UTF16PtrToString(uint16p) valueString := windows.UTF16PtrToString(uint16p)
env.log(Debug, "getWindowsRegistryKeyValue", fmt.Sprintf("success, string: %s", valueString)) env.log(Debug, "WindowsRegistryKeyValue", fmt.Sprintf("success, string: %s", valueString))
return &windowsRegistryValue{valueType: regString, str: valueString}, nil return &windowsRegistryValue{valueType: regString, str: valueString}, nil
case windows.REG_DWORD: case windows.REG_DWORD:
var uint32p *uint32 var uint32p *uint32
uint32p = (*uint32)(unsafe.Pointer(&keyBuf[0])) // more casting goodness uint32p = (*uint32)(unsafe.Pointer(&keyBuf[0])) // more casting goodness
env.log(Debug, "getWindowsRegistryKeyValue", fmt.Sprintf("success, DWORD, 0x%08X", *uint32p)) env.log(Debug, "WindowsRegistryKeyValue", fmt.Sprintf("success, DWORD, 0x%08X", *uint32p))
return &windowsRegistryValue{valueType: regDword, dword: *uint32p}, nil return &windowsRegistryValue{valueType: regDword, dword: *uint32p}, nil
case windows.REG_QWORD: case windows.REG_QWORD:
var uint64p *uint64 var uint64p *uint64
uint64p = (*uint64)(unsafe.Pointer(&keyBuf[0])) // more casting goodness uint64p = (*uint64)(unsafe.Pointer(&keyBuf[0])) // more casting goodness
env.log(Debug, "getWindowsRegistryKeyValue", fmt.Sprintf("success, QWORD, 0x%016X", *uint64p)) env.log(Debug, "WindowsRegistryKeyValue", fmt.Sprintf("success, QWORD, 0x%016X", *uint64p))
return &windowsRegistryValue{valueType: regQword, qword: *uint64p}, nil return &windowsRegistryValue{valueType: regQword, qword: *uint64p}, nil
default: default:
errorLogMsg := fmt.Sprintf("Error, no formatter for REG_? type:%d, data size:%d bytes", keyBufType, keyBufSize) errorLogMsg := fmt.Sprintf("Error, no formatter for REG_? type:%d, data size:%d bytes", keyBufType, keyBufSize)
@ -253,15 +253,15 @@ func (env *environment) getWindowsRegistryKeyValue(path string) (*windowsRegistr
} }
} }
func (env *environment) inWSLSharedDrive() bool { func (env *environment) InWSLSharedDrive() bool {
return false return false
} }
func (env *environment) convertToWindowsPath(path string) string { func (env *environment) ConvertToWindowsPath(path string) string {
return path return path
} }
func (env *environment) convertToLinuxPath(path string) string { func (env *environment) ConvertToLinuxPath(path string) string {
return path return path
} }
@ -273,8 +273,8 @@ var (
hWlanQueryInterface = hapi.NewProc("WlanQueryInterface") hWlanQueryInterface = hapi.NewProc("WlanQueryInterface")
) )
func (env *environment) getWifiNetwork() (*wifiInfo, error) { func (env *environment) WifiNetwork() (*wifiInfo, error) {
env.trace(time.Now(), "getWifiNetwork") env.trace(time.Now(), "WifiNetwork")
// Open handle // Open handle
var pdwNegotiatedVersion uint32 var pdwNegotiatedVersion uint32
var phClientHandle uint32 var phClientHandle uint32

View file

@ -33,8 +33,8 @@ func getImagePid(imageName string) ([]int, error) {
return pids, nil return pids, nil
} }
// getWindowTitle returns the title of a window linked to a process name // WindowTitle returns the title of a window linked to a process name
func getWindowTitle(imageName, windowTitleRegex string) (string, error) { func WindowTitle(imageName, windowTitleRegex string) (string, error) {
processPid, err := getImagePid(imageName) processPid, err := getImagePid(imageName)
if err != nil { if err != nil {
return "", nil return "", nil

View file

@ -40,7 +40,7 @@ const (
plain = "shell" plain = "shell"
) )
type args struct { type Args struct {
ErrorCode *int ErrorCode *int
PrintConfig *bool PrintConfig *bool
ConfigFormat *string ConfigFormat *string
@ -70,7 +70,7 @@ type args struct {
} }
func main() { func main() {
args := &args{ args := &Args{
ErrorCode: flag.Int( ErrorCode: flag.Int(
"error", "error",
0, 0,
@ -183,9 +183,9 @@ func main() {
} }
env := &environment{} env := &environment{}
env.init(args) env.init(args)
defer env.close() defer env.Close()
if *args.PrintShell { if *args.PrintShell {
fmt.Println(env.getShellName()) fmt.Println(env.Shell())
return return
} }
if *args.Millis { if *args.Millis {
@ -193,7 +193,7 @@ func main() {
return return
} }
if *args.CachePath { if *args.CachePath {
fmt.Print(env.getCachePath()) fmt.Print(env.CachePath())
return return
} }
if *args.Init { if *args.Init {
@ -212,7 +212,7 @@ func main() {
} }
cfg := GetConfig(env) cfg := GetConfig(env)
ansi := &ansiUtils{} ansi := &ansiUtils{}
ansi.init(env.getShellName()) ansi.init(env.Shell())
var writer promptWriter var writer promptWriter
if *args.Plain { if *args.Plain {
writer = &PlainWriter{} writer = &PlainWriter{}

View file

@ -18,12 +18,11 @@ func TestConsoleBackgroundColorTemplate(t *testing.T) {
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("templateCache").Return(&templateCache{ env.On("TemplateCache").Return(&TemplateCache{
Env: map[string]string{ Env: map[string]string{
"TERM_PROGRAM": tc.Term, "TERM_PROGRAM": tc.Term,
}, },
}) })
env.onTemplate()
color := getConsoleBackgroundColor(env, "{{ if eq \"vscode\" .Env.TERM_PROGRAM }}#123456{{end}}") color := getConsoleBackgroundColor(env, "{{ if eq \"vscode\" .Env.TERM_PROGRAM }}#123456{{end}}")
assert.Equal(t, tc.Expected, color, tc.Case) assert.Equal(t, tc.Expected, color, tc.Case)
} }

View file

@ -82,7 +82,7 @@ func matchString(pattern, text string) bool {
func dirMatchesOneOf(env Environment, dir string, regexes []string) bool { func dirMatchesOneOf(env Environment, dir string, regexes []string) bool {
normalizedCwd := strings.ReplaceAll(dir, "\\", "/") normalizedCwd := strings.ReplaceAll(dir, "\\", "/")
normalizedHomeDir := strings.ReplaceAll(env.homeDir(), "\\", "/") normalizedHomeDir := strings.ReplaceAll(env.Home(), "\\", "/")
for _, element := range regexes { for _, element := range regexes {
normalizedElement := strings.ReplaceAll(element, "\\\\", "/") normalizedElement := strings.ReplaceAll(element, "\\\\", "/")
@ -90,7 +90,7 @@ func dirMatchesOneOf(env Environment, dir string, regexes []string) bool {
normalizedElement = strings.Replace(normalizedElement, "~", normalizedHomeDir, 1) normalizedElement = strings.Replace(normalizedElement, "~", normalizedHomeDir, 1)
} }
pattern := fmt.Sprintf("^%s$", normalizedElement) pattern := fmt.Sprintf("^%s$", normalizedElement)
goos := env.getRuntimeGOOS() goos := env.GOOS()
if goos == windowsPlatform || goos == darwinPlatform { if goos == windowsPlatform || goos == darwinPlatform {
pattern = "(?i)" + pattern pattern = "(?i)" + pattern
} }

View file

@ -32,8 +32,8 @@ func TestDirMatchesOneOf(t *testing.T) {
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("getRuntimeGOOS").Return(tc.GOOS) env.On("GOOS").Return(tc.GOOS)
env.On("homeDir").Return(tc.HomeDir) env.On("Home").Return(tc.HomeDir)
got := dirMatchesOneOf(env, tc.Dir, []string{tc.Pattern}) got := dirMatchesOneOf(env, tc.Dir, []string{tc.Pattern})
assert.Equal(t, tc.Expected, got) assert.Equal(t, tc.Expected, got)
} }

View file

@ -75,6 +75,6 @@ func (s *scm) shouldIgnoreRootRepository(rootDir string) bool {
return dirMatchesOneOf(s.env, rootDir, excludedFolders) return dirMatchesOneOf(s.env, rootDir, excludedFolders)
} }
func (s *scm) getFileContents(folder, file string) string { func (s *scm) FileContents(folder, file string) string {
return strings.Trim(s.env.getFileContent(folder+"/"+file), " \r\n") return strings.Trim(s.env.FileContent(folder+"/"+file), " \r\n")
} }

View file

@ -174,8 +174,8 @@ func TestScmShouldIgnoreRootRepository(t *testing.T) {
}, },
} }
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("homeDir").Return("/home/bill") env.On("Home").Return("/home/bill")
env.On("getRuntimeGOOS").Return(windowsPlatform) env.On("GOOS").Return(windowsPlatform)
s := &scm{ s := &scm{
props: props, props: props,
env: env, env: env,

View file

@ -50,7 +50,7 @@ type Properties interface {
// SegmentWriter is the interface used to define what and if to write to the prompt // SegmentWriter is the interface used to define what and if to write to the prompt
type SegmentWriter interface { type SegmentWriter interface {
enabled() bool enabled() bool
string() string template() string
init(props Properties, env Environment) init(props Properties, env Environment)
} }
@ -156,7 +156,16 @@ const (
) )
func (segment *Segment) string() string { func (segment *Segment) string() string {
return segment.writer.string() template := &textTemplate{
Template: segment.writer.template(),
Context: segment.writer,
Env: segment.env,
}
text, err := template.render()
if err != nil {
return err.Error()
}
return text
} }
func (segment *Segment) enabled() bool { func (segment *Segment) enabled() bool {
@ -191,7 +200,7 @@ func (segment *Segment) cwdIncluded() bool {
return true return true
} }
return dirMatchesOneOf(segment.env, segment.env.pwd(), list) return dirMatchesOneOf(segment.env, segment.env.Pwd(), list)
} }
func (segment *Segment) cwdExcluded() bool { func (segment *Segment) cwdExcluded() bool {
@ -200,7 +209,7 @@ func (segment *Segment) cwdExcluded() bool {
value = segment.Properties[IgnoreFolders] value = segment.Properties[IgnoreFolders]
} }
list := parseStringArray(value) list := parseStringArray(value)
return dirMatchesOneOf(segment.env, segment.env.pwd(), list) return dirMatchesOneOf(segment.env, segment.env.Pwd(), list)
} }
func (segment *Segment) getColor(templates []string, defaultColor string) string { func (segment *Segment) getColor(templates []string, defaultColor string) string {

View file

@ -9,9 +9,8 @@ type angular struct {
language language
} }
func (a *angular) string() string { func (a *angular) template() string {
segmentTemplate := a.language.props.getString(SegmentTemplate, "{{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }}") return languageTemplate
return a.language.string(segmentTemplate, a)
} }
func (a *angular) init(props Properties, env Environment) { func (a *angular) init(props Properties, env Environment) {
@ -25,13 +24,13 @@ func (a *angular) init(props Properties, env Environment) {
getVersion: func() (string, error) { getVersion: func() (string, error) {
const fileName string = "package.json" const fileName string = "package.json"
const fileFolder string = "/node_modules/@angular/core" const fileFolder string = "/node_modules/@angular/core"
angularFilePath := a.language.env.pwd() + fileFolder angularFilePath := a.language.env.Pwd() + fileFolder
if !a.language.env.hasFilesInDir(angularFilePath, fileName) { if !a.language.env.HasFilesInDir(angularFilePath, fileName) {
return "", fmt.Errorf("%s not found in %s", fileName, angularFilePath) return "", fmt.Errorf("%s not found in %s", fileName, angularFilePath)
} }
// parse file // parse file
objmap := map[string]json.RawMessage{} objmap := map[string]json.RawMessage{}
content := a.language.env.getFileContent(a.language.env.pwd() + fileFolder + "/" + fileName) content := a.language.env.FileContent(a.language.env.Pwd() + fileFolder + "/" + fileName)
err := json.Unmarshal([]byte(content), &objmap) err := json.Unmarshal([]byte(content), &objmap)
if err != nil { if err != nil {
return "", err return "", err

View file

@ -10,11 +10,11 @@ import (
func TestAngularCliVersionDisplayed(t *testing.T) { func TestAngularCliVersionDisplayed(t *testing.T) {
cases := []struct { cases := []struct {
Case string Case string
ExpectedString string FullVersion string
Version string Version string
}{ }{
{Case: "Angular 13.0.3", ExpectedString: "13.0.3", Version: "{ \"name\": \"@angular/core\",\"version\": \"13.0.3\"}"}, {Case: "Angular 13.0.3", FullVersion: "13.0.3", Version: "{ \"name\": \"@angular/core\",\"version\": \"13.0.3\"}"},
{Case: "Angular 11.0.1", ExpectedString: "11.0.1", Version: "{ \"name\": \"@angular/core\",\"version\": \"11.0.1\"}"}, {Case: "Angular 11.0.1", FullVersion: "11.0.1", Version: "{ \"name\": \"@angular/core\",\"version\": \"11.0.1\"}"},
} }
for _, ta := range cases { for _, ta := range cases {
@ -24,16 +24,18 @@ func TestAngularCliVersionDisplayed(t *testing.T) {
var env = new(MockedEnvironment) var env = new(MockedEnvironment)
// mock getVersion methods // mock getVersion methods
env.On("pwd").Return("/usr/home/dev/my-app") env.On("Pwd").Return("/usr/home/dev/my-app")
env.On("homeDir").Return("/usr/home") env.On("Home").Return("/usr/home")
env.On("hasFiles", params.extension).Return(true) env.On("HasFiles", params.extension).Return(true)
env.On("hasFilesInDir", "/usr/home/dev/my-app/node_modules/@angular/core", "package.json").Return(true) env.On("HasFilesInDir", "/usr/home/dev/my-app/node_modules/@angular/core", "package.json").Return(true)
env.On("getFileContent", "/usr/home/dev/my-app/node_modules/@angular/core/package.json").Return(ta.Version) env.On("FileContent", "/usr/home/dev/my-app/node_modules/@angular/core/package.json").Return(ta.Version)
env.onTemplate() env.On("TemplateCache").Return(&TemplateCache{
Env: make(map[string]string),
})
props := properties{} props := properties{}
angular := &angular{} angular := &angular{}
angular.init(props, env) angular.init(props, env)
assert.True(t, angular.enabled(), fmt.Sprintf("Failed in case: %s", ta.Case)) assert.True(t, angular.enabled(), fmt.Sprintf("Failed in case: %s", ta.Case))
assert.Equal(t, ta.ExpectedString, angular.string(), fmt.Sprintf("Failed in case: %s", ta.Case)) assert.Equal(t, ta.FullVersion, renderTemplate(env, angular.template(), angular), fmt.Sprintf("Failed in case: %s", ta.Case))
} }
} }

View file

@ -16,6 +16,10 @@ const (
defaultUser = "default" defaultUser = "default"
) )
func (a *aws) template() string {
return "{{ .Profile }}{{ if .Region }}@{{ .Region }}{{ end }}"
}
func (a *aws) init(props Properties, env Environment) { func (a *aws) init(props Properties, env Environment) {
a.props = props a.props = props
a.env = env a.env = env
@ -24,7 +28,7 @@ func (a *aws) init(props Properties, env Environment) {
func (a *aws) enabled() bool { func (a *aws) enabled() bool {
getEnvFirstMatch := func(envs ...string) string { getEnvFirstMatch := func(envs ...string) string {
for _, env := range envs { for _, env := range envs {
value := a.env.getenv(env) value := a.env.Getenv(env)
if value != "" { if value != "" {
return value return value
} }
@ -52,11 +56,11 @@ func (a *aws) enabled() bool {
} }
func (a *aws) getConfigFileInfo() { func (a *aws) getConfigFileInfo() {
configPath := a.env.getenv("AWS_CONFIG_FILE") configPath := a.env.Getenv("AWS_CONFIG_FILE")
if configPath == "" { if configPath == "" {
configPath = fmt.Sprintf("%s/.aws/config", a.env.homeDir()) configPath = fmt.Sprintf("%s/.aws/config", a.env.Home())
} }
config := a.env.getFileContent(configPath) config := a.env.FileContent(configPath)
configSection := "[default]" configSection := "[default]"
if a.Profile != "" { if a.Profile != "" {
configSection = fmt.Sprintf("[profile %s]", a.Profile) configSection = fmt.Sprintf("[profile %s]", a.Profile)
@ -80,17 +84,3 @@ func (a *aws) getConfigFileInfo() {
a.Profile = defaultUser a.Profile = defaultUser
} }
} }
func (a *aws) string() string {
segmentTemplate := a.props.getString(SegmentTemplate, "{{.Profile}}{{if .Region}}@{{.Region}}{{end}}")
template := &textTemplate{
Template: segmentTemplate,
Context: a,
Env: a.env,
}
text, err := template.render()
if err != nil {
return err.Error()
}
return text
}

View file

@ -47,26 +47,24 @@ func TestAWSSegment(t *testing.T) {
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("getenv", "AWS_VAULT").Return(tc.Vault) env.On("Getenv", "AWS_VAULT").Return(tc.Vault)
env.On("getenv", "AWS_PROFILE").Return(tc.Profile) env.On("Getenv", "AWS_PROFILE").Return(tc.Profile)
env.On("getenv", "AWS_REGION").Return(tc.Region) env.On("Getenv", "AWS_REGION").Return(tc.Region)
env.On("getenv", "AWS_DEFAULT_REGION").Return(tc.DefaultRegion) env.On("Getenv", "AWS_DEFAULT_REGION").Return(tc.DefaultRegion)
env.On("getenv", "AWS_CONFIG_FILE").Return(tc.ConfigFile) env.On("Getenv", "AWS_CONFIG_FILE").Return(tc.ConfigFile)
env.On("getFileContent", "/usr/home/.aws/config").Return("") env.On("FileContent", "/usr/home/.aws/config").Return("")
env.On("homeDir").Return("/usr/home") env.On("Home").Return("/usr/home")
env.onTemplate()
props := properties{ props := properties{
DisplayDefault: tc.DisplayDefault, DisplayDefault: tc.DisplayDefault,
} }
if tc.Template != "" {
props[SegmentTemplate] = tc.Template
}
aws := &aws{ aws := &aws{
env: env, env: env,
props: props, props: props,
} }
if tc.Template == "" {
tc.Template = aws.template()
}
assert.Equal(t, tc.ExpectedEnabled, aws.enabled(), tc.Case) assert.Equal(t, tc.ExpectedEnabled, aws.enabled(), tc.Case)
assert.Equal(t, tc.ExpectedString, aws.string(), tc.Case) assert.Equal(t, tc.ExpectedString, renderTemplate(env, tc.Template, aws), tc.Case)
} }
} }

View file

@ -78,18 +78,8 @@ type AzurePowerShellSubscription struct {
} `json:"Environment"` } `json:"Environment"`
} }
func (a *az) string() string { func (a *az) template() string {
segmentTemplate := a.props.getString(SegmentTemplate, "{{ .Name }}") return "{{ .Name }}"
template := &textTemplate{
Template: segmentTemplate,
Context: a,
Env: a.env,
}
text, err := template.render()
if err != nil {
return err.Error()
}
return text
} }
func (a *az) init(props Properties, env Environment) { func (a *az) init(props Properties, env Environment) {
@ -101,16 +91,16 @@ func (a *az) enabled() bool {
return a.getAzureProfile() || a.getAzureRmContext() return a.getAzureProfile() || a.getAzureRmContext()
} }
func (a *az) getFileContentWithoutBom(file string) string { func (a *az) FileContentWithoutBom(file string) string {
config := a.env.getFileContent(file) config := a.env.FileContent(file)
const ByteOrderMark = "\ufeff" const ByteOrderMark = "\ufeff"
return strings.TrimLeft(config, ByteOrderMark) return strings.TrimLeft(config, ByteOrderMark)
} }
func (a *az) getAzureProfile() bool { func (a *az) getAzureProfile() bool {
var content string var content string
profile := filepath.Join(a.env.homeDir(), ".azure", "azureProfile.json") profile := filepath.Join(a.env.Home(), ".azure", "azureProfile.json")
if content = a.getFileContentWithoutBom(profile); len(content) == 0 { if content = a.FileContentWithoutBom(profile); len(content) == 0 {
return false return false
} }
var config AzureConfig var config AzureConfig
@ -130,11 +120,11 @@ func (a *az) getAzureProfile() bool {
func (a *az) getAzureRmContext() bool { func (a *az) getAzureRmContext() bool {
var content string var content string
profiles := []string{ profiles := []string{
filepath.Join(a.env.homeDir(), ".azure", "AzureRmContext.json"), filepath.Join(a.env.Home(), ".azure", "AzureRmContext.json"),
filepath.Join(a.env.homeDir(), ".Azure", "AzureRmContext.json"), filepath.Join(a.env.Home(), ".Azure", "AzureRmContext.json"),
} }
for _, profile := range profiles { for _, profile := range profiles {
if content = a.getFileContentWithoutBom(profile); len(content) != 0 { if content = a.FileContentWithoutBom(profile); len(content) != 0 {
break break
} }
} }

View file

@ -4,9 +4,8 @@ type azfunc struct {
language language
} }
func (az *azfunc) string() string { func (az *azfunc) template() string {
segmentTemplate := az.language.props.getString(SegmentTemplate, "{{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }}") return languageTemplate
return az.language.string(segmentTemplate, az)
} }
func (az *azfunc) init(props Properties, env Environment) { func (az *azfunc) init(props Properties, env Environment) {

View file

@ -69,7 +69,7 @@ func TestAzSegment(t *testing.T) {
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
home := "/Users/posh" home := "/Users/posh"
env.On("homeDir").Return(home) env.On("Home").Return(home)
var azureProfile, azureRmContext, azureRMContext string var azureProfile, azureRmContext, azureRMContext string
if tc.HasCLI { if tc.HasCLI {
content, _ := ioutil.ReadFile("./test/azureProfile.json") content, _ := ioutil.ReadFile("./test/azureProfile.json")
@ -83,19 +83,15 @@ func TestAzSegment(t *testing.T) {
content, _ := ioutil.ReadFile("./test/AzureRmContext.json") content, _ := ioutil.ReadFile("./test/AzureRmContext.json")
azureRMContext = string(content) azureRMContext = string(content)
} }
env.On("getRuntimeGOOS").Return(linuxPlatform) env.On("GOOS").Return(linuxPlatform)
env.On("getFileContent", filepath.Join(home, ".azure", "azureProfile.json")).Return(azureProfile) env.On("FileContent", filepath.Join(home, ".azure", "azureProfile.json")).Return(azureProfile)
env.On("getFileContent", filepath.Join(home, ".Azure", "AzureRmContext.json")).Return(azureRmContext) env.On("FileContent", filepath.Join(home, ".Azure", "AzureRmContext.json")).Return(azureRmContext)
env.On("getFileContent", filepath.Join(home, ".azure", "AzureRmContext.json")).Return(azureRMContext) env.On("FileContent", filepath.Join(home, ".azure", "AzureRmContext.json")).Return(azureRMContext)
env.onTemplate()
props := properties{
SegmentTemplate: tc.Template,
}
az := &az{ az := &az{
env: env, env: env,
props: props, props: properties{},
} }
assert.Equal(t, tc.ExpectedEnabled, az.enabled(), tc.Case) assert.Equal(t, tc.ExpectedEnabled, az.enabled(), tc.Case)
assert.Equal(t, tc.ExpectedString, az.string(), tc.Case) assert.Equal(t, tc.ExpectedString, renderTemplate(env, tc.Template, az), tc.Case)
} }
} }

View file

@ -25,8 +25,12 @@ const (
ChargedIcon Property = "charged_icon" ChargedIcon Property = "charged_icon"
) )
func (b *batt) template() string {
return "{{ if not .Error }}{{.Icon}}{{.Percentage}}{{ end }}{{.Error}}"
}
func (b *batt) enabled() bool { func (b *batt) enabled() bool {
batteries, err := b.env.getBatteryInfo() batteries, err := b.env.BatteryInfo()
if !b.enabledWhileError(err) { if !b.enabledWhileError(err) {
return false return false
@ -99,20 +103,6 @@ func (b *batt) mapMostLogicalState(currentState, newState battery.State) battery
return newState return newState
} }
func (b *batt) string() string {
segmentTemplate := b.props.getString(SegmentTemplate, "{{ if not .Error }}{{.Icon}}{{.Percentage}}{{ end }}{{.Error}}")
template := &textTemplate{
Template: segmentTemplate,
Context: b,
Env: b.env,
}
text, err := template.render()
if err != nil {
return err.Error()
}
return text
}
func (b *batt) init(props Properties, env Environment) { func (b *batt) init(props Properties, env Environment) {
b.props = props b.props = props
b.env = env b.env = env

View file

@ -7,82 +7,6 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestGetBatteryColors(t *testing.T) {
cases := []struct {
Case string
ExpectedColor string
Templates []string
DefaultColor string
Battery *battery.Battery
Percentage int
}{
{
Case: "Percentage lower",
ExpectedColor: "color2",
DefaultColor: "color",
Templates: []string{
"{{if (lt .Percentage 60)}}color2{{end}}",
"{{if (gt .Percentage 60)}}color3{{end}}",
},
Percentage: 50,
},
{
Case: "Percentage higher",
ExpectedColor: "color3",
DefaultColor: "color",
Templates: []string{
"{{if (lt .Percentage 60)}}color2{{end}}",
"{{if (gt .Percentage 60)}}color3{{end}}",
},
Percentage: 70,
},
{
Case: "Charging",
ExpectedColor: "color2",
DefaultColor: "color",
Templates: []string{
"{{if eq \"Charging\" .Battery.State.String}}color2{{end}}",
"{{if eq \"Discharging\" .Battery.State.String}}color3{{end}}",
"{{if eq \"Full\" .Battery.State.String}}color4{{end}}",
},
Battery: &battery.Battery{
State: battery.Charging,
},
},
{
Case: "Discharging",
ExpectedColor: "color3",
DefaultColor: "color",
Templates: []string{
"{{if eq \"Charging\" .Battery.State.String}}color2{{end}}",
"{{if eq \"Discharging\" .Battery.State.String}}color3{{end}}",
"{{if eq \"Full\" .Battery.State.String}}color2{{end}}",
},
Battery: &battery.Battery{
State: battery.Discharging,
},
},
}
for _, tc := range cases {
env := new(MockedEnvironment)
env.onTemplate()
batt := &batt{
Percentage: tc.Percentage,
}
if tc.Battery != nil {
batt.Battery = *tc.Battery
}
segment := &Segment{
writer: batt,
env: env,
}
segment.Foreground = tc.DefaultColor
segment.ForegroundTemplates = tc.Templates
color := segment.foreground()
assert.Equal(t, tc.ExpectedColor, color, tc.Case)
}
}
func TestMapBatteriesState(t *testing.T) { func TestMapBatteriesState(t *testing.T) {
cases := []struct { cases := []struct {
Case string Case string

View file

@ -98,6 +98,10 @@ type Batch struct {
TemperatureTrend float64 // diff between this and last, short term trend TemperatureTrend float64 // diff between this and last, short term trend
} }
func (bf *brewfather) template() string {
return DefaultTemplate
}
func (bf *brewfather) enabled() bool { func (bf *brewfather) enabled() bool {
data, err := bf.getResult() data, err := bf.getResult()
if err != nil { if err != nil {
@ -197,24 +201,9 @@ func (bf *brewfather) getBatchStatusIcon(batchStatus string) string {
} }
} }
func (bf *brewfather) string() string {
segmentTemplate := bf.props.getString(SegmentTemplate, DefaultTemplate)
template := &textTemplate{
Template: segmentTemplate,
Context: bf,
Env: bf.env,
}
text, err := template.render()
if err != nil {
return err.Error()
}
return text
}
func (bf *brewfather) getResult() (*Batch, error) { func (bf *brewfather) getResult() (*Batch, error) {
getFromCache := func(key string) (*Batch, error) { getFromCache := func(key string) (*Batch, error) {
val, found := bf.env.cache().get(key) val, found := bf.env.Cache().Get(key)
// we got something from the cache // we got something from the cache
if found { if found {
var result Batch var result Batch
@ -232,7 +221,7 @@ func (bf *brewfather) getResult() (*Batch, error) {
return err return err
} }
bf.env.cache().set(key, string(cacheJSON), cacheTimeout) bf.env.Cache().Set(key, string(cacheJSON), cacheTimeout)
return nil return nil
} }

View file

@ -145,16 +145,12 @@ func TestBrewfatherSegment(t *testing.T) {
} }
cache := &MockedCache{} cache := &MockedCache{}
cache.On("get", BFCacheKey).Return(nil, false) // cache testing later because cache is a little more complicated than just the single response. cache.On("Get", BFCacheKey).Return(nil, false) // cache testing later because cache is a little more complicated than just the single response.
// cache.On("set", BFCacheKey, tc.JSONResponse, tc.CacheTimeout).Return() // cache.On("Set", BFCacheKey, tc.JSONResponse, tc.CacheTimeout).Return()
env.On("HTTPRequest", BFBatchURL).Return([]byte(tc.BatchJSONResponse), tc.Error) env.On("HTTPRequest", BFBatchURL).Return([]byte(tc.BatchJSONResponse), tc.Error)
env.On("HTTPRequest", BFBatchReadingsURL).Return([]byte(tc.BatchReadingsJSONResponse), tc.Error) env.On("HTTPRequest", BFBatchReadingsURL).Return([]byte(tc.BatchReadingsJSONResponse), tc.Error)
env.On("cache").Return(cache) env.On("Cache").Return(cache)
env.onTemplate()
if tc.Template != "" {
props[SegmentTemplate] = tc.Template
}
ns := &brewfather{ ns := &brewfather{
props: props, props: props,
@ -167,6 +163,9 @@ func TestBrewfatherSegment(t *testing.T) {
continue continue
} }
assert.Equal(t, tc.ExpectedString, ns.string(), tc.Case) if tc.Template == "" {
tc.Template = ns.template()
}
assert.Equal(t, tc.ExpectedString, renderTemplate(env, tc.Template, ns), tc.Case)
} }
} }

View file

@ -16,16 +16,20 @@ const (
Command Property = "command" Command Property = "command"
) )
func (c *command) template() string {
return "{{ .Output }}"
}
func (c *command) enabled() bool { func (c *command) enabled() bool {
shell := c.props.getString(ExecutableShell, "bash") shell := c.props.getString(ExecutableShell, "bash")
if !c.env.hasCommand(shell) { if !c.env.HasCommand(shell) {
return false return false
} }
command := c.props.getString(Command, "echo no command specified") command := c.props.getString(Command, "echo no command specified")
if strings.Contains(command, "||") { if strings.Contains(command, "||") {
commands := strings.Split(command, "||") commands := strings.Split(command, "||")
for _, cmd := range commands { for _, cmd := range commands {
output := c.env.runShellCommand(shell, strings.TrimSpace(cmd)) output := c.env.RunShellCommand(shell, strings.TrimSpace(cmd))
if output != "" { if output != "" {
c.Output = output c.Output = output
return true return true
@ -36,29 +40,15 @@ func (c *command) enabled() bool {
var output string var output string
commands := strings.Split(command, "&&") commands := strings.Split(command, "&&")
for _, cmd := range commands { for _, cmd := range commands {
output += c.env.runShellCommand(shell, strings.TrimSpace(cmd)) output += c.env.RunShellCommand(shell, strings.TrimSpace(cmd))
} }
c.Output = output c.Output = output
return c.Output != "" return c.Output != ""
} }
c.Output = c.env.runShellCommand(shell, strings.TrimSpace(command)) c.Output = c.env.RunShellCommand(shell, strings.TrimSpace(command))
return c.Output != "" return c.Output != ""
} }
func (c *command) string() string {
segmentTemplate := c.props.getString(SegmentTemplate, "{{.Output}}")
template := &textTemplate{
Template: segmentTemplate,
Context: c,
Env: c.env,
}
text, err := template.render()
if err != nil {
return err.Error()
}
return text
}
func (c *command) init(props Properties, env Environment) { func (c *command) init(props Properties, env Environment) {
c.props = props c.props = props
c.env = env c.env = env

View file

@ -8,9 +8,8 @@ import (
func TestExecuteCommand(t *testing.T) { func TestExecuteCommand(t *testing.T) {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("hasCommand", "bash").Return(true) env.On("HasCommand", "bash").Return(true)
env.On("runShellCommand", "bash", "echo hello").Return("hello") env.On("RunShellCommand", "bash", "echo hello").Return("hello")
env.onTemplate()
props := properties{ props := properties{
Command: "echo hello", Command: "echo hello",
} }
@ -20,16 +19,15 @@ func TestExecuteCommand(t *testing.T) {
} }
enabled := c.enabled() enabled := c.enabled()
assert.True(t, enabled) assert.True(t, enabled)
assert.Equal(t, "hello", c.string()) assert.Equal(t, "hello", renderTemplate(env, c.template(), c))
} }
func TestExecuteMultipleCommandsOrFirst(t *testing.T) { func TestExecuteMultipleCommandsOrFirst(t *testing.T) {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("hasCommand", "bash").Return(true) env.On("HasCommand", "bash").Return(true)
env.On("runShellCommand", "bash", "exit 1").Return("") env.On("RunShellCommand", "bash", "exit 1").Return("")
env.On("runShellCommand", "bash", "echo hello").Return("hello") env.On("RunShellCommand", "bash", "echo hello").Return("hello")
env.On("runShellCommand", "bash", "exit 1 || echo hello").Return("hello") env.On("RunShellCommand", "bash", "exit 1 || echo hello").Return("hello")
env.onTemplate()
props := properties{ props := properties{
Command: "exit 1 || echo hello", Command: "exit 1 || echo hello",
} }
@ -39,15 +37,14 @@ func TestExecuteMultipleCommandsOrFirst(t *testing.T) {
} }
enabled := c.enabled() enabled := c.enabled()
assert.True(t, enabled) assert.True(t, enabled)
assert.Equal(t, "hello", c.string()) assert.Equal(t, "hello", renderTemplate(env, c.template(), c))
} }
func TestExecuteMultipleCommandsOrSecond(t *testing.T) { func TestExecuteMultipleCommandsOrSecond(t *testing.T) {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("hasCommand", "bash").Return(true) env.On("HasCommand", "bash").Return(true)
env.On("runShellCommand", "bash", "echo hello").Return("hello") env.On("RunShellCommand", "bash", "echo hello").Return("hello")
env.On("runShellCommand", "bash", "echo world").Return("world") env.On("RunShellCommand", "bash", "echo world").Return("world")
env.onTemplate()
props := properties{ props := properties{
Command: "echo hello || echo world", Command: "echo hello || echo world",
} }
@ -57,15 +54,14 @@ func TestExecuteMultipleCommandsOrSecond(t *testing.T) {
} }
enabled := c.enabled() enabled := c.enabled()
assert.True(t, enabled) assert.True(t, enabled)
assert.Equal(t, "hello", c.string()) assert.Equal(t, "hello", renderTemplate(env, c.template(), c))
} }
func TestExecuteMultipleCommandsAnd(t *testing.T) { func TestExecuteMultipleCommandsAnd(t *testing.T) {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("hasCommand", "bash").Return(true) env.On("HasCommand", "bash").Return(true)
env.On("runShellCommand", "bash", "echo hello").Return("hello") env.On("RunShellCommand", "bash", "echo hello").Return("hello")
env.On("runShellCommand", "bash", "echo world").Return("world") env.On("RunShellCommand", "bash", "echo world").Return("world")
env.onTemplate()
props := properties{ props := properties{
Command: "echo hello && echo world", Command: "echo hello && echo world",
} }
@ -75,14 +71,13 @@ func TestExecuteMultipleCommandsAnd(t *testing.T) {
} }
enabled := c.enabled() enabled := c.enabled()
assert.True(t, enabled) assert.True(t, enabled)
assert.Equal(t, "helloworld", c.string()) assert.Equal(t, "helloworld", renderTemplate(env, c.template(), c))
} }
func TestExecuteSingleCommandEmpty(t *testing.T) { func TestExecuteSingleCommandEmpty(t *testing.T) {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("hasCommand", "bash").Return(true) env.On("HasCommand", "bash").Return(true)
env.On("runShellCommand", "bash", "").Return("") env.On("RunShellCommand", "bash", "").Return("")
env.onTemplate()
props := properties{ props := properties{
Command: "", Command: "",
} }
@ -96,9 +91,8 @@ func TestExecuteSingleCommandEmpty(t *testing.T) {
func TestExecuteSingleCommandNoCommandProperty(t *testing.T) { func TestExecuteSingleCommandNoCommandProperty(t *testing.T) {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("hasCommand", "bash").Return(true) env.On("HasCommand", "bash").Return(true)
env.On("runShellCommand", "bash", "echo no command specified").Return("no command specified") env.On("RunShellCommand", "bash", "echo no command specified").Return("no command specified")
env.onTemplate()
var props properties var props properties
c := &command{ c := &command{
props: props, props: props,
@ -111,9 +105,8 @@ func TestExecuteSingleCommandNoCommandProperty(t *testing.T) {
func TestExecuteMultipleCommandsAndDisabled(t *testing.T) { func TestExecuteMultipleCommandsAndDisabled(t *testing.T) {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("hasCommand", "bash").Return(true) env.On("HasCommand", "bash").Return(true)
env.On("runShellCommand", "bash", "echo").Return("") env.On("RunShellCommand", "bash", "echo").Return("")
env.onTemplate()
props := properties{ props := properties{
Command: "echo && echo", Command: "echo && echo",
} }
@ -127,10 +120,9 @@ func TestExecuteMultipleCommandsAndDisabled(t *testing.T) {
func TestExecuteMultipleCommandsOrDisabled(t *testing.T) { func TestExecuteMultipleCommandsOrDisabled(t *testing.T) {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("hasCommand", "bash").Return(true) env.On("HasCommand", "bash").Return(true)
env.On("runShellCommand", "bash", "echo").Return("") env.On("RunShellCommand", "bash", "echo").Return("")
env.On("runShellCommand", "bash", "echo|| echo").Return("") env.On("RunShellCommand", "bash", "echo|| echo").Return("")
env.onTemplate()
props := properties{ props := properties{
Command: "echo|| echo", Command: "echo|| echo",
} }

View file

@ -4,9 +4,8 @@ type crystal struct {
language language
} }
func (c *crystal) string() string { func (c *crystal) template() string {
segmentTemplate := c.language.props.getString(SegmentTemplate, "{{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }}") return languageTemplate
return c.language.string(segmentTemplate, c)
} }
func (c *crystal) init(props Properties, env Environment) { func (c *crystal) init(props Properties, env Environment) {

View file

@ -26,6 +26,6 @@ func TestCrystal(t *testing.T) {
c := &crystal{} c := &crystal{}
c.init(props, env) c.init(props, env)
assert.True(t, c.enabled(), fmt.Sprintf("Failed in case: %s", tc.Case)) assert.True(t, c.enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
assert.Equal(t, tc.ExpectedString, c.string(), fmt.Sprintf("Failed in case: %s", tc.Case)) assert.Equal(t, tc.ExpectedString, renderTemplate(env, c.template(), c), fmt.Sprintf("Failed in case: %s", tc.Case))
} }
} }

View file

@ -4,9 +4,8 @@ type dart struct {
language language
} }
func (d *dart) string() string { func (d *dart) template() string {
segmentTemplate := d.language.props.getString(SegmentTemplate, "{{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }}") return languageTemplate
return d.language.string(segmentTemplate, d)
} }
func (d *dart) init(props Properties, env Environment) { func (d *dart) init(props Properties, env Environment) {

View file

@ -26,6 +26,6 @@ func TestDart(t *testing.T) {
d := &dart{} d := &dart{}
d.init(props, env) d.init(props, env)
assert.True(t, d.enabled(), fmt.Sprintf("Failed in case: %s", tc.Case)) assert.True(t, d.enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
assert.Equal(t, tc.ExpectedString, d.string(), fmt.Sprintf("Failed in case: %s", tc.Case)) assert.Equal(t, tc.ExpectedString, renderTemplate(env, d.template(), d), fmt.Sprintf("Failed in case: %s", tc.Case))
} }
} }

View file

@ -6,9 +6,8 @@ type dotnet struct {
Unsupported bool Unsupported bool
} }
func (d *dotnet) string() string { func (d *dotnet) template() string {
segmentTemplate := d.language.props.getString(SegmentTemplate, "{{ if .Unsupported }}\uf071{{ else }}{{ .Full }}{{ end }}") return "{{ if .Unsupported }}\uf071{{ else }}{{ .Full }}{{ end }}"
return d.language.string(segmentTemplate, d)
} }
func (d *dotnet) init(props Properties, env Environment) { func (d *dotnet) init(props Properties, env Environment) {

View file

@ -6,76 +6,44 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
type dotnetArgs struct { func TestDotnetSegment(t *testing.T) {
enabled bool cases := []struct {
version string Case string
exitCode int Expected string
unsupportedIcon string ExitCode int
displayVersion bool HasCommand bool
} Version string
FetchVersion bool
func bootStrapDotnetTest(args *dotnetArgs) *dotnet { }{
env := new(MockedEnvironment) {Case: "Unsupported version", Expected: "\uf071", HasCommand: true, FetchVersion: true, ExitCode: dotnetExitCode, Version: "3.1.402"},
env.On("hasCommand", "dotnet").Return(args.enabled) {Case: "Regular version", Expected: "3.1.402", HasCommand: true, FetchVersion: true, Version: "3.1.402"},
if args.exitCode != 0 { {Case: "Regular version", Expected: "", HasCommand: true, FetchVersion: false, Version: "3.1.402"},
err := &commandError{exitCode: args.exitCode} {Case: "Regular version", Expected: "", HasCommand: false, FetchVersion: false, Version: "3.1.402"},
env.On("runCommand", "dotnet", []string{"--version"}).Return("", err)
} else {
env.On("runCommand", "dotnet", []string{"--version"}).Return(args.version, nil)
} }
env.On("hasFiles", "*.cs").Return(true) for _, tc := range cases {
env.On("getPathSeperator").Return("") env := new(MockedEnvironment)
env.On("pwd").Return("/usr/home/project") env.On("HasCommand", "dotnet").Return(tc.HasCommand)
env.On("homeDir").Return("/usr/home") if tc.ExitCode != 0 {
env.onTemplate() err := &commandError{exitCode: tc.ExitCode}
env.On("RunCommand", "dotnet", []string{"--version"}).Return("", err)
} else {
env.On("RunCommand", "dotnet", []string{"--version"}).Return(tc.Version, nil)
}
env.On("HasFiles", "*.cs").Return(true)
env.On("PathSeperator").Return("")
env.On("Pwd").Return("/usr/home/project")
env.On("Home").Return("/usr/home")
env.On("TemplateCache").Return(&TemplateCache{
Env: make(map[string]string),
})
props := properties{ props := properties{
FetchVersion: args.displayVersion, FetchVersion: tc.FetchVersion,
} }
dotnet := &dotnet{} dotnet := &dotnet{}
dotnet.init(props, env) dotnet.init(props, env)
return dotnet
}
func TestEnabledDotnetNotFound(t *testing.T) {
args := &dotnetArgs{
enabled: false,
}
dotnet := bootStrapDotnetTest(args)
assert.True(t, dotnet.enabled()) assert.True(t, dotnet.enabled())
} assert.Equal(t, tc.Expected, renderTemplate(env, dotnet.template(), dotnet), tc.Case)
func TestDotnetVersionNotDisplayed(t *testing.T) {
args := &dotnetArgs{
enabled: true,
displayVersion: false,
version: "3.1.402",
} }
dotnet := bootStrapDotnetTest(args)
assert.True(t, dotnet.enabled())
assert.Equal(t, "", dotnet.string())
}
func TestDotnetVersionDisplayed(t *testing.T) {
expected := "3.1.402"
args := &dotnetArgs{
enabled: true,
displayVersion: true,
version: expected,
}
dotnet := bootStrapDotnetTest(args)
assert.True(t, dotnet.enabled())
assert.Equal(t, expected, dotnet.string())
}
func TestDotnetVersionUnsupported(t *testing.T) {
args := &dotnetArgs{
enabled: true,
displayVersion: true,
exitCode: dotnetExitCode,
unsupportedIcon: expected,
}
dotnet := bootStrapDotnetTest(args)
assert.True(t, dotnet.enabled())
assert.Equal(t, "\uf071", dotnet.string())
} }

View file

@ -48,7 +48,7 @@ const (
func (t *executiontime) enabled() bool { func (t *executiontime) enabled() bool {
alwaysEnabled := t.props.getBool(AlwaysEnabled, false) alwaysEnabled := t.props.getBool(AlwaysEnabled, false)
executionTimeMs := t.env.executionTime() executionTimeMs := t.env.ExecutionTime()
thresholdMs := t.props.getFloat64(ThresholdProperty, float64(500)) thresholdMs := t.props.getFloat64(ThresholdProperty, float64(500))
if !alwaysEnabled && executionTimeMs < thresholdMs { if !alwaysEnabled && executionTimeMs < thresholdMs {
return false return false
@ -59,18 +59,8 @@ func (t *executiontime) enabled() bool {
return t.FormattedMs != "" return t.FormattedMs != ""
} }
func (t *executiontime) string() string { func (t *executiontime) template() string {
segmentTemplate := t.props.getString(SegmentTemplate, "{{.FormattedMs}}") return "{{ .FormattedMs }}"
template := &textTemplate{
Template: segmentTemplate,
Context: t,
Env: t.env,
}
text, err := template.render()
if err != nil {
return err.Error()
}
return text
} }
func (t *executiontime) init(props Properties, env Environment) { func (t *executiontime) init(props Properties, env Environment) {

View file

@ -9,7 +9,7 @@ import (
func TestExecutionTimeWriterDefaultThresholdEnabled(t *testing.T) { func TestExecutionTimeWriterDefaultThresholdEnabled(t *testing.T) {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("executionTime").Return(1337) env.On("ExecutionTime").Return(1337)
executionTime := &executiontime{ executionTime := &executiontime{
env: env, env: env,
props: properties{}, props: properties{},
@ -19,7 +19,7 @@ func TestExecutionTimeWriterDefaultThresholdEnabled(t *testing.T) {
func TestExecutionTimeWriterDefaultThresholdDisabled(t *testing.T) { func TestExecutionTimeWriterDefaultThresholdDisabled(t *testing.T) {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("executionTime").Return(1) env.On("ExecutionTime").Return(1)
executionTime := &executiontime{ executionTime := &executiontime{
env: env, env: env,
props: properties{}, props: properties{},
@ -29,7 +29,7 @@ func TestExecutionTimeWriterDefaultThresholdDisabled(t *testing.T) {
func TestExecutionTimeWriterCustomThresholdEnabled(t *testing.T) { func TestExecutionTimeWriterCustomThresholdEnabled(t *testing.T) {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("executionTime").Return(99) env.On("ExecutionTime").Return(99)
props := properties{ props := properties{
ThresholdProperty: float64(10), ThresholdProperty: float64(10),
} }
@ -42,7 +42,7 @@ func TestExecutionTimeWriterCustomThresholdEnabled(t *testing.T) {
func TestExecutionTimeWriterCustomThresholdDisabled(t *testing.T) { func TestExecutionTimeWriterCustomThresholdDisabled(t *testing.T) {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("executionTime").Return(99) env.On("ExecutionTime").Return(99)
props := properties{ props := properties{
ThresholdProperty: float64(100), ThresholdProperty: float64(100),
} }
@ -57,7 +57,7 @@ func TestExecutionTimeWriterDuration(t *testing.T) {
input := 1337 input := 1337
expected := "1.337s" expected := "1.337s"
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("executionTime").Return(input) env.On("ExecutionTime").Return(input)
executionTime := &executiontime{ executionTime := &executiontime{
env: env, env: env,
props: properties{}, props: properties{},
@ -70,7 +70,7 @@ func TestExecutionTimeWriterDuration2(t *testing.T) {
input := 13371337 input := 13371337
expected := "3h 42m 51.337s" expected := "3h 42m 51.337s"
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("executionTime").Return(input) env.On("ExecutionTime").Return(input)
executionTime := &executiontime{ executionTime := &executiontime{
env: env, env: env,
props: properties{}, props: properties{},

View file

@ -9,26 +9,16 @@ type exit struct {
Text string Text string
} }
func (e *exit) template() string {
return "{{ .Text }}"
}
func (e *exit) enabled() bool { func (e *exit) enabled() bool {
e.Text = e.getMeaningFromExitCode(e.env.lastErrorCode()) e.Text = e.getMeaningFromExitCode(e.env.ErrorCode())
if e.props.getBool(AlwaysEnabled, false) { if e.props.getBool(AlwaysEnabled, false) {
return true return true
} }
return e.env.lastErrorCode() != 0 return e.env.ErrorCode() != 0
}
func (e *exit) string() string {
segmentTemplate := e.props.getString(SegmentTemplate, "{{ .Text }}")
template := &textTemplate{
Template: segmentTemplate,
Context: e,
Env: e.env,
}
text, err := template.render()
if err != nil {
return err.Error()
}
return text
} }
func (e *exit) init(props Properties, env Environment) { func (e *exit) init(props Properties, env Environment) {

View file

@ -18,7 +18,7 @@ func TestExitWriterEnabled(t *testing.T) {
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("lastErrorCode").Return(tc.ExitCode) env.On("ErrorCode").Return(tc.ExitCode)
e := &exit{ e := &exit{
env: env, env: env,
props: properties{}, props: properties{},
@ -75,18 +75,14 @@ func TestExitWriterTemplateString(t *testing.T) {
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("lastErrorCode").Return(tc.ExitCode) env.On("ErrorCode").Return(tc.ExitCode)
env.On("templateCache").Return(&templateCache{ env.On("TemplateCache").Return(&TemplateCache{
Code: tc.ExitCode, Code: tc.ExitCode,
}) })
env.onTemplate()
props := properties{
SegmentTemplate: tc.Template,
}
e := &exit{ e := &exit{
env: env, env: env,
props: props, props: properties{},
} }
assert.Equal(t, tc.Expected, e.string(), tc.Case) assert.Equal(t, tc.Expected, renderTemplate(env, tc.Template, e), tc.Case)
} }
} }

View file

@ -104,6 +104,10 @@ const (
BRANCHPREFIX = "ref: refs/heads/" BRANCHPREFIX = "ref: refs/heads/"
) )
func (g *git) template() string {
return "{{ .HEAD }} {{ .BranchStatus }}{{ if .Working.Changed }} \uF044 {{ .Working.String }}{{ end }}{{ if .Staging.Changed }} \uF046 {{ .Staging.String }}{{ end }}" // nolint: lll
}
func (g *git) enabled() bool { func (g *git) enabled() bool {
if !g.shouldDisplay() { if !g.shouldDisplay() {
return false return false
@ -134,28 +138,28 @@ func (g *git) shouldDisplay() bool {
// when in wsl/wsl2 and in a windows shared folder // when in wsl/wsl2 and in a windows shared folder
// we must use git.exe and convert paths accordingly // we must use git.exe and convert paths accordingly
// for worktrees, stashes, and path to work // for worktrees, stashes, and path to work
g.IsWslSharedPath = g.env.inWSLSharedDrive() g.IsWslSharedPath = g.env.InWSLSharedDrive()
if !g.env.hasCommand(g.getGitCommand()) { if !g.env.HasCommand(g.getGitCommand()) {
return false return false
} }
gitdir, err := g.env.hasParentFilePath(".git") gitdir, err := g.env.HasParentFilePath(".git")
if err != nil { if err != nil {
return false return false
} }
if g.shouldIgnoreRootRepository(gitdir.parentFolder) { if g.shouldIgnoreRootRepository(gitdir.ParentFolder) {
return false return false
} }
if gitdir.isDir { if gitdir.IsDir {
g.gitWorkingFolder = gitdir.path g.gitWorkingFolder = gitdir.Path
g.gitRootFolder = gitdir.path g.gitRootFolder = gitdir.Path
// convert the worktree file path to a windows one when in wsl 2 shared folder // convert the worktree file path to a windows one when in wsl 2 shared folder
g.gitRealFolder = strings.TrimSuffix(g.convertToWindowsPath(gitdir.path), ".git") g.gitRealFolder = strings.TrimSuffix(g.convertToWindowsPath(gitdir.Path), ".git")
return true return true
} }
// handle worktree // handle worktree
g.gitRootFolder = gitdir.path g.gitRootFolder = gitdir.Path
dirPointer := strings.Trim(g.env.getFileContent(gitdir.path), " \r\n") dirPointer := strings.Trim(g.env.FileContent(gitdir.Path), " \r\n")
matches := findNamedRegexMatch(`^gitdir: (?P<dir>.*)$`, dirPointer) matches := findNamedRegexMatch(`^gitdir: (?P<dir>.*)$`, dirPointer)
if matches != nil && matches["dir"] != "" { if matches != nil && matches["dir"] != "" {
// if we open a worktree file in a shared wsl2 folder, we have to convert it back // if we open a worktree file in a shared wsl2 folder, we have to convert it back
@ -168,7 +172,7 @@ func (g *git) shouldDisplay() bool {
ind := strings.LastIndex(g.gitWorkingFolder, "/.git/worktrees") ind := strings.LastIndex(g.gitWorkingFolder, "/.git/worktrees")
if ind > -1 { if ind > -1 {
g.gitRootFolder = g.gitWorkingFolder[:ind+5] g.gitRootFolder = g.gitWorkingFolder[:ind+5]
g.gitRealFolder = strings.TrimSuffix(g.env.getFileContent(g.gitWorkingFolder+"/gitdir"), ".git\n") g.gitRealFolder = strings.TrimSuffix(g.env.FileContent(g.gitWorkingFolder+"/gitdir"), ".git\n")
g.IsWorkTree = true g.IsWorkTree = true
return true return true
} }
@ -176,7 +180,7 @@ func (g *git) shouldDisplay() bool {
// we need the parent folder to detect where the real .git folder is // we need the parent folder to detect where the real .git folder is
ind = strings.LastIndex(g.gitWorkingFolder, "/.git/modules") ind = strings.LastIndex(g.gitWorkingFolder, "/.git/modules")
if ind > -1 { if ind > -1 {
g.gitRootFolder = gitdir.parentFolder + "/" + g.gitWorkingFolder g.gitRootFolder = gitdir.ParentFolder + "/" + g.gitWorkingFolder
g.gitRealFolder = g.gitRootFolder g.gitRealFolder = g.gitRootFolder
g.gitWorkingFolder = g.gitRootFolder g.gitWorkingFolder = g.gitRootFolder
return true return true
@ -187,24 +191,6 @@ func (g *git) shouldDisplay() bool {
return false return false
} }
func (g *git) string() string {
segmentTemplate := g.props.getString(SegmentTemplate, "{{ .HEAD }} {{ .BranchStatus }}{{ if .Working.Changed }} \uF044 {{ .Working.String }}{{ end }}{{ if .Staging.Changed }} \uF046 {{ .Staging.String }}{{ end }}") // nolint: lll
return g.templateString(segmentTemplate)
}
func (g *git) templateString(segmentTemplate string) string {
template := &textTemplate{
Template: segmentTemplate,
Context: g,
Env: g.env,
}
text, err := template.render()
if err != nil {
return err.Error()
}
return text
}
func (g *git) setBranchStatus() { func (g *git) setBranchStatus() {
getBranchStatus := func() string { getBranchStatus := func() string {
if g.Ahead > 0 && g.Behind > 0 { if g.Ahead > 0 && g.Behind > 0 {
@ -301,7 +287,7 @@ func (g *git) getGitCommand() string {
return g.gitCommand return g.gitCommand
} }
g.gitCommand = "git" g.gitCommand = "git"
if g.env.getRuntimeGOOS() == windowsPlatform || g.IsWslSharedPath { if g.env.GOOS() == windowsPlatform || g.IsWslSharedPath {
g.gitCommand = "git.exe" g.gitCommand = "git.exe"
} }
return g.gitCommand return g.gitCommand
@ -309,7 +295,7 @@ func (g *git) getGitCommand() string {
func (g *git) getGitCommandOutput(args ...string) string { func (g *git) getGitCommandOutput(args ...string) string {
args = append([]string{"-C", g.gitRealFolder, "--no-optional-locks", "-c", "core.quotepath=false", "-c", "color.status=false"}, args...) args = append([]string{"-C", g.gitRealFolder, "--no-optional-locks", "-c", "core.quotepath=false", "-c", "color.status=false"}, args...)
val, err := g.env.runCommand(g.getGitCommand(), args...) val, err := g.env.RunCommand(g.getGitCommand(), args...)
if err != nil { if err != nil {
return "" return ""
} }
@ -334,7 +320,7 @@ func (g *git) setGitHEADContext() {
getPrettyNameOrigin := func(file string) string { getPrettyNameOrigin := func(file string) string {
var origin string var origin string
head := g.getFileContents(g.gitWorkingFolder, file) head := g.FileContents(g.gitWorkingFolder, file)
if head == "detached HEAD" { if head == "detached HEAD" {
origin = formatDetached() origin = formatDetached()
} else { } else {
@ -344,20 +330,20 @@ func (g *git) setGitHEADContext() {
return origin return origin
} }
if g.env.hasFolder(g.gitWorkingFolder + "/rebase-merge") { if g.env.HasFolder(g.gitWorkingFolder + "/rebase-merge") {
origin := getPrettyNameOrigin("rebase-merge/head-name") origin := getPrettyNameOrigin("rebase-merge/head-name")
onto := g.getGitRefFileSymbolicName("rebase-merge/onto") onto := g.getGitRefFileSymbolicName("rebase-merge/onto")
onto = g.formatHEAD(onto) onto = g.formatHEAD(onto)
step := g.getFileContents(g.gitWorkingFolder, "rebase-merge/msgnum") step := g.FileContents(g.gitWorkingFolder, "rebase-merge/msgnum")
total := g.getFileContents(g.gitWorkingFolder, "rebase-merge/end") total := g.FileContents(g.gitWorkingFolder, "rebase-merge/end")
icon := g.props.getString(RebaseIcon, "\uE728 ") icon := g.props.getString(RebaseIcon, "\uE728 ")
g.HEAD = fmt.Sprintf("%s%s onto %s%s (%s/%s) at %s", icon, origin, branchIcon, onto, step, total, g.HEAD) g.HEAD = fmt.Sprintf("%s%s onto %s%s (%s/%s) at %s", icon, origin, branchIcon, onto, step, total, g.HEAD)
return return
} }
if g.env.hasFolder(g.gitWorkingFolder + "/rebase-apply") { if g.env.HasFolder(g.gitWorkingFolder + "/rebase-apply") {
origin := getPrettyNameOrigin("rebase-apply/head-name") origin := getPrettyNameOrigin("rebase-apply/head-name")
step := g.getFileContents(g.gitWorkingFolder, "rebase-apply/next") step := g.FileContents(g.gitWorkingFolder, "rebase-apply/next")
total := g.getFileContents(g.gitWorkingFolder, "rebase-apply/last") total := g.FileContents(g.gitWorkingFolder, "rebase-apply/last")
icon := g.props.getString(RebaseIcon, "\uE728 ") icon := g.props.getString(RebaseIcon, "\uE728 ")
g.HEAD = fmt.Sprintf("%s%s (%s/%s) at %s", icon, origin, step, total, g.HEAD) g.HEAD = fmt.Sprintf("%s%s (%s/%s) at %s", icon, origin, step, total, g.HEAD)
return return
@ -366,7 +352,7 @@ func (g *git) setGitHEADContext() {
commitIcon := g.props.getString(CommitIcon, "\uF417") commitIcon := g.props.getString(CommitIcon, "\uF417")
if g.hasGitFile("MERGE_MSG") { if g.hasGitFile("MERGE_MSG") {
icon := g.props.getString(MergeIcon, "\uE727 ") icon := g.props.getString(MergeIcon, "\uE727 ")
mergeContext := g.getFileContents(g.gitWorkingFolder, "MERGE_MSG") mergeContext := g.FileContents(g.gitWorkingFolder, "MERGE_MSG")
matches := findNamedRegexMatch(`Merge (remote-tracking )?(?P<type>branch|commit|tag) '(?P<theirs>.*)'`, mergeContext) matches := findNamedRegexMatch(`Merge (remote-tracking )?(?P<type>branch|commit|tag) '(?P<theirs>.*)'`, mergeContext)
// head := g.getGitRefFileSymbolicName("ORIG_HEAD") // head := g.getGitRefFileSymbolicName("ORIG_HEAD")
if matches != nil && matches["theirs"] != "" { if matches != nil && matches["theirs"] != "" {
@ -392,19 +378,19 @@ func (g *git) setGitHEADContext() {
// reverts then CHERRY_PICK_HEAD/REVERT_HEAD will not exist so we have to read // reverts then CHERRY_PICK_HEAD/REVERT_HEAD will not exist so we have to read
// the todo file. // the todo file.
if g.hasGitFile("CHERRY_PICK_HEAD") { if g.hasGitFile("CHERRY_PICK_HEAD") {
sha := g.getFileContents(g.gitWorkingFolder, "CHERRY_PICK_HEAD") sha := g.FileContents(g.gitWorkingFolder, "CHERRY_PICK_HEAD")
cherry := g.props.getString(CherryPickIcon, "\uE29B ") cherry := g.props.getString(CherryPickIcon, "\uE29B ")
g.HEAD = fmt.Sprintf("%s%s%s onto %s", cherry, commitIcon, g.formatSHA(sha), formatDetached()) g.HEAD = fmt.Sprintf("%s%s%s onto %s", cherry, commitIcon, g.formatSHA(sha), formatDetached())
return return
} }
if g.hasGitFile("REVERT_HEAD") { if g.hasGitFile("REVERT_HEAD") {
sha := g.getFileContents(g.gitWorkingFolder, "REVERT_HEAD") sha := g.FileContents(g.gitWorkingFolder, "REVERT_HEAD")
revert := g.props.getString(RevertIcon, "\uF0E2 ") revert := g.props.getString(RevertIcon, "\uF0E2 ")
g.HEAD = fmt.Sprintf("%s%s%s onto %s", revert, commitIcon, g.formatSHA(sha), formatDetached()) g.HEAD = fmt.Sprintf("%s%s%s onto %s", revert, commitIcon, g.formatSHA(sha), formatDetached())
return return
} }
if g.hasGitFile("sequencer/todo") { if g.hasGitFile("sequencer/todo") {
todo := g.getFileContents(g.gitWorkingFolder, "sequencer/todo") todo := g.FileContents(g.gitWorkingFolder, "sequencer/todo")
matches := findNamedRegexMatch(`^(?P<action>p|pick|revert)\s+(?P<sha>\S+)`, todo) matches := findNamedRegexMatch(`^(?P<action>p|pick|revert)\s+(?P<sha>\S+)`, todo)
if matches != nil && matches["sha"] != "" { if matches != nil && matches["sha"] != "" {
action := matches["action"] action := matches["action"]
@ -441,18 +427,18 @@ func (g *git) formatSHA(sha string) string {
} }
func (g *git) hasGitFile(file string) bool { func (g *git) hasGitFile(file string) bool {
return g.env.hasFilesInDir(g.gitWorkingFolder, file) return g.env.HasFilesInDir(g.gitWorkingFolder, file)
} }
func (g *git) getGitRefFileSymbolicName(refFile string) string { func (g *git) getGitRefFileSymbolicName(refFile string) string {
ref := g.getFileContents(g.gitWorkingFolder, refFile) ref := g.FileContents(g.gitWorkingFolder, refFile)
return g.getGitCommandOutput("name-rev", "--name-only", "--exclude=tags/*", ref) return g.getGitCommandOutput("name-rev", "--name-only", "--exclude=tags/*", ref)
} }
func (g *git) setPrettyHEADName() { func (g *git) setPrettyHEADName() {
// we didn't fetch status, fallback to parsing the HEAD file // we didn't fetch status, fallback to parsing the HEAD file
if len(g.Hash) == 0 { if len(g.Hash) == 0 {
HEADRef := g.getFileContents(g.gitWorkingFolder, "HEAD") HEADRef := g.FileContents(g.gitWorkingFolder, "HEAD")
if strings.HasPrefix(HEADRef, BRANCHPREFIX) { if strings.HasPrefix(HEADRef, BRANCHPREFIX) {
branchName := strings.TrimPrefix(HEADRef, BRANCHPREFIX) branchName := strings.TrimPrefix(HEADRef, BRANCHPREFIX)
g.HEAD = fmt.Sprintf("%s%s", g.props.getString(BranchIcon, "\uE0A0"), g.formatHEAD(branchName)) g.HEAD = fmt.Sprintf("%s%s", g.props.getString(BranchIcon, "\uE0A0"), g.formatHEAD(branchName))
@ -478,7 +464,7 @@ func (g *git) setPrettyHEADName() {
} }
func (g *git) getStashContext() int { func (g *git) getStashContext() int {
stashContent := g.getFileContents(g.gitRootFolder, "logs/refs/stash") stashContent := g.FileContents(g.gitRootFolder, "logs/refs/stash")
if stashContent == "" { if stashContent == "" {
return 0 return 0
} }
@ -487,10 +473,10 @@ func (g *git) getStashContext() int {
} }
func (g *git) getWorktreeContext() int { func (g *git) getWorktreeContext() int {
if !g.env.hasFolder(g.gitRootFolder + "/worktrees") { if !g.env.HasFolder(g.gitRootFolder + "/worktrees") {
return 0 return 0
} }
worktreeFolders := g.env.getFoldersList(g.gitRootFolder + "/worktrees") worktreeFolders := g.env.FolderList(g.gitRootFolder + "/worktrees")
return len(worktreeFolders) return len(worktreeFolders)
} }
@ -522,12 +508,12 @@ func (g *git) convertToWindowsPath(path string) string {
if !g.IsWslSharedPath { if !g.IsWslSharedPath {
return path return path
} }
return g.env.convertToWindowsPath(path) return g.env.ConvertToWindowsPath(path)
} }
func (g *git) convertToLinuxPath(path string) string { func (g *git) convertToLinuxPath(path string) string {
if !g.IsWslSharedPath { if !g.IsWslSharedPath {
return path return path
} }
return g.env.convertToLinuxPath(path) return g.env.ConvertToLinuxPath(path)
} }

View file

@ -14,10 +14,10 @@ const (
func TestEnabledGitNotFound(t *testing.T) { func TestEnabledGitNotFound(t *testing.T) {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("inWSLSharedDrive").Return(false) env.On("InWSLSharedDrive").Return(false)
env.On("hasCommand", "git").Return(false) env.On("HasCommand", "git").Return(false)
env.On("getRuntimeGOOS").Return("") env.On("GOOS").Return("")
env.On("isWsl").Return(false) env.On("IsWsl").Return(false)
g := &git{ g := &git{
scm: scm{ scm: scm{
env: env, env: env,
@ -28,19 +28,19 @@ func TestEnabledGitNotFound(t *testing.T) {
} }
func TestEnabledInWorkingDirectory(t *testing.T) { func TestEnabledInWorkingDirectory(t *testing.T) {
fileInfo := &fileInfo{ fileInfo := &FileInfo{
path: "/dir/hello", Path: "/dir/hello",
parentFolder: "/dir", ParentFolder: "/dir",
isDir: true, IsDir: true,
} }
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("inWSLSharedDrive").Return(false) env.On("InWSLSharedDrive").Return(false)
env.On("hasCommand", "git").Return(true) env.On("HasCommand", "git").Return(true)
env.On("getRuntimeGOOS").Return("") env.On("GOOS").Return("")
env.On("getFileContent", "/dir/hello/HEAD").Return("") env.On("FileContent", "/dir/hello/HEAD").Return("")
env.mockGitCommand(fileInfo.path, "", "describe", "--tags", "--exact-match") env.mockGitCommand(fileInfo.Path, "", "describe", "--tags", "--exact-match")
env.On("isWsl").Return(false) env.On("IsWsl").Return(false)
env.On("hasParentFilePath", ".git").Return(fileInfo, nil) env.On("HasParentFilePath", ".git").Return(fileInfo, nil)
g := &git{ g := &git{
scm: scm{ scm: scm{
env: env, env: env,
@ -48,25 +48,25 @@ func TestEnabledInWorkingDirectory(t *testing.T) {
}, },
} }
assert.True(t, g.enabled()) assert.True(t, g.enabled())
assert.Equal(t, fileInfo.path, g.gitWorkingFolder) assert.Equal(t, fileInfo.Path, g.gitWorkingFolder)
} }
func TestEnabledInWorkingTree(t *testing.T) { func TestEnabledInWorkingTree(t *testing.T) {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("inWSLSharedDrive").Return(false) env.On("InWSLSharedDrive").Return(false)
env.On("hasCommand", "git").Return(true) env.On("HasCommand", "git").Return(true)
env.On("getRuntimeGOOS").Return("") env.On("GOOS").Return("")
env.On("isWsl").Return(false) env.On("IsWsl").Return(false)
fileInfo := &fileInfo{ fileInfo := &FileInfo{
path: "/dev/folder_worktree/.git", Path: "/dev/folder_worktree/.git",
parentFolder: "/dev/folder_worktree", ParentFolder: "/dev/folder_worktree",
isDir: false, IsDir: false,
} }
env.On("getFileContent", "/dev/real_folder/.git/worktrees/folder_worktree/HEAD").Return("") env.On("FileContent", "/dev/real_folder/.git/worktrees/folder_worktree/HEAD").Return("")
env.mockGitCommand(fileInfo.parentFolder, "", "describe", "--tags", "--exact-match") env.mockGitCommand(fileInfo.ParentFolder, "", "describe", "--tags", "--exact-match")
env.On("hasParentFilePath", ".git").Return(fileInfo, nil) env.On("HasParentFilePath", ".git").Return(fileInfo, nil)
env.On("getFileContent", "/dev/folder_worktree/.git").Return("gitdir: /dev/real_folder/.git/worktrees/folder_worktree") env.On("FileContent", "/dev/folder_worktree/.git").Return("gitdir: /dev/real_folder/.git/worktrees/folder_worktree")
env.On("getFileContent", "/dev/real_folder/.git/worktrees/folder_worktree/gitdir").Return("/dev/folder_worktree.git\n") env.On("FileContent", "/dev/real_folder/.git/worktrees/folder_worktree/gitdir").Return("/dev/folder_worktree.git\n")
g := &git{ g := &git{
scm: scm{ scm: scm{
env: env, env: env,
@ -80,20 +80,20 @@ func TestEnabledInWorkingTree(t *testing.T) {
func TestEnabledInSubmodule(t *testing.T) { func TestEnabledInSubmodule(t *testing.T) {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("inWSLSharedDrive").Return(false) env.On("InWSLSharedDrive").Return(false)
env.On("hasCommand", "git").Return(true) env.On("HasCommand", "git").Return(true)
env.On("getRuntimeGOOS").Return("") env.On("GOOS").Return("")
env.On("isWsl").Return(false) env.On("IsWsl").Return(false)
fileInfo := &fileInfo{ fileInfo := &FileInfo{
path: "/dev/parent/test-submodule/.git", Path: "/dev/parent/test-submodule/.git",
parentFolder: "/dev/parent/test-submodule", ParentFolder: "/dev/parent/test-submodule",
isDir: false, IsDir: false,
} }
env.On("getFileContent", "/dev/parent/test-submodule/../.git/modules/test-submodule/HEAD").Return("") env.On("FileContent", "/dev/parent/test-submodule/../.git/modules/test-submodule/HEAD").Return("")
env.mockGitCommand("/dev/parent/test-submodule/../.git/modules/test-submodule", "", "describe", "--tags", "--exact-match") env.mockGitCommand("/dev/parent/test-submodule/../.git/modules/test-submodule", "", "describe", "--tags", "--exact-match")
env.On("hasParentFilePath", ".git").Return(fileInfo, nil) env.On("HasParentFilePath", ".git").Return(fileInfo, nil)
env.On("getFileContent", "/dev/parent/test-submodule/.git").Return("gitdir: ../.git/modules/test-submodule") env.On("FileContent", "/dev/parent/test-submodule/.git").Return("gitdir: ../.git/modules/test-submodule")
env.On("getFileContent", "/dev/parent/.git/modules/test-submodule").Return("/dev/folder_worktree.git\n") env.On("FileContent", "/dev/parent/.git/modules/test-submodule").Return("/dev/folder_worktree.git\n")
g := &git{ g := &git{
scm: scm{ scm: scm{
env: env, env: env,
@ -111,9 +111,9 @@ func TestGetGitOutputForCommand(t *testing.T) {
commandArgs := []string{"symbolic-ref", "--short", "HEAD"} commandArgs := []string{"symbolic-ref", "--short", "HEAD"}
want := "je suis le output" want := "je suis le output"
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("isWsl").Return(false) env.On("IsWsl").Return(false)
env.On("runCommand", "git", append(args, commandArgs...)).Return(want, nil) env.On("RunCommand", "git", append(args, commandArgs...)).Return(want, nil)
env.On("getRuntimeGOOS").Return("unix") env.On("GOOS").Return("unix")
g := &git{ g := &git{
scm: scm{ scm: scm{
env: env, env: env,
@ -126,7 +126,7 @@ func TestGetGitOutputForCommand(t *testing.T) {
func (m *MockedEnvironment) mockGitCommand(dir, returnValue string, args ...string) { func (m *MockedEnvironment) mockGitCommand(dir, returnValue string, args ...string) {
args = append([]string{"-C", dir, "--no-optional-locks", "-c", "core.quotepath=false", "-c", "color.status=false"}, args...) args = append([]string{"-C", dir, "--no-optional-locks", "-c", "core.quotepath=false", "-c", "color.status=false"}, args...)
m.On("runCommand", "git", args).Return(returnValue, nil) m.On("RunCommand", "git", args).Return(returnValue, nil)
} }
func TestSetGitHEADContextClean(t *testing.T) { func TestSetGitHEADContextClean(t *testing.T) {
@ -233,35 +233,35 @@ func TestSetGitHEADContextClean(t *testing.T) {
} }
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("inWSLSharedDrive").Return(false) env.On("InWSLSharedDrive").Return(false)
env.On("getRuntimeGOOS").Return("unix") env.On("GOOS").Return("unix")
env.On("isWsl").Return(false) env.On("IsWsl").Return(false)
env.mockGitCommand("", "", "describe", "--tags", "--exact-match") env.mockGitCommand("", "", "describe", "--tags", "--exact-match")
env.mockGitCommand("", tc.Theirs, "name-rev", "--name-only", "--exclude=tags/*", tc.Theirs) env.mockGitCommand("", tc.Theirs, "name-rev", "--name-only", "--exclude=tags/*", tc.Theirs)
env.mockGitCommand("", tc.Ours, "name-rev", "--name-only", "--exclude=tags/*", tc.Ours) env.mockGitCommand("", tc.Ours, "name-rev", "--name-only", "--exclude=tags/*", tc.Ours)
// rebase merge // rebase merge
env.On("hasFolder", "/rebase-merge").Return(tc.RebaseMerge) env.On("HasFolder", "/rebase-merge").Return(tc.RebaseMerge)
env.On("getFileContent", "/rebase-merge/head-name").Return(tc.Ours) env.On("FileContent", "/rebase-merge/head-name").Return(tc.Ours)
env.On("getFileContent", "/rebase-merge/onto").Return(tc.Theirs) env.On("FileContent", "/rebase-merge/onto").Return(tc.Theirs)
env.On("getFileContent", "/rebase-merge/msgnum").Return(tc.Step) env.On("FileContent", "/rebase-merge/msgnum").Return(tc.Step)
env.On("getFileContent", "/rebase-merge/end").Return(tc.Total) env.On("FileContent", "/rebase-merge/end").Return(tc.Total)
// rebase apply // rebase apply
env.On("hasFolder", "/rebase-apply").Return(tc.RebaseApply) env.On("HasFolder", "/rebase-apply").Return(tc.RebaseApply)
env.On("getFileContent", "/rebase-apply/head-name").Return(tc.Ours) env.On("FileContent", "/rebase-apply/head-name").Return(tc.Ours)
env.On("getFileContent", "/rebase-apply/next").Return(tc.Step) env.On("FileContent", "/rebase-apply/next").Return(tc.Step)
env.On("getFileContent", "/rebase-apply/last").Return(tc.Total) env.On("FileContent", "/rebase-apply/last").Return(tc.Total)
// merge // merge
env.On("hasFilesInDir", "", "MERGE_MSG").Return(tc.Merge) env.On("HasFilesInDir", "", "MERGE_MSG").Return(tc.Merge)
env.On("getFileContent", "/MERGE_MSG").Return(fmt.Sprintf("Merge %s into %s", tc.Theirs, tc.Ours)) env.On("FileContent", "/MERGE_MSG").Return(fmt.Sprintf("Merge %s into %s", tc.Theirs, tc.Ours))
// cherry pick // cherry pick
env.On("hasFilesInDir", "", "CHERRY_PICK_HEAD").Return(tc.CherryPick) env.On("HasFilesInDir", "", "CHERRY_PICK_HEAD").Return(tc.CherryPick)
env.On("getFileContent", "/CHERRY_PICK_HEAD").Return(tc.Theirs) env.On("FileContent", "/CHERRY_PICK_HEAD").Return(tc.Theirs)
// revert // revert
env.On("hasFilesInDir", "", "REVERT_HEAD").Return(tc.Revert) env.On("HasFilesInDir", "", "REVERT_HEAD").Return(tc.Revert)
env.On("getFileContent", "/REVERT_HEAD").Return(tc.Theirs) env.On("FileContent", "/REVERT_HEAD").Return(tc.Theirs)
// sequencer // sequencer
env.On("hasFilesInDir", "", "sequencer/todo").Return(tc.Sequencer) env.On("HasFilesInDir", "", "sequencer/todo").Return(tc.Sequencer)
env.On("getFileContent", "/sequencer/todo").Return(tc.Theirs) env.On("FileContent", "/sequencer/todo").Return(tc.Theirs)
g := &git{ g := &git{
scm: scm{ scm: scm{
@ -301,9 +301,9 @@ func TestSetPrettyHEADName(t *testing.T) {
} }
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("getFileContent", "/HEAD").Return(tc.HEAD) env.On("FileContent", "/HEAD").Return(tc.HEAD)
env.On("getRuntimeGOOS").Return("unix") env.On("GOOS").Return("unix")
env.On("isWsl").Return(false) env.On("IsWsl").Return(false)
env.mockGitCommand("", tc.Tag, "describe", "--tags", "--exact-match") env.mockGitCommand("", tc.Tag, "describe", "--tags", "--exact-match")
g := &git{ g := &git{
scm: scm{ scm: scm{
@ -419,8 +419,8 @@ func TestSetGitStatus(t *testing.T) {
} }
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("getRuntimeGOOS").Return("unix") env.On("GOOS").Return("unix")
env.On("isWsl").Return(false) env.On("IsWsl").Return(false)
env.mockGitCommand("", strings.ReplaceAll(tc.Output, "\t", ""), "status", "-unormal", "--branch", "--porcelain=2") env.mockGitCommand("", strings.ReplaceAll(tc.Output, "\t", ""), "status", "-unormal", "--branch", "--porcelain=2")
g := &git{ g := &git{
scm: scm{ scm: scm{
@ -455,7 +455,7 @@ func TestGetStashContextZeroEntries(t *testing.T) {
} }
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("getFileContent", "/logs/refs/stash").Return(tc.StashContent) env.On("FileContent", "/logs/refs/stash").Return(tc.StashContent)
g := &git{ g := &git{
scm: scm{ scm: scm{
env: env, env: env,
@ -482,10 +482,10 @@ func TestGitUpstream(t *testing.T) {
} }
for _, tc := range cases { for _, tc := range cases {
env := &MockedEnvironment{} env := &MockedEnvironment{}
env.On("isWsl").Return(false) env.On("IsWsl").Return(false)
env.On("runCommand", "git", []string{"-C", "", "--no-optional-locks", "-c", "core.quotepath=false", env.On("RunCommand", "git", []string{"-C", "", "--no-optional-locks", "-c", "core.quotepath=false",
"-c", "color.status=false", "remote", "get-url", "origin"}).Return(tc.Upstream, nil) "-c", "color.status=false", "remote", "get-url", "origin"}).Return(tc.Upstream, nil)
env.On("getRuntimeGOOS").Return("unix") env.On("GOOS").Return("unix")
props := properties{ props := properties{
GithubIcon: "GH", GithubIcon: "GH",
GitlabIcon: "GL", GitlabIcon: "GL",
@ -561,8 +561,8 @@ func TestShouldIgnoreRootRepository(t *testing.T) {
}, },
} }
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("homeDir").Return("/home/bill") env.On("Home").Return("/home/bill")
env.On("getRuntimeGOOS").Return(windowsPlatform) env.On("GOOS").Return(windowsPlatform)
git := &git{ git := &git{
scm: scm{ scm: scm{
props: props, props: props,
@ -593,24 +593,24 @@ func TestGetGitCommand(t *testing.T) {
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("isWsl").Return(tc.IsWSL) env.On("IsWsl").Return(tc.IsWSL)
env.On("getRuntimeGOOS").Return(tc.GOOS) env.On("GOOS").Return(tc.GOOS)
env.On("pwd").Return(tc.CWD) env.On("Pwd").Return(tc.CWD)
wslUname := "5.10.60.1-microsoft-standard-WSL2" wslUname := "5.10.60.1-microsoft-standard-WSL2"
if tc.IsWSL1 { if tc.IsWSL1 {
wslUname = "4.4.0-19041-Microsoft" wslUname = "4.4.0-19041-Microsoft"
} }
env.On("runCommand", "uname", []string{"-r"}).Return(wslUname, nil) env.On("RunCommand", "uname", []string{"-r"}).Return(wslUname, nil)
g := &git{ g := &git{
scm: scm{ scm: scm{
env: env, env: env,
}, },
} }
if tc.IsWslSharedPath { if tc.IsWslSharedPath {
env.On("inWSLSharedDrive").Return(true) env.On("InWSLSharedDrive").Return(true)
g.IsWslSharedPath = tc.IsWslSharedPath g.IsWslSharedPath = tc.IsWslSharedPath
} else { } else {
env.On("inWSLSharedDrive").Return(false) env.On("InWSLSharedDrive").Return(false)
} }
assert.Equal(t, tc.Expected, g.getGitCommand(), tc.Case) assert.Equal(t, tc.Expected, g.getGitCommand(), tc.Case)
} }
@ -744,9 +744,8 @@ func TestGitTemplateString(t *testing.T) {
FetchStatus: true, FetchStatus: true,
} }
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.onTemplate()
tc.Git.env = env tc.Git.env = env
tc.Git.props = props tc.Git.props = props
assert.Equal(t, tc.Expected, tc.Git.templateString(tc.Template), tc.Case) assert.Equal(t, tc.Expected, renderTemplate(env, tc.Template, tc.Git), tc.Case)
} }
} }

View file

@ -12,9 +12,8 @@ const (
ParseModFile Property = "parse_mod_file" ParseModFile Property = "parse_mod_file"
) )
func (g *golang) string() string { func (g *golang) template() string {
segmentTemplate := g.language.props.getString(SegmentTemplate, "{{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }}") return languageTemplate
return g.language.string(segmentTemplate, g)
} }
func (g *golang) init(props Properties, env Environment) { func (g *golang) init(props Properties, env Environment) {
@ -41,12 +40,12 @@ func (g *golang) getVersion() (string, error) {
if !g.props.getBool(ParseModFile, false) { if !g.props.getBool(ParseModFile, false) {
return "", nil return "", nil
} }
gomod, err := g.language.env.hasParentFilePath("go.mod") gomod, err := g.language.env.HasParentFilePath("go.mod")
if err != nil { if err != nil {
return "", nil return "", nil
} }
contents := g.language.env.getFileContent(gomod.path) contents := g.language.env.FileContent(gomod.Path)
file, err := modfile.Parse(gomod.path, []byte(contents), nil) file, err := modfile.Parse(gomod.Path, []byte(contents), nil)
if err != nil { if err != nil {
return "", err return "", err
} }

View file

@ -18,12 +18,14 @@ type mockedLanguageParams struct {
func getMockedLanguageEnv(params *mockedLanguageParams) (*MockedEnvironment, properties) { func getMockedLanguageEnv(params *mockedLanguageParams) (*MockedEnvironment, properties) {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("hasCommand", params.cmd).Return(true) env.On("HasCommand", params.cmd).Return(true)
env.On("runCommand", params.cmd, []string{params.versionParam}).Return(params.versionOutput, nil) env.On("RunCommand", params.cmd, []string{params.versionParam}).Return(params.versionOutput, nil)
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("homeDir").Return("/usr/home") env.On("Home").Return("/usr/home")
env.onTemplate() env.On("TemplateCache").Return(&TemplateCache{
Env: make(map[string]string),
})
props := properties{ props := properties{
FetchVersion: true, FetchVersion: true,
} }
@ -62,28 +64,28 @@ func TestGolang(t *testing.T) {
env, props := getMockedLanguageEnv(params) env, props := getMockedLanguageEnv(params)
if tc.ParseModFile { if tc.ParseModFile {
props[ParseModFile] = tc.ParseModFile props[ParseModFile] = tc.ParseModFile
fileInfo := &fileInfo{ fileInfo := &FileInfo{
path: "./go.mod", Path: "./go.mod",
parentFolder: "./", ParentFolder: "./",
isDir: false, IsDir: false,
} }
var err error var err error
if !tc.HasModFileInParentDir { if !tc.HasModFileInParentDir {
err = errors.New("no match") err = errors.New("no match")
} }
env.On("hasParentFilePath", "go.mod").Return(fileInfo, err) env.On("HasParentFilePath", "go.mod").Return(fileInfo, err)
var content string var content string
if tc.InvalidModfile { if tc.InvalidModfile {
content = "invalid go.mod file" content = "invalid go.mod file"
} else { } else {
tmp, _ := ioutil.ReadFile(fileInfo.path) tmp, _ := ioutil.ReadFile(fileInfo.Path)
content = string(tmp) content = string(tmp)
} }
env.On("getFileContent", fileInfo.path).Return(content) env.On("FileContent", fileInfo.Path).Return(content)
} }
g := &golang{} g := &golang{}
g.init(props, env) g.init(props, env)
assert.True(t, g.enabled(), fmt.Sprintf("Failed in case: %s", tc.Case)) assert.True(t, g.enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
assert.Equal(t, tc.ExpectedString, g.string(), fmt.Sprintf("Failed in case: %s", tc.Case)) assert.Equal(t, tc.ExpectedString, renderTemplate(env, g.template(), g), fmt.Sprintf("Failed in case: %s", tc.Case))
} }
} }

View file

@ -10,6 +10,10 @@ const (
IpifyURL Property = "url" IpifyURL Property = "url"
) )
func (i *ipify) template() string {
return "{{ .IP }}"
}
func (i *ipify) enabled() bool { func (i *ipify) enabled() bool {
ip, err := i.getResult() ip, err := i.getResult()
if err != nil { if err != nil {
@ -20,21 +24,6 @@ func (i *ipify) enabled() bool {
return true return true
} }
func (i *ipify) string() string {
segmentTemplate := i.props.getString(SegmentTemplate, "{{.IP}}")
template := &textTemplate{
Template: segmentTemplate,
Context: i,
Env: i.env,
}
text, err := template.render()
if err != nil {
return err.Error()
}
return text
}
func (i *ipify) getResult() (string, error) { func (i *ipify) getResult() (string, error) {
cacheTimeout := i.props.getInt(CacheTimeout, DefaultCacheTimeout) cacheTimeout := i.props.getInt(CacheTimeout, DefaultCacheTimeout)
@ -42,7 +31,7 @@ func (i *ipify) getResult() (string, error) {
if cacheTimeout > 0 { if cacheTimeout > 0 {
// check if data stored in cache // check if data stored in cache
val, found := i.env.cache().get(url) val, found := i.env.Cache().Get(url)
// we got something from te cache // we got something from te cache
if found { if found {
return val, nil return val, nil
@ -61,7 +50,7 @@ func (i *ipify) getResult() (string, error) {
if cacheTimeout > 0 { if cacheTimeout > 0 {
// persist public ip in cache // persist public ip in cache
i.env.cache().set(url, response, cacheTimeout) i.env.Cache().Set(url, response, cacheTimeout)
} }
return response, nil return response, nil
} }

View file

@ -46,25 +46,22 @@ func TestIpifySegment(t *testing.T) {
props := properties{ props := properties{
CacheTimeout: 0, CacheTimeout: 0,
} }
env.On("HTTPRequest", IPIFYAPIURL).Return([]byte(tc.Response), tc.Error) env.On("HTTPRequest", IPIFYAPIURL).Return([]byte(tc.Response), tc.Error)
env.onTemplate()
if tc.Template != "" { ipify := &ipify{
props[SegmentTemplate] = tc.Template
}
o := &ipify{
props: props, props: props,
env: env, env: env,
} }
enabled := o.enabled() enabled := ipify.enabled()
assert.Equal(t, tc.ExpectedEnabled, enabled, tc.Case) assert.Equal(t, tc.ExpectedEnabled, enabled, tc.Case)
if !enabled { if !enabled {
continue continue
} }
assert.Equal(t, tc.ExpectedString, o.string(), tc.Case) if tc.Template == "" {
tc.Template = ipify.template()
}
assert.Equal(t, tc.ExpectedString, renderTemplate(env, tc.Template, ipify), tc.Case)
} }
} }

View file

@ -6,9 +6,8 @@ type java struct {
language language
} }
func (j *java) string() string { func (j *java) template() string {
segmentTemplate := j.language.props.getString(SegmentTemplate, "{{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }}") return languageTemplate
return j.language.string(segmentTemplate, j)
} }
func (j *java) init(props Properties, env Environment) { func (j *java) init(props Properties, env Environment) {
@ -37,7 +36,7 @@ func (j *java) init(props Properties, env Environment) {
"*.cljc", "*.cljc",
}, },
} }
javaHome := j.language.env.getenv("JAVA_HOME") javaHome := j.language.env.Getenv("JAVA_HOME")
if len(javaHome) > 0 { if len(javaHome) > 0 {
java := fmt.Sprintf("%s/bin/java", javaHome) java := fmt.Sprintf("%s/bin/java", javaHome)
j.language.commands = []*cmd{ j.language.commands = []*cmd{

View file

@ -54,25 +54,24 @@ func TestJava(t *testing.T) {
} }
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("hasCommand", "java").Return(true) env.On("HasCommand", "java").Return(true)
env.On("runCommand", "java", []string{"-Xinternalversion"}).Return(tc.Version, nil) env.On("RunCommand", "java", []string{"-Xinternalversion"}).Return(tc.Version, nil)
env.On("hasFiles", "pom.xml").Return(true) env.On("HasFiles", "pom.xml").Return(true)
env.On("pwd").Return("/usr/home/project") env.On("Pwd").Return("/usr/home/project")
env.On("homeDir").Return("/usr/home") env.On("Home").Return("/usr/home")
if tc.JavaHomeEnabled { if tc.JavaHomeEnabled {
env.On("getenv", "JAVA_HOME").Return("/usr/java") env.On("Getenv", "JAVA_HOME").Return("/usr/java")
env.On("hasCommand", "/usr/java/bin/java").Return(true) env.On("HasCommand", "/usr/java/bin/java").Return(true)
env.On("runCommand", "/usr/java/bin/java", []string{"-Xinternalversion"}).Return(tc.JavaHomeVersion, nil) env.On("RunCommand", "/usr/java/bin/java", []string{"-Xinternalversion"}).Return(tc.JavaHomeVersion, nil)
} else { } else {
env.On("getenv", "JAVA_HOME").Return("") env.On("Getenv", "JAVA_HOME").Return("")
} }
env.onTemplate()
props := properties{ props := properties{
FetchVersion: true, FetchVersion: true,
} }
j := &java{} j := &java{}
j.init(props, env) j.init(props, env)
assert.True(t, j.enabled(), fmt.Sprintf("Failed in case: %s", tc.Case)) assert.True(t, j.enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
assert.Equal(t, tc.ExpectedString, j.string(), fmt.Sprintf("Failed in case: %s", tc.Case)) assert.Equal(t, tc.ExpectedString, renderTemplate(env, j.template(), j), fmt.Sprintf("Failed in case: %s", tc.Case))
} }
} }

View file

@ -4,9 +4,8 @@ type julia struct {
language language
} }
func (j *julia) string() string { func (j *julia) template() string {
segmentTemplate := j.language.props.getString(SegmentTemplate, "{{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }}") return languageTemplate
return j.language.string(segmentTemplate, j)
} }
func (j *julia) init(props Properties, env Environment) { func (j *julia) init(props Properties, env Environment) {

View file

@ -27,6 +27,6 @@ func TestJulia(t *testing.T) {
j := &julia{} j := &julia{}
j.init(props, env) j.init(props, env)
assert.True(t, j.enabled(), fmt.Sprintf("Failed in case: %s", tc.Case)) assert.True(t, j.enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
assert.Equal(t, tc.ExpectedString, j.string(), fmt.Sprintf("Failed in case: %s", tc.Case)) assert.Equal(t, tc.ExpectedString, renderTemplate(env, j.template(), j), fmt.Sprintf("Failed in case: %s", tc.Case))
} }
} }

View file

@ -30,18 +30,8 @@ type KubeContext struct {
Namespace string `yaml:"namespace"` Namespace string `yaml:"namespace"`
} }
func (k *kubectl) string() string { func (k *kubectl) template() string {
segmentTemplate := k.props.getString(SegmentTemplate, "{{.Context}}{{if .Namespace}} :: {{.Namespace}}{{end}}") return "{{ .Context }}{{ if .Namespace }} :: {{ .Namespace }}{{ end }}"
template := &textTemplate{
Template: segmentTemplate,
Context: k,
Env: k.env,
}
text, err := template.render()
if err != nil {
return err.Error()
}
return text
} }
func (k *kubectl) init(props Properties, env Environment) { func (k *kubectl) init(props Properties, env Environment) {
@ -60,9 +50,9 @@ func (k *kubectl) enabled() bool {
func (k *kubectl) doParseKubeConfig() bool { func (k *kubectl) doParseKubeConfig() bool {
// Follow kubectl search rules (see https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/#the-kubeconfig-environment-variable) // Follow kubectl search rules (see https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/#the-kubeconfig-environment-variable)
// TL;DR: KUBECONFIG can contain a list of files. If it's empty ~/.kube/config is used. First file in list wins when merging keys. // TL;DR: KUBECONFIG can contain a list of files. If it's empty ~/.kube/config is used. First file in list wins when merging keys.
kubeconfigs := filepath.SplitList(k.env.getenv("KUBECONFIG")) kubeconfigs := filepath.SplitList(k.env.Getenv("KUBECONFIG"))
if len(kubeconfigs) == 0 { if len(kubeconfigs) == 0 {
kubeconfigs = []string{filepath.Join(k.env.homeDir(), ".kube/config")} kubeconfigs = []string{filepath.Join(k.env.Home(), ".kube/config")}
} }
contexts := make(map[string]*KubeContext) contexts := make(map[string]*KubeContext)
k.Context = "" k.Context = ""
@ -71,7 +61,7 @@ func (k *kubectl) doParseKubeConfig() bool {
continue continue
} }
content := k.env.getFileContent(kubeconfig) content := k.env.FileContent(kubeconfig)
var config KubeConfig var config KubeConfig
err := yaml.Unmarshal([]byte(content), &config) err := yaml.Unmarshal([]byte(content), &config)
@ -109,10 +99,10 @@ func (k *kubectl) doParseKubeConfig() bool {
func (k *kubectl) doCallKubectl() bool { func (k *kubectl) doCallKubectl() bool {
cmd := "kubectl" cmd := "kubectl"
if !k.env.hasCommand(cmd) { if !k.env.HasCommand(cmd) {
return false return false
} }
result, err := k.env.runCommand(cmd, "config", "view", "--output", "yaml", "--minify") result, err := k.env.RunCommand(cmd, "config", "view", "--output", "yaml", "--minify")
displayError := k.props.getBool(DisplayError, false) displayError := k.props.getBool(DisplayError, false)
if err != nil && displayError { if err != nil && displayError {
k.setError("KUBECTL ERR") k.setError("KUBECTL ERR")

View file

@ -106,7 +106,7 @@ func TestKubectlSegment(t *testing.T) {
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("hasCommand", "kubectl").Return(tc.KubectlExists) env.On("HasCommand", "kubectl").Return(tc.KubectlExists)
var kubeconfig string var kubeconfig string
content, err := ioutil.ReadFile("./test/kubectl.yml") content, err := ioutil.ReadFile("./test/kubectl.yml")
if err == nil { if err == nil {
@ -119,25 +119,23 @@ func TestKubectlSegment(t *testing.T) {
exitCode: 1, exitCode: 1,
} }
} }
env.On("runCommand", "kubectl", []string{"config", "view", "--output", "yaml", "--minify"}).Return(kubeconfig, kubectlErr) env.On("RunCommand", "kubectl", []string{"config", "view", "--output", "yaml", "--minify"}).Return(kubeconfig, kubectlErr)
env.On("getenv", "KUBECONFIG").Return(tc.Kubeconfig) env.On("Getenv", "KUBECONFIG").Return(tc.Kubeconfig)
for path, content := range tc.Files { for path, content := range tc.Files {
env.On("getFileContent", path).Return(content) env.On("FileContent", path).Return(content)
} }
env.On("homeDir").Return("testhome") env.On("Home").Return("testhome")
env.onTemplate()
k := &kubectl{ k := &kubectl{
env: env, env: env,
props: properties{ props: properties{
SegmentTemplate: tc.Template,
DisplayError: tc.DisplayError, DisplayError: tc.DisplayError,
ParseKubeConfig: tc.ParseKubeConfig, ParseKubeConfig: tc.ParseKubeConfig,
}, },
} }
assert.Equal(t, tc.ExpectedEnabled, k.enabled(), tc.Case) assert.Equal(t, tc.ExpectedEnabled, k.enabled(), tc.Case)
if tc.ExpectedEnabled { if tc.ExpectedEnabled {
assert.Equal(t, tc.ExpectedString, k.string(), tc.Case) assert.Equal(t, tc.ExpectedString, renderTemplate(env, tc.Template, k), tc.Case)
} }
} }
} }

View file

@ -5,6 +5,10 @@ import (
"fmt" "fmt"
) )
const (
languageTemplate = "{{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }}"
)
type loadContext func() type loadContext func()
type inContext func() bool type inContext func() bool
@ -83,24 +87,11 @@ const (
LanguageExtensions Property = "extensions" LanguageExtensions Property = "extensions"
) )
func (l *language) string(segmentTemplate string, context SegmentWriter) string {
template := &textTemplate{
Template: segmentTemplate,
Context: context,
Env: l.env,
}
text, err := template.render()
if err != nil {
return err.Error()
}
return text
}
func (l *language) enabled() bool { func (l *language) enabled() bool {
// override default extensions if needed // override default extensions if needed
l.extensions = l.props.getStringArray(LanguageExtensions, l.extensions) l.extensions = l.props.getStringArray(LanguageExtensions, l.extensions)
inHomeDir := func() bool { inHomeDir := func() bool {
return l.env.pwd() == l.env.homeDir() return l.env.Pwd() == l.env.Home()
} }
var enabled bool var enabled bool
homeEnabled := l.props.getBool(HomeEnabled, l.homeEnabled) homeEnabled := l.props.getBool(HomeEnabled, l.homeEnabled)
@ -138,7 +129,7 @@ func (l *language) enabled() bool {
// hasLanguageFiles will return true at least one file matching the extensions is found // hasLanguageFiles will return true at least one file matching the extensions is found
func (l *language) hasLanguageFiles() bool { func (l *language) hasLanguageFiles() bool {
for i, extension := range l.extensions { for i, extension := range l.extensions {
if l.env.hasFiles(extension) { if l.env.HasFiles(extension) {
break break
} }
if i == len(l.extensions)-1 { if i == len(l.extensions)-1 {
@ -155,10 +146,10 @@ func (l *language) setVersion() error {
var versionStr string var versionStr string
var err error var err error
if command.getVersion == nil { if command.getVersion == nil {
if !l.env.hasCommand(command.executable) { if !l.env.HasCommand(command.executable) {
continue continue
} }
versionStr, err = l.env.runCommand(command.executable, command.args...) versionStr, err = l.env.RunCommand(command.executable, command.args...)
if exitErr, ok := err.(*commandError); ok { if exitErr, ok := err.(*commandError); ok {
l.exitCode = exitErr.exitCode l.exitCode = exitErr.exitCode
return fmt.Errorf("err executing %s with %s", command.executable, command.args) return fmt.Errorf("err executing %s with %s", command.executable, command.args)

View file

@ -37,20 +37,22 @@ func (l *languageArgs) hasvalue(value string, list []string) bool {
func bootStrapLanguageTest(args *languageArgs) *language { func bootStrapLanguageTest(args *languageArgs) *language {
env := new(MockedEnvironment) env := new(MockedEnvironment)
for _, command := range args.commands { for _, command := range args.commands {
env.On("hasCommand", command.executable).Return(args.hasvalue(command.executable, args.enabledCommands)) env.On("HasCommand", command.executable).Return(args.hasvalue(command.executable, args.enabledCommands))
env.On("runCommand", command.executable, command.args).Return(args.version, args.expectedError) env.On("RunCommand", command.executable, command.args).Return(args.version, args.expectedError)
} }
for _, extension := range args.extensions { for _, extension := range args.extensions {
env.On("hasFiles", extension).Return(args.hasvalue(extension, args.enabledExtensions)) env.On("HasFiles", extension).Return(args.hasvalue(extension, args.enabledExtensions))
} }
home := "/usr/home" home := "/usr/home"
cwd := "/usr/home/project" cwd := "/usr/home/project"
if args.inHome { if args.inHome {
cwd = home cwd = home
} }
env.On("pwd").Return(cwd) env.On("Pwd").Return(cwd)
env.On("homeDir").Return(home) env.On("Home").Return(home)
env.onTemplate() env.On("TemplateCache").Return(&TemplateCache{
Env: make(map[string]string),
})
if args.properties == nil { if args.properties == nil {
args.properties = properties{} args.properties = properties{}
} }

View file

@ -7,10 +7,11 @@ import (
type nbgv struct { type nbgv struct {
props Properties props Properties
env Environment env Environment
nbgv *versionInfo
VersionInfo
} }
type versionInfo struct { type VersionInfo struct {
VersionFileFound bool `json:"VersionFileFound"` VersionFileFound bool `json:"VersionFileFound"`
Version string `json:"Version"` Version string `json:"Version"`
AssemblyVersion string `json:"AssemblyVersion"` AssemblyVersion string `json:"AssemblyVersion"`
@ -21,35 +22,25 @@ type versionInfo struct {
SimpleVersion string `json:"SimpleVersion"` SimpleVersion string `json:"SimpleVersion"`
} }
func (n *nbgv) enabled() bool { func (n *nbgv) template() string {
nbgv := "nbgv" return "{{ .Version }}"
if !n.env.hasCommand(nbgv) {
return false
}
response, err := n.env.runCommand(nbgv, "get-version", "--format=json")
if err != nil {
return false
}
n.nbgv = new(versionInfo)
err = json.Unmarshal([]byte(response), n.nbgv)
if err != nil {
return false
}
return n.nbgv.VersionFileFound
} }
func (n *nbgv) string() string { func (n *nbgv) enabled() bool {
segmentTemplate := n.props.getString(SegmentTemplate, "{{ .Version }}") nbgv := "nbgv"
template := &textTemplate{ if !n.env.HasCommand(nbgv) {
Template: segmentTemplate, return false
Context: n.nbgv,
Env: n.env,
} }
text, err := template.render() response, err := n.env.RunCommand(nbgv, "get-version", "--format=json")
if err != nil { if err != nil {
return err.Error() return false
} }
return text n.VersionInfo = VersionInfo{}
err = json.Unmarshal([]byte(response), &n.VersionInfo)
if err != nil {
return false
}
return n.VersionInfo.VersionFileFound
} }
func (n *nbgv) init(props Properties, env Environment) { func (n *nbgv) init(props Properties, env Environment) {

View file

@ -14,7 +14,7 @@ func TestNbgv(t *testing.T) {
ExpectedString string ExpectedString string
Response string Response string
HasNbgv bool HasNbgv bool
SegmentTemplate string Template string
Error error Error error
}{ }{
{Case: "nbgv not installed"}, {Case: "nbgv not installed"},
@ -26,7 +26,7 @@ func TestNbgv(t *testing.T) {
ExpectedString: "invalid template text", ExpectedString: "invalid template text",
HasNbgv: true, HasNbgv: true,
Response: "{ \"VersionFileFound\": true }", Response: "{ \"VersionFileFound\": true }",
SegmentTemplate: "{{ err }}", Template: "{{ err }}",
}, },
{ {
Case: "command error", Case: "command error",
@ -44,7 +44,7 @@ func TestNbgv(t *testing.T) {
ExpectedString: "bump", ExpectedString: "bump",
HasNbgv: true, HasNbgv: true,
Response: "{ \"VersionFileFound\": true, \"Version\": \"bump\" }", Response: "{ \"VersionFileFound\": true, \"Version\": \"bump\" }",
SegmentTemplate: "{{ .Version }}", Template: "{{ .Version }}",
}, },
{ {
Case: "AssemblyVersion", Case: "AssemblyVersion",
@ -52,25 +52,25 @@ func TestNbgv(t *testing.T) {
ExpectedString: "bump", ExpectedString: "bump",
HasNbgv: true, HasNbgv: true,
Response: "{ \"VersionFileFound\": true, \"AssemblyVersion\": \"bump\" }", Response: "{ \"VersionFileFound\": true, \"AssemblyVersion\": \"bump\" }",
SegmentTemplate: "{{ .AssemblyVersion }}", Template: "{{ .AssemblyVersion }}",
}, },
} }
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("hasCommand", "nbgv").Return(tc.HasNbgv) env.On("HasCommand", "nbgv").Return(tc.HasNbgv)
env.On("runCommand", "nbgv", []string{"get-version", "--format=json"}).Return(tc.Response, tc.Error) env.On("RunCommand", "nbgv", []string{"get-version", "--format=json"}).Return(tc.Response, tc.Error)
env.onTemplate()
nbgv := &nbgv{ nbgv := &nbgv{
env: env, env: env,
props: properties{ props: properties{},
SegmentTemplate: tc.SegmentTemplate,
},
} }
enabled := nbgv.enabled() enabled := nbgv.enabled()
assert.Equal(t, tc.ExpectedEnabled, enabled, tc.Case) assert.Equal(t, tc.ExpectedEnabled, enabled, tc.Case)
if tc.Template == "" {
tc.Template = nbgv.template()
}
if enabled { if enabled {
assert.Equal(t, tc.ExpectedString, nbgv.string(), tc.Case) assert.Equal(t, tc.ExpectedString, renderTemplate(env, tc.Template, nbgv), tc.Case)
} }
} }
} }

View file

@ -45,6 +45,10 @@ type NightscoutData struct {
Mills int64 `json:"mills"` Mills int64 `json:"mills"`
} }
func (ns *nightscout) template() string {
return "{{ .Sgv }}"
}
func (ns *nightscout) enabled() bool { func (ns *nightscout) enabled() bool {
data, err := ns.getResult() data, err := ns.getResult()
if err != nil { if err != nil {
@ -77,21 +81,6 @@ func (ns *nightscout) getTrendIcon() string {
} }
} }
func (ns *nightscout) string() string {
segmentTemplate := ns.props.getString(SegmentTemplate, "{{.Sgv}}")
template := &textTemplate{
Template: segmentTemplate,
Context: ns,
Env: ns.env,
}
text, err := template.render()
if err != nil {
return err.Error()
}
return text
}
func (ns *nightscout) getResult() (*NightscoutData, error) { func (ns *nightscout) getResult() (*NightscoutData, error) {
parseSingleElement := func(data []byte) (*NightscoutData, error) { parseSingleElement := func(data []byte) (*NightscoutData, error) {
var result []*NightscoutData var result []*NightscoutData
@ -105,7 +94,7 @@ func (ns *nightscout) getResult() (*NightscoutData, error) {
return result[0], nil return result[0], nil
} }
getCacheValue := func(key string) (*NightscoutData, error) { getCacheValue := func(key string) (*NightscoutData, error) {
val, found := ns.env.cache().get(key) val, found := ns.env.Cache().Get(key)
// we got something from the cache // we got something from the cache
if found { if found {
if data, err := parseSingleElement([]byte(val)); err == nil { if data, err := parseSingleElement([]byte(val)); err == nil {
@ -143,7 +132,7 @@ func (ns *nightscout) getResult() (*NightscoutData, error) {
if cacheTimeout > 0 { if cacheTimeout > 0 {
// persist new sugars in cache // persist new sugars in cache
ns.env.cache().set(url, string(body), cacheTimeout) ns.env.Cache().Set(url, string(body), cacheTimeout)
} }
return data, nil return data, nil
} }

View file

@ -136,16 +136,11 @@ func TestNSSegment(t *testing.T) {
} }
cache := &MockedCache{} cache := &MockedCache{}
cache.On("get", FAKEAPIURL).Return(tc.JSONResponse, !tc.CacheFoundFail) cache.On("Get", FAKEAPIURL).Return(tc.JSONResponse, !tc.CacheFoundFail)
cache.On("set", FAKEAPIURL, tc.JSONResponse, tc.CacheTimeout).Return() cache.On("Set", FAKEAPIURL, tc.JSONResponse, tc.CacheTimeout).Return()
env.On("HTTPRequest", FAKEAPIURL).Return([]byte(tc.JSONResponse), tc.Error) env.On("HTTPRequest", FAKEAPIURL).Return([]byte(tc.JSONResponse), tc.Error)
env.On("cache").Return(cache) env.On("Cache").Return(cache)
env.onTemplate()
if tc.Template != "" {
props[SegmentTemplate] = tc.Template
}
ns := &nightscout{ ns := &nightscout{
props: props, props: props,
@ -158,6 +153,9 @@ func TestNSSegment(t *testing.T) {
continue continue
} }
assert.Equal(t, tc.ExpectedString, ns.string(), tc.Case) if tc.Template == "" {
tc.Template = ns.template()
}
assert.Equal(t, tc.ExpectedString, renderTemplate(env, tc.Template, ns), tc.Case)
} }
} }

View file

@ -17,9 +17,8 @@ const (
FetchPackageManager Property = "fetch_package_manager" FetchPackageManager Property = "fetch_package_manager"
) )
func (n *node) string() string { func (n *node) template() string {
segmentTemplate := n.language.props.getString(SegmentTemplate, "{{ if .PackageManagerIcon }}{{ .PackageManagerIcon }} {{ end }}{{ .Full }}") return "{{ if .PackageManagerIcon }}{{ .PackageManagerIcon }} {{ end }}{{ .Full }}"
return n.language.string(segmentTemplate, n)
} }
func (n *node) init(props Properties, env Environment) { func (n *node) init(props Properties, env Environment) {
@ -48,17 +47,17 @@ func (n *node) loadContext() {
if !n.language.props.getBool(FetchPackageManager, false) { if !n.language.props.getBool(FetchPackageManager, false) {
return return
} }
if n.language.env.hasFiles("yarn.lock") { if n.language.env.HasFiles("yarn.lock") {
n.PackageManagerIcon = n.language.props.getString(YarnIcon, " \uF61A") n.PackageManagerIcon = n.language.props.getString(YarnIcon, " \uF61A")
return return
} }
if n.language.env.hasFiles("package-lock.json") || n.language.env.hasFiles("package.json") { if n.language.env.HasFiles("package-lock.json") || n.language.env.HasFiles("package.json") {
n.PackageManagerIcon = n.language.props.getString(NPMIcon, " \uE71E") n.PackageManagerIcon = n.language.props.getString(NPMIcon, " \uE71E")
} }
} }
func (n *node) matchesVersionFile() bool { func (n *node) matchesVersionFile() bool {
fileVersion := n.language.env.getFileContent(".nvmrc") fileVersion := n.language.env.FileContent(".nvmrc")
if len(fileVersion) == 0 { if len(fileVersion) == 0 {
return true return true
} }

View file

@ -30,7 +30,7 @@ func TestNodeMatchesVersionFile(t *testing.T) {
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("getFileContent", ".nvmrc").Return(tc.RCVersion) env.On("FileContent", ".nvmrc").Return(tc.RCVersion)
node := &node{ node := &node{
language: language{ language: language{
@ -61,9 +61,9 @@ func TestNodeInContext(t *testing.T) {
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("hasFiles", "yarn.lock").Return(tc.HasYarn) env.On("HasFiles", "yarn.lock").Return(tc.HasYarn)
env.On("hasFiles", "package-lock.json").Return(tc.hasNPM) env.On("HasFiles", "package-lock.json").Return(tc.hasNPM)
env.On("hasFiles", "package.json").Return(tc.hasDefault) env.On("HasFiles", "package.json").Return(tc.hasDefault)
node := &node{ node := &node{
language: language{ language: language{
env: env, env: env,

View file

@ -56,86 +56,76 @@ const (
DisplayDistroName Property = "display_distro_name" DisplayDistroName Property = "display_distro_name"
) )
func (n *osInfo) enabled() bool { func (oi *osInfo) template() string {
goos := n.env.getRuntimeGOOS() return "{{ if .WSL }}WSL at {{ end }}{{.Icon}}"
}
func (oi *osInfo) enabled() bool {
goos := oi.env.GOOS()
switch goos { switch goos {
case windowsPlatform: case windowsPlatform:
n.Icon = n.props.getString(Windows, "\uE62A") oi.Icon = oi.props.getString(Windows, "\uE62A")
case darwinPlatform: case darwinPlatform:
n.Icon = n.props.getString(MacOS, "\uF179") oi.Icon = oi.props.getString(MacOS, "\uF179")
case linuxPlatform: case linuxPlatform:
platform := n.env.getPlatform() platform := oi.env.Platform()
displayDistroName := n.props.getBool(DisplayDistroName, false) displayDistroName := oi.props.getBool(DisplayDistroName, false)
if displayDistroName { if displayDistroName {
n.Icon = platform oi.Icon = platform
break break
} }
n.Icon = n.getDistroIcon(platform) oi.Icon = oi.getDistroIcon(platform)
default: default:
n.Icon = goos oi.Icon = goos
} }
return true return true
} }
func (n *osInfo) string() string { func (oi *osInfo) getDistroIcon(distro string) string {
segmentTemplate := n.props.getString(SegmentTemplate, "{{ if .WSL }}WSL at {{ end }}{{.Icon}}")
template := &textTemplate{
Template: segmentTemplate,
Context: n,
Env: n.env,
}
text, err := template.render()
if err != nil {
return err.Error()
}
return text
}
func (n *osInfo) getDistroIcon(distro string) string {
switch distro { switch distro {
case "alpine": case "alpine":
return n.props.getString(Alpine, "\uF300") return oi.props.getString(Alpine, "\uF300")
case "aosc": case "aosc":
return n.props.getString(Aosc, "\uF301") return oi.props.getString(Aosc, "\uF301")
case "arch": case "arch":
return n.props.getString(Arch, "\uF303") return oi.props.getString(Arch, "\uF303")
case "centos": case "centos":
return n.props.getString(Centos, "\uF304") return oi.props.getString(Centos, "\uF304")
case "coreos": case "coreos":
return n.props.getString(Coreos, "\uF305") return oi.props.getString(Coreos, "\uF305")
case "debian": case "debian":
return n.props.getString(Debian, "\uF306") return oi.props.getString(Debian, "\uF306")
case "devuan": case "devuan":
return n.props.getString(Devuan, "\uF307") return oi.props.getString(Devuan, "\uF307")
case "raspbian": case "raspbian":
return n.props.getString(Raspbian, "\uF315") return oi.props.getString(Raspbian, "\uF315")
case "elementary": case "elementary":
return n.props.getString(Elementary, "\uF309") return oi.props.getString(Elementary, "\uF309")
case "fedora": case "fedora":
return n.props.getString(Fedora, "\uF30a") return oi.props.getString(Fedora, "\uF30a")
case "gentoo": case "gentoo":
return n.props.getString(Gentoo, "\uF30d") return oi.props.getString(Gentoo, "\uF30d")
case "mageia": case "mageia":
return n.props.getString(Mageia, "\uF310") return oi.props.getString(Mageia, "\uF310")
case "manjaro": case "manjaro":
return n.props.getString(Manjaro, "\uF312") return oi.props.getString(Manjaro, "\uF312")
case "mint": case "mint":
return n.props.getString(Mint, "\uF30e") return oi.props.getString(Mint, "\uF30e")
case "nixos": case "nixos":
return n.props.getString(Nixos, "\uF313") return oi.props.getString(Nixos, "\uF313")
case "opensuse": case "opensuse":
return n.props.getString(Opensuse, "\uF314") return oi.props.getString(Opensuse, "\uF314")
case "sabayon": case "sabayon":
return n.props.getString(Sabayon, "\uF317") return oi.props.getString(Sabayon, "\uF317")
case "slackware": case "slackware":
return n.props.getString(Slackware, "\uF319") return oi.props.getString(Slackware, "\uF319")
case "ubuntu": case "ubuntu":
return n.props.getString(Ubuntu, "\uF31b") return oi.props.getString(Ubuntu, "\uF31b")
} }
return n.props.getString(Linux, "\uF17C") return oi.props.getString(Linux, "\uF17C")
} }
func (n *osInfo) init(props Properties, env Environment) { func (oi *osInfo) init(props Properties, env Environment) {
n.props = props oi.props = props
n.env = env oi.env = env
} }

View file

@ -61,9 +61,9 @@ func TestOSInfo(t *testing.T) {
} }
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("getRuntimeGOOS").Return(tc.GOOS) env.On("GOOS").Return(tc.GOOS)
env.On("getPlatform").Return(tc.Platform) env.On("Platform").Return(tc.Platform)
env.On("templateCache").Return(&templateCache{ env.On("TemplateCache").Return(&TemplateCache{
Env: make(map[string]string), Env: make(map[string]string),
WSL: tc.IsWSL, WSL: tc.IsWSL,
}) })
@ -76,6 +76,6 @@ func TestOSInfo(t *testing.T) {
}, },
} }
_ = osInfo.enabled() _ = osInfo.enabled()
assert.Equal(t, tc.ExpectedString, osInfo.string(), tc.Case) assert.Equal(t, tc.ExpectedString, renderTemplate(env, osInfo.template(), osInfo), tc.Case)
} }
} }

View file

@ -50,18 +50,8 @@ func (d *owm) enabled() bool {
return err == nil return err == nil
} }
func (d *owm) string() string { func (d *owm) template() string {
segmentTemplate := d.props.getString(SegmentTemplate, "{{.Weather}} ({{.Temperature}}{{.UnitIcon}})") return "{{ .Weather }} ({{ .Temperature }}{{ .UnitIcon }})"
template := &textTemplate{
Template: segmentTemplate,
Context: d,
Env: d.env,
}
text, err := template.render()
if err != nil {
return err.Error()
}
return text
} }
func (d *owm) getResult() (*owmDataResponse, error) { func (d *owm) getResult() (*owmDataResponse, error) {
@ -69,14 +59,14 @@ func (d *owm) getResult() (*owmDataResponse, error) {
response := new(owmDataResponse) response := new(owmDataResponse)
if cacheTimeout > 0 { if cacheTimeout > 0 {
// check if data stored in cache // check if data stored in cache
val, found := d.env.cache().get(CacheKeyResponse) val, found := d.env.Cache().Get(CacheKeyResponse)
// we got something from te cache // we got something from te cache
if found { if found {
err := json.Unmarshal([]byte(val), response) err := json.Unmarshal([]byte(val), response)
if err != nil { if err != nil {
return nil, err return nil, err
} }
d.URL, _ = d.env.cache().get(CacheKeyURL) d.URL, _ = d.env.Cache().Get(CacheKeyURL)
return response, nil return response, nil
} }
} }
@ -98,8 +88,8 @@ func (d *owm) getResult() (*owmDataResponse, error) {
if cacheTimeout > 0 { if cacheTimeout > 0 {
// persist new forecasts in cache // persist new forecasts in cache
d.env.cache().set(CacheKeyResponse, string(body), cacheTimeout) d.env.Cache().Set(CacheKeyResponse, string(body), cacheTimeout)
d.env.cache().set(CacheKeyURL, d.URL, cacheTimeout) d.env.Cache().Set(CacheKeyURL, d.URL, cacheTimeout)
} }
return response, nil return response, nil
} }

View file

@ -59,11 +59,6 @@ func TestOWMSegmentSingle(t *testing.T) {
} }
env.On("HTTPRequest", OWMAPIURL).Return([]byte(tc.JSONResponse), tc.Error) env.On("HTTPRequest", OWMAPIURL).Return([]byte(tc.JSONResponse), tc.Error)
env.onTemplate()
if tc.Template != "" {
props[SegmentTemplate] = tc.Template
}
o := &owm{ o := &owm{
props: props, props: props,
@ -76,7 +71,10 @@ func TestOWMSegmentSingle(t *testing.T) {
continue continue
} }
assert.Equal(t, tc.ExpectedString, o.string(), tc.Case) if tc.Template == "" {
tc.Template = o.template()
}
assert.Equal(t, tc.ExpectedString, renderTemplate(env, tc.Template, o), tc.Case)
} }
} }
@ -186,7 +184,6 @@ func TestOWMSegmentIcons(t *testing.T) {
expectedString := fmt.Sprintf("%s (20°C)", tc.ExpectedIconString) expectedString := fmt.Sprintf("%s (20°C)", tc.ExpectedIconString)
env.On("HTTPRequest", OWMAPIURL).Return([]byte(response), nil) env.On("HTTPRequest", OWMAPIURL).Return([]byte(response), nil)
env.onTemplate()
o := &owm{ o := &owm{
props: properties{ props: properties{
@ -199,7 +196,7 @@ func TestOWMSegmentIcons(t *testing.T) {
} }
assert.Nil(t, o.setStatus()) assert.Nil(t, o.setStatus())
assert.Equal(t, expectedString, o.string(), tc.Case) assert.Equal(t, expectedString, renderTemplate(env, o.template(), o), tc.Case)
} }
// test with hyperlink enabled // test with hyperlink enabled
@ -210,7 +207,6 @@ func TestOWMSegmentIcons(t *testing.T) {
expectedString := fmt.Sprintf("[%s (20°C)](http://api.openweathermap.org/data/2.5/weather?q=AMSTERDAM,NL&units=metric&appid=key)", tc.ExpectedIconString) expectedString := fmt.Sprintf("[%s (20°C)](http://api.openweathermap.org/data/2.5/weather?q=AMSTERDAM,NL&units=metric&appid=key)", tc.ExpectedIconString)
env.On("HTTPRequest", OWMAPIURL).Return([]byte(response), nil) env.On("HTTPRequest", OWMAPIURL).Return([]byte(response), nil)
env.onTemplate()
o := &owm{ o := &owm{
props: properties{ props: properties{
@ -218,13 +214,12 @@ func TestOWMSegmentIcons(t *testing.T) {
Location: "AMSTERDAM,NL", Location: "AMSTERDAM,NL",
Units: "metric", Units: "metric",
CacheTimeout: 0, CacheTimeout: 0,
SegmentTemplate: "[{{.Weather}} ({{.Temperature}}{{.UnitIcon}})]({{.URL}})",
}, },
env: env, env: env,
} }
assert.Nil(t, o.setStatus()) assert.Nil(t, o.setStatus())
assert.Equal(t, expectedString, o.string(), tc.Case) assert.Equal(t, expectedString, renderTemplate(env, "[{{.Weather}} ({{.Temperature}}{{.UnitIcon}})]({{.URL}})", o), tc.Case)
} }
} }
func TestOWMSegmentFromCache(t *testing.T) { func TestOWMSegmentFromCache(t *testing.T) {
@ -241,14 +236,13 @@ func TestOWMSegmentFromCache(t *testing.T) {
}, },
env: env, env: env,
} }
cache.On("get", "owm_response").Return(response, true) cache.On("Get", "owm_response").Return(response, true)
cache.On("get", "owm_url").Return("http://api.openweathermap.org/data/2.5/weather?q=AMSTERDAM,NL&units=metric&appid=key", true) cache.On("Get", "owm_url").Return("http://api.openweathermap.org/data/2.5/weather?q=AMSTERDAM,NL&units=metric&appid=key", true)
cache.On("set").Return() cache.On("Set").Return()
env.On("cache").Return(cache) env.On("Cache").Return(cache)
env.onTemplate()
assert.Nil(t, o.setStatus()) assert.Nil(t, o.setStatus())
assert.Equal(t, expectedString, o.string()) assert.Equal(t, expectedString, renderTemplate(env, o.template(), o), "should return the cached response")
} }
func TestOWMSegmentFromCacheWithHyperlink(t *testing.T) { func TestOWMSegmentFromCacheWithHyperlink(t *testing.T) {
@ -263,16 +257,14 @@ func TestOWMSegmentFromCacheWithHyperlink(t *testing.T) {
APIKey: "key", APIKey: "key",
Location: "AMSTERDAM,NL", Location: "AMSTERDAM,NL",
Units: "metric", Units: "metric",
SegmentTemplate: "[{{.Weather}} ({{.Temperature}}{{.UnitIcon}})]({{.URL}})",
}, },
env: env, env: env,
} }
cache.On("get", "owm_response").Return(response, true) cache.On("Get", "owm_response").Return(response, true)
cache.On("get", "owm_url").Return("http://api.openweathermap.org/data/2.5/weather?q=AMSTERDAM,NL&units=metric&appid=key", true) cache.On("Get", "owm_url").Return("http://api.openweathermap.org/data/2.5/weather?q=AMSTERDAM,NL&units=metric&appid=key", true)
cache.On("set").Return() cache.On("Set").Return()
env.On("cache").Return(cache) env.On("Cache").Return(cache)
env.onTemplate()
assert.Nil(t, o.setStatus()) assert.Nil(t, o.setStatus())
assert.Equal(t, expectedString, o.string()) assert.Equal(t, expectedString, renderTemplate(env, "[{{.Weather}} ({{.Temperature}}{{.UnitIcon}})]({{.URL}})", o))
} }

View file

@ -54,8 +54,12 @@ const (
MaxDepth Property = "max_depth" MaxDepth Property = "max_depth"
) )
func (pt *path) template() string {
return "{{ .Path }}"
}
func (pt *path) enabled() bool { func (pt *path) enabled() bool {
pt.pwd = pt.env.pwd() pt.pwd = pt.env.Pwd()
switch style := pt.props.getString(Style, Agnoster); style { switch style := pt.props.getString(Style, Agnoster); style {
case Agnoster: case Agnoster:
pt.Path = pt.getAgnosterPath() pt.Path = pt.getAgnosterPath()
@ -80,32 +84,18 @@ func (pt *path) enabled() bool {
pt.Path = fmt.Sprintf("Path style: %s is not available", style) pt.Path = fmt.Sprintf("Path style: %s is not available", style)
} }
pt.Path = pt.formatWindowsDrive(pt.Path) pt.Path = pt.formatWindowsDrive(pt.Path)
if pt.env.isWsl() { if pt.env.IsWsl() {
pt.Location, _ = pt.env.runCommand("wslpath", "-m", pt.pwd) pt.Location, _ = pt.env.RunCommand("wslpath", "-m", pt.pwd)
} else { } else {
pt.Location = pt.pwd pt.Location = pt.pwd
} }
pt.StackCount = pt.env.stackCount() pt.StackCount = pt.env.StackCount()
return true return true
} }
func (pt *path) string() string {
segmentTemplate := pt.props.getString(SegmentTemplate, "{{ .Path }}")
template := &textTemplate{
Template: segmentTemplate,
Context: pt,
Env: pt.env,
}
text, err := template.render()
if err != nil {
return err.Error()
}
return text
}
func (pt *path) formatWindowsDrive(pwd string) string { func (pt *path) formatWindowsDrive(pwd string) string {
if pt.env.getRuntimeGOOS() != windowsPlatform || !strings.HasSuffix(pwd, ":") { if pt.env.GOOS() != windowsPlatform || !strings.HasSuffix(pwd, ":") {
return pwd return pwd
} }
return pwd + "\\" return pwd + "\\"
@ -119,7 +109,7 @@ func (pt *path) init(props Properties, env Environment) {
func (pt *path) getMixedPath() string { func (pt *path) getMixedPath() string {
var buffer strings.Builder var buffer strings.Builder
pwd := pt.getPwd() pwd := pt.getPwd()
splitted := strings.Split(pwd, pt.env.getPathSeperator()) splitted := strings.Split(pwd, pt.env.PathSeperator())
threshold := int(pt.props.getFloat64(MixedThreshold, 4)) threshold := int(pt.props.getFloat64(MixedThreshold, 4))
for i, part := range splitted { for i, part := range splitted {
if part == "" { if part == "" {
@ -130,7 +120,7 @@ func (pt *path) getMixedPath() string {
if len(part) > threshold && i != 0 && i != len(splitted)-1 { if len(part) > threshold && i != 0 && i != len(splitted)-1 {
folder = pt.props.getString(FolderIcon, "..") folder = pt.props.getString(FolderIcon, "..")
} }
separator := pt.props.getString(FolderSeparatorIcon, pt.env.getPathSeperator()) separator := pt.props.getString(FolderSeparatorIcon, pt.env.PathSeperator())
if i == 0 { if i == 0 {
separator = "" separator = ""
} }
@ -146,7 +136,7 @@ func (pt *path) getAgnosterPath() string {
buffer.WriteString(pt.rootLocation()) buffer.WriteString(pt.rootLocation())
pathDepth := pt.pathDepth(pwd) pathDepth := pt.pathDepth(pwd)
folderIcon := pt.props.getString(FolderIcon, "..") folderIcon := pt.props.getString(FolderIcon, "..")
separator := pt.props.getString(FolderSeparatorIcon, pt.env.getPathSeperator()) separator := pt.props.getString(FolderSeparatorIcon, pt.env.PathSeperator())
for i := 1; i < pathDepth; i++ { for i := 1; i < pathDepth; i++ {
buffer.WriteString(fmt.Sprintf("%s%s", separator, folderIcon)) buffer.WriteString(fmt.Sprintf("%s%s", separator, folderIcon))
} }
@ -158,7 +148,7 @@ func (pt *path) getAgnosterPath() string {
func (pt *path) getAgnosterLeftPath() string { func (pt *path) getAgnosterLeftPath() string {
pwd := pt.getPwd() pwd := pt.getPwd()
separator := pt.env.getPathSeperator() separator := pt.env.PathSeperator()
pwd = strings.Trim(pwd, separator) pwd = strings.Trim(pwd, separator)
splitted := strings.Split(pwd, separator) splitted := strings.Split(pwd, separator)
folderIcon := pt.props.getString(FolderIcon, "..") folderIcon := pt.props.getString(FolderIcon, "..")
@ -182,8 +172,8 @@ func (pt *path) getAgnosterLeftPath() string {
func (pt *path) getLetterPath() string { func (pt *path) getLetterPath() string {
var buffer strings.Builder var buffer strings.Builder
pwd := pt.getPwd() pwd := pt.getPwd()
splitted := strings.Split(pwd, pt.env.getPathSeperator()) splitted := strings.Split(pwd, pt.env.PathSeperator())
separator := pt.props.getString(FolderSeparatorIcon, pt.env.getPathSeperator()) separator := pt.props.getString(FolderSeparatorIcon, pt.env.PathSeperator())
for i := 0; i < len(splitted)-1; i++ { for i := 0; i < len(splitted)-1; i++ {
folder := splitted[i] folder := splitted[i]
if len(folder) == 0 { if len(folder) == 0 {
@ -213,7 +203,7 @@ func (pt *path) getLetterPath() string {
func (pt *path) getAgnosterFullPath() string { func (pt *path) getAgnosterFullPath() string {
pwd := pt.getPwd() pwd := pt.getPwd()
if len(pwd) > 1 && string(pwd[0]) == pt.env.getPathSeperator() { if len(pwd) > 1 && string(pwd[0]) == pt.env.PathSeperator() {
pwd = pwd[1:] pwd = pwd[1:]
} }
return pt.replaceFolderSeparators(pwd) return pt.replaceFolderSeparators(pwd)
@ -229,7 +219,7 @@ func (pt *path) getAgnosterShortPath() string {
if pathDepth <= maxDepth { if pathDepth <= maxDepth {
return pt.getAgnosterFullPath() return pt.getAgnosterFullPath()
} }
pathSeparator := pt.env.getPathSeperator() pathSeparator := pt.env.PathSeperator()
folderSeparator := pt.props.getString(FolderSeparatorIcon, pathSeparator) folderSeparator := pt.props.getString(FolderSeparatorIcon, pathSeparator)
folderIcon := pt.props.getString(FolderIcon, "..") folderIcon := pt.props.getString(FolderIcon, "..")
root := pt.rootLocation() root := pt.rootLocation()
@ -256,9 +246,9 @@ func (pt *path) getFolderPath() string {
} }
func (pt *path) getPwd() string { func (pt *path) getPwd() string {
pwd := *pt.env.getArgs().PSWD pwd := *pt.env.Args().PSWD
if pwd == "" { if pwd == "" {
pwd = pt.env.pwd() pwd = pt.env.Pwd()
} }
pwd = pt.replaceMappedLocations(pwd) pwd = pt.replaceMappedLocations(pwd)
return pwd return pwd
@ -267,10 +257,10 @@ func (pt *path) getPwd() string {
func (pt *path) normalize(inputPath string) string { func (pt *path) normalize(inputPath string) string {
normalized := inputPath normalized := inputPath
if strings.HasPrefix(inputPath, "~") { if strings.HasPrefix(inputPath, "~") {
normalized = pt.env.homeDir() + normalized[1:] normalized = pt.env.Home() + normalized[1:]
} }
normalized = strings.ReplaceAll(normalized, "\\", "/") normalized = strings.ReplaceAll(normalized, "\\", "/")
goos := pt.env.getRuntimeGOOS() goos := pt.env.GOOS()
if goos == windowsPlatform || goos == darwinPlatform { if goos == windowsPlatform || goos == darwinPlatform {
normalized = strings.ToLower(normalized) normalized = strings.ToLower(normalized)
} }
@ -286,7 +276,7 @@ func (pt *path) replaceMappedLocations(pwd string) string {
if pt.props.getBool(MappedLocationsEnabled, true) { if pt.props.getBool(MappedLocationsEnabled, true) {
mappedLocations["HKCU:"] = pt.props.getString(WindowsRegistryIcon, "\uF013") mappedLocations["HKCU:"] = pt.props.getString(WindowsRegistryIcon, "\uF013")
mappedLocations["HKLM:"] = pt.props.getString(WindowsRegistryIcon, "\uF013") mappedLocations["HKLM:"] = pt.props.getString(WindowsRegistryIcon, "\uF013")
mappedLocations[pt.normalize(pt.env.homeDir())] = pt.props.getString(HomeIcon, "~") mappedLocations[pt.normalize(pt.env.Home())] = pt.props.getString(HomeIcon, "~")
} }
// merge custom locations with mapped locations // merge custom locations with mapped locations
@ -318,7 +308,7 @@ func (pt *path) replaceMappedLocations(pwd string) string {
} }
func (pt *path) replaceFolderSeparators(pwd string) string { func (pt *path) replaceFolderSeparators(pwd string) string {
defaultSeparator := pt.env.getPathSeperator() defaultSeparator := pt.env.PathSeperator()
if pwd == defaultSeparator { if pwd == defaultSeparator {
return pwd return pwd
} }
@ -332,19 +322,19 @@ func (pt *path) replaceFolderSeparators(pwd string) string {
} }
func (pt *path) inHomeDir(pwd string) bool { func (pt *path) inHomeDir(pwd string) bool {
return strings.HasPrefix(pwd, pt.env.homeDir()) return strings.HasPrefix(pwd, pt.env.Home())
} }
func (pt *path) rootLocation() string { func (pt *path) rootLocation() string {
pwd := pt.getPwd() pwd := pt.getPwd()
pwd = strings.TrimPrefix(pwd, pt.env.getPathSeperator()) pwd = strings.TrimPrefix(pwd, pt.env.PathSeperator())
splitted := strings.Split(pwd, pt.env.getPathSeperator()) splitted := strings.Split(pwd, pt.env.PathSeperator())
rootLocation := splitted[0] rootLocation := splitted[0]
return rootLocation return rootLocation
} }
func (pt *path) pathDepth(pwd string) int { func (pt *path) pathDepth(pwd string) int {
splitted := strings.Split(pwd, pt.env.getPathSeperator()) splitted := strings.Split(pwd, pt.env.PathSeperator())
depth := 0 depth := 0
for _, part := range splitted { for _, part := range splitted {
if part != "" { if part != "" {
@ -363,7 +353,7 @@ func base(path string, env Environment) string {
} }
volumeName := filepath.VolumeName(path) volumeName := filepath.VolumeName(path)
// Strip trailing slashes. // Strip trailing slashes.
for len(path) > 0 && string(path[len(path)-1]) == env.getPathSeperator() { for len(path) > 0 && string(path[len(path)-1]) == env.PathSeperator() {
path = path[0 : len(path)-1] path = path[0 : len(path)-1]
} }
if volumeName == path { if volumeName == path {
@ -373,7 +363,7 @@ func base(path string, env Environment) string {
path = path[len(filepath.VolumeName(path)):] path = path[len(filepath.VolumeName(path)):]
// Find the last element // Find the last element
i := len(path) - 1 i := len(path) - 1
for i >= 0 && string(path[i]) != env.getPathSeperator() { for i >= 0 && string(path[i]) != env.PathSeperator() {
i-- i--
} }
if i >= 0 { if i >= 0 {
@ -381,7 +371,7 @@ func base(path string, env Environment) string {
} }
// If empty now, it had only slashes. // If empty now, it had only slashes.
if path == "" { if path == "" {
return env.getPathSeperator() return env.PathSeperator()
} }
return path return path
} }

View file

@ -14,124 +14,124 @@ type MockedEnvironment struct {
mock.Mock mock.Mock
} }
func (env *MockedEnvironment) getenv(key string) string { func (env *MockedEnvironment) Getenv(key string) string {
args := env.Called(key) args := env.Called(key)
return args.String(0) return args.String(0)
} }
func (env *MockedEnvironment) pwd() string { func (env *MockedEnvironment) Pwd() string {
args := env.Called() args := env.Called()
return args.String(0) return args.String(0)
} }
func (env *MockedEnvironment) homeDir() string { func (env *MockedEnvironment) Home() string {
args := env.Called() args := env.Called()
return args.String(0) return args.String(0)
} }
func (env *MockedEnvironment) hasFiles(pattern string) bool { func (env *MockedEnvironment) HasFiles(pattern string) bool {
args := env.Called(pattern) args := env.Called(pattern)
return args.Bool(0) return args.Bool(0)
} }
func (env *MockedEnvironment) hasFilesInDir(dir, pattern string) bool { func (env *MockedEnvironment) HasFilesInDir(dir, pattern string) bool {
args := env.Called(dir, pattern) args := env.Called(dir, pattern)
return args.Bool(0) return args.Bool(0)
} }
func (env *MockedEnvironment) hasFolder(folder string) bool { func (env *MockedEnvironment) HasFolder(folder string) bool {
args := env.Called(folder) args := env.Called(folder)
return args.Bool(0) return args.Bool(0)
} }
func (env *MockedEnvironment) getFileContent(file string) string { func (env *MockedEnvironment) FileContent(file string) string {
args := env.Called(file) args := env.Called(file)
return args.String(0) return args.String(0)
} }
func (env *MockedEnvironment) getFoldersList(path string) []string { func (env *MockedEnvironment) FolderList(path string) []string {
args := env.Called(path) args := env.Called(path)
return args.Get(0).([]string) return args.Get(0).([]string)
} }
func (env *MockedEnvironment) getPathSeperator() string { func (env *MockedEnvironment) PathSeperator() string {
args := env.Called() args := env.Called()
return args.String(0) return args.String(0)
} }
func (env *MockedEnvironment) getCurrentUser() string { func (env *MockedEnvironment) User() string {
args := env.Called() args := env.Called()
return args.String(0) return args.String(0)
} }
func (env *MockedEnvironment) getHostName() (string, error) { func (env *MockedEnvironment) Host() (string, error) {
args := env.Called() args := env.Called()
return args.String(0), args.Error(1) return args.String(0), args.Error(1)
} }
func (env *MockedEnvironment) getRuntimeGOOS() string { func (env *MockedEnvironment) GOOS() string {
args := env.Called() args := env.Called()
return args.String(0) return args.String(0)
} }
func (env *MockedEnvironment) getPlatform() string { func (env *MockedEnvironment) Platform() string {
args := env.Called() args := env.Called()
return args.String(0) return args.String(0)
} }
func (env *MockedEnvironment) hasCommand(command string) bool { func (env *MockedEnvironment) HasCommand(command string) bool {
args := env.Called(command) args := env.Called(command)
return args.Bool(0) return args.Bool(0)
} }
func (env *MockedEnvironment) runCommand(command string, args ...string) (string, error) { func (env *MockedEnvironment) RunCommand(command string, args ...string) (string, error) {
arguments := env.Called(command, args) arguments := env.Called(command, args)
return arguments.String(0), arguments.Error(1) return arguments.String(0), arguments.Error(1)
} }
func (env *MockedEnvironment) runShellCommand(shell, command string) string { func (env *MockedEnvironment) RunShellCommand(shell, command string) string {
args := env.Called(shell, command) args := env.Called(shell, command)
return args.String(0) return args.String(0)
} }
func (env *MockedEnvironment) lastErrorCode() int { func (env *MockedEnvironment) ErrorCode() int {
args := env.Called() args := env.Called()
return args.Int(0) return args.Int(0)
} }
func (env *MockedEnvironment) executionTime() float64 { func (env *MockedEnvironment) ExecutionTime() float64 {
args := env.Called() args := env.Called()
return float64(args.Int(0)) return float64(args.Int(0))
} }
func (env *MockedEnvironment) isRunningAsRoot() bool { func (env *MockedEnvironment) Root() bool {
args := env.Called() args := env.Called()
return args.Bool(0) return args.Bool(0)
} }
func (env *MockedEnvironment) getArgs() *args { func (env *MockedEnvironment) Args() *Args {
arguments := env.Called() arguments := env.Called()
return arguments.Get(0).(*args) return arguments.Get(0).(*Args)
} }
func (env *MockedEnvironment) getBatteryInfo() ([]*battery.Battery, error) { func (env *MockedEnvironment) BatteryInfo() ([]*battery.Battery, error) {
args := env.Called() args := env.Called()
return args.Get(0).([]*battery.Battery), args.Error(1) return args.Get(0).([]*battery.Battery), args.Error(1)
} }
func (env *MockedEnvironment) getShellName() string { func (env *MockedEnvironment) Shell() string {
args := env.Called() args := env.Called()
return args.String(0) return args.String(0)
} }
func (env *MockedEnvironment) getWindowTitle(imageName, windowTitleRegex string) (string, error) { func (env *MockedEnvironment) WindowTitle(imageName, windowTitleRegex string) (string, error) {
args := env.Called(imageName) args := env.Called(imageName)
return args.String(0), args.Error(1) return args.String(0), args.Error(1)
} }
func (env *MockedEnvironment) getWindowsRegistryKeyValue(path string) (*windowsRegistryValue, error) { func (env *MockedEnvironment) WindowsRegistryKeyValue(path string) (*WindowsRegistryValue, error) {
args := env.Called(path) args := env.Called(path)
return args.Get(0).(*windowsRegistryValue), args.Error(1) return args.Get(0).(*WindowsRegistryValue), args.Error(1)
} }
func (env *MockedEnvironment) HTTPRequest(url string, timeout int, requestModifiers ...HTTPRequestModifier) ([]byte, error) { func (env *MockedEnvironment) HTTPRequest(url string, timeout int, requestModifiers ...HTTPRequestModifier) ([]byte, error) {
@ -139,84 +139,98 @@ func (env *MockedEnvironment) HTTPRequest(url string, timeout int, requestModifi
return args.Get(0).([]byte), args.Error(1) return args.Get(0).([]byte), args.Error(1)
} }
func (env *MockedEnvironment) hasParentFilePath(path string) (*fileInfo, error) { func (env *MockedEnvironment) HasParentFilePath(path string) (*FileInfo, error) {
args := env.Called(path) args := env.Called(path)
return args.Get(0).(*fileInfo), args.Error(1) return args.Get(0).(*FileInfo), args.Error(1)
} }
func (env *MockedEnvironment) stackCount() int { func (env *MockedEnvironment) StackCount() int {
args := env.Called() args := env.Called()
return args.Int(0) return args.Int(0)
} }
func (env *MockedEnvironment) isWsl() bool { func (env *MockedEnvironment) IsWsl() bool {
args := env.Called() args := env.Called()
return args.Bool(0) return args.Bool(0)
} }
func (env *MockedEnvironment) isWsl2() bool { func (env *MockedEnvironment) IsWsl2() bool {
args := env.Called() args := env.Called()
return args.Bool(0) return args.Bool(0)
} }
func (env *MockedEnvironment) getTerminalWidth() (int, error) { func (env *MockedEnvironment) TerminalWidth() (int, error) {
args := env.Called() args := env.Called()
return args.Int(0), args.Error(1) return args.Int(0), args.Error(1)
} }
func (env *MockedEnvironment) getCachePath() string { func (env *MockedEnvironment) CachePath() string {
args := env.Called() args := env.Called()
return args.String(0) return args.String(0)
} }
func (env *MockedEnvironment) cache() cache { func (env *MockedEnvironment) Cache() Cache {
args := env.Called() args := env.Called()
return args.Get(0).(cache) return args.Get(0).(Cache)
} }
func (env *MockedEnvironment) close() { func (env *MockedEnvironment) Close() {
_ = env.Called() _ = env.Called()
} }
func (env *MockedEnvironment) logs() string { func (env *MockedEnvironment) Logs() string {
args := env.Called() args := env.Called()
return args.String(0) return args.String(0)
} }
func (env *MockedEnvironment) inWSLSharedDrive() bool { func (env *MockedEnvironment) InWSLSharedDrive() bool {
args := env.Called() args := env.Called()
return args.Bool(0) return args.Bool(0)
} }
func (env *MockedEnvironment) convertToWindowsPath(path string) string { func (env *MockedEnvironment) ConvertToWindowsPath(path string) string {
args := env.Called() args := env.Called()
return args.String(0) return args.String(0)
} }
func (env *MockedEnvironment) convertToLinuxPath(path string) string { func (env *MockedEnvironment) ConvertToLinuxPath(path string) string {
args := env.Called() args := env.Called()
return args.String(0) return args.String(0)
} }
func (env *MockedEnvironment) getWifiNetwork() (*wifiInfo, error) { func (env *MockedEnvironment) WifiNetwork() (*WifiInfo, error) {
args := env.Called() args := env.Called()
return args.Get(0).(*wifiInfo), args.Error(1) return args.Get(0).(*WifiInfo), args.Error(1)
} }
func (env *MockedEnvironment) templateCache() *templateCache { func (env *MockedEnvironment) TemplateCache() *TemplateCache {
args := env.Called() args := env.Called()
return args.Get(0).(*templateCache) return args.Get(0).(*TemplateCache)
} }
func (env *MockedEnvironment) onTemplate() { func renderTemplate(env *MockedEnvironment, segmentTemplate string, context interface{}) string {
found := false
for _, call := range env.Mock.ExpectedCalls { for _, call := range env.Mock.ExpectedCalls {
if call.Method == "templateCache" { if call.Method == "TemplateCache" {
return found = true
break
} }
} }
env.On("templateCache").Return(&templateCache{ if !found {
env.On("TemplateCache").Return(&TemplateCache{
Env: make(map[string]string), Env: make(map[string]string),
}) })
}
template := &textTemplate{
Template: segmentTemplate,
Context: context,
Env: env,
}
text, err := template.render()
if err != nil {
return err.Error()
}
return text
} }
const ( const (
@ -229,7 +243,7 @@ const (
func TestIsInHomeDirTrue(t *testing.T) { func TestIsInHomeDirTrue(t *testing.T) {
home := homeBill home := homeBill
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("homeDir").Return(home) env.On("Home").Return(home)
path := &path{ path := &path{
env: env, env: env,
} }
@ -244,7 +258,7 @@ func TestIsInHomeDirLevelTrue(t *testing.T) {
pwd += levelDir pwd += levelDir
} }
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("homeDir").Return(home) env.On("Home").Return(home)
path := &path{ path := &path{
env: env, env: env,
} }
@ -273,14 +287,14 @@ func TestRootLocationHome(t *testing.T) {
} }
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("homeDir").Return(tc.HomePath) env.On("Home").Return(tc.HomePath)
env.On("pwd").Return(tc.Pwd) env.On("Pwd").Return(tc.Pwd)
args := &args{ args := &Args{
PSWD: &tc.Pswd, PSWD: &tc.Pswd,
} }
env.On("getArgs").Return(args) env.On("Args").Return(args)
env.On("getPathSeperator").Return(tc.PathSeperator) env.On("PathSeperator").Return(tc.PathSeperator)
env.On("getRuntimeGOOS").Return("") env.On("GOOS").Return("")
path := &path{ path := &path{
env: env, env: env,
props: properties{ props: properties{
@ -296,7 +310,7 @@ func TestRootLocationHome(t *testing.T) {
func TestIsInHomeDirFalse(t *testing.T) { func TestIsInHomeDirFalse(t *testing.T) {
home := homeBill home := homeBill
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("homeDir").Return(home) env.On("Home").Return(home)
path := &path{ path := &path{
env: env, env: env,
} }
@ -310,7 +324,7 @@ func TestPathDepthMultipleLevelsDeep(t *testing.T) {
pwd += levelDir pwd += levelDir
} }
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("getPathSeperator").Return("/") env.On("PathSeperator").Return("/")
env.On("getRunteGOOS").Return("") env.On("getRunteGOOS").Return("")
path := &path{ path := &path{
env: env, env: env,
@ -322,7 +336,7 @@ func TestPathDepthMultipleLevelsDeep(t *testing.T) {
func TestPathDepthZeroLevelsDeep(t *testing.T) { func TestPathDepthZeroLevelsDeep(t *testing.T) {
pwd := "/usr/" pwd := "/usr/"
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("getPathSeperator").Return("/") env.On("PathSeperator").Return("/")
path := &path{ path := &path{
env: env, env: env,
} }
@ -333,7 +347,7 @@ func TestPathDepthZeroLevelsDeep(t *testing.T) {
func TestPathDepthOneLevelDeep(t *testing.T) { func TestPathDepthOneLevelDeep(t *testing.T) {
pwd := "/usr/location" pwd := "/usr/location"
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("getPathSeperator").Return("/") env.On("PathSeperator").Return("/")
path := &path{ path := &path{
env: env, env: env,
} }
@ -424,28 +438,26 @@ func TestAgnosterPathStyles(t *testing.T) {
} }
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("getPathSeperator").Return(tc.PathSeperator) env.On("PathSeperator").Return(tc.PathSeperator)
env.On("homeDir").Return(tc.HomePath) env.On("Home").Return(tc.HomePath)
env.On("pwd").Return(tc.Pwd) env.On("Pwd").Return(tc.Pwd)
env.On("getRuntimeGOOS").Return(tc.GOOS) env.On("GOOS").Return(tc.GOOS)
env.On("stackCount").Return(0) env.On("StackCount").Return(0)
env.On("isWsl").Return(false) env.On("IsWsl").Return(false)
args := &args{ args := &Args{
PSWD: &tc.Pswd, PSWD: &tc.Pswd,
} }
env.On("getArgs").Return(args) env.On("Args").Return(args)
env.onTemplate()
path := &path{ path := &path{
env: env, env: env,
props: properties{ props: properties{
FolderSeparatorIcon: tc.FolderSeparatorIcon, FolderSeparatorIcon: tc.FolderSeparatorIcon,
Style: tc.Style, Style: tc.Style,
MaxDepth: tc.MaxDepth, MaxDepth: tc.MaxDepth,
SegmentTemplate: "{{ .Path }}",
}, },
} }
_ = path.enabled() _ = path.enabled()
got := path.string() got := renderTemplate(env, "{{ .Path }}", path)
assert.Equal(t, tc.Expected, got) assert.Equal(t, tc.Expected, got)
} }
} }
@ -547,23 +559,21 @@ func TestGetFullPath(t *testing.T) {
if len(tc.PathSeparator) == 0 { if len(tc.PathSeparator) == 0 {
tc.PathSeparator = "/" tc.PathSeparator = "/"
} }
env.On("getPathSeperator").Return(tc.PathSeparator) env.On("PathSeperator").Return(tc.PathSeparator)
env.On("homeDir").Return("/usr/home") env.On("Home").Return("/usr/home")
env.On("pwd").Return(tc.Pwd) env.On("Pwd").Return(tc.Pwd)
env.On("getRuntimeGOOS").Return(tc.GOOS) env.On("GOOS").Return(tc.GOOS)
env.On("stackCount").Return(tc.StackCount) env.On("StackCount").Return(tc.StackCount)
env.On("isWsl").Return(false) env.On("IsWsl").Return(false)
args := &args{ args := &Args{
PSWD: &tc.Pswd, PSWD: &tc.Pswd,
} }
env.On("getArgs").Return(args) env.On("Args").Return(args)
env.onTemplate()
if len(tc.Template) == 0 { if len(tc.Template) == 0 {
tc.Template = "{{ if gt .StackCount 0 }}{{ .StackCount }} {{ end }}{{ .Path }}" tc.Template = "{{ if gt .StackCount 0 }}{{ .StackCount }} {{ end }}{{ .Path }}"
} }
props := properties{ props := properties{
Style: tc.Style, Style: tc.Style,
SegmentTemplate: tc.Template,
} }
if tc.FolderSeparatorIcon != "" { if tc.FolderSeparatorIcon != "" {
props[FolderSeparatorIcon] = tc.FolderSeparatorIcon props[FolderSeparatorIcon] = tc.FolderSeparatorIcon
@ -576,7 +586,7 @@ func TestGetFullPath(t *testing.T) {
props: props, props: props,
} }
_ = path.enabled() _ = path.enabled()
got := path.string() got := renderTemplate(env, tc.Template, path)
assert.Equal(t, tc.Expected, got) assert.Equal(t, tc.Expected, got)
} }
} }
@ -600,14 +610,14 @@ func TestGetFullPathCustomMappedLocations(t *testing.T) {
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("getPathSeperator").Return("/") env.On("PathSeperator").Return("/")
env.On("homeDir").Return("/usr/home") env.On("Home").Return("/usr/home")
env.On("pwd").Return(tc.Pwd) env.On("Pwd").Return(tc.Pwd)
env.On("getRuntimeGOOS").Return("") env.On("GOOS").Return("")
args := &args{ args := &Args{
PSWD: &tc.Pwd, PSWD: &tc.Pwd,
} }
env.On("getArgs").Return(args) env.On("Args").Return(args)
path := &path{ path := &path{
env: env, env: env,
props: properties{ props: properties{
@ -638,8 +648,8 @@ func TestNormalizePath(t *testing.T) {
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("homeDir").Return("/usr/home") env.On("Home").Return("/usr/home")
env.On("getRuntimeGOOS").Return(tc.GOOS) env.On("GOOS").Return(tc.GOOS)
pt := &path{ pt := &path{
env: env, env: env,
} }
@ -651,14 +661,14 @@ func TestNormalizePath(t *testing.T) {
func TestGetFolderPathCustomMappedLocations(t *testing.T) { func TestGetFolderPathCustomMappedLocations(t *testing.T) {
pwd := "/a/b/c/d" pwd := "/a/b/c/d"
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("getPathSeperator").Return("/") env.On("PathSeperator").Return("/")
env.On("homeDir").Return("/usr/home") env.On("Home").Return("/usr/home")
env.On("pwd").Return(pwd) env.On("Pwd").Return(pwd)
env.On("getRuntimeGOOS").Return("") env.On("GOOS").Return("")
args := &args{ args := &Args{
PSWD: &pwd, PSWD: &pwd,
} }
env.On("getArgs").Return(args) env.On("Args").Return(args)
path := &path{ path := &path{
env: env, env: env,
props: properties{ props: properties{
@ -698,14 +708,14 @@ func TestAgnosterPath(t *testing.T) { // nolint:dupl
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("homeDir").Return(tc.Home) env.On("Home").Return(tc.Home)
env.On("getPathSeperator").Return(tc.PathSeparator) env.On("PathSeperator").Return(tc.PathSeparator)
env.On("pwd").Return(tc.PWD) env.On("Pwd").Return(tc.PWD)
env.On("getRuntimeGOOS").Return("") env.On("GOOS").Return("")
args := &args{ args := &Args{
PSWD: &tc.PWD, PSWD: &tc.PWD,
} }
env.On("getArgs").Return(args) env.On("Args").Return(args)
path := &path{ path := &path{
env: env, env: env,
props: properties{ props: properties{
@ -746,14 +756,14 @@ func TestAgnosterLeftPath(t *testing.T) { // nolint:dupl
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("homeDir").Return(tc.Home) env.On("Home").Return(tc.Home)
env.On("getPathSeperator").Return(tc.PathSeparator) env.On("PathSeperator").Return(tc.PathSeparator)
env.On("pwd").Return(tc.PWD) env.On("Pwd").Return(tc.PWD)
env.On("getRuntimeGOOS").Return("") env.On("GOOS").Return("")
args := &args{ args := &Args{
PSWD: &tc.PWD, PSWD: &tc.PWD,
} }
env.On("getArgs").Return(args) env.On("Args").Return(args)
path := &path{ path := &path{
env: env, env: env,
props: properties{ props: properties{
@ -794,14 +804,14 @@ func TestGetPwd(t *testing.T) {
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("getPathSeperator").Return("/") env.On("PathSeperator").Return("/")
env.On("homeDir").Return("/usr/home") env.On("Home").Return("/usr/home")
env.On("pwd").Return(tc.Pwd) env.On("Pwd").Return(tc.Pwd)
env.On("getRuntimeGOOS").Return("") env.On("GOOS").Return("")
args := &args{ args := &Args{
PSWD: &tc.Pswd, PSWD: &tc.Pswd,
} }
env.On("getArgs").Return(args) env.On("Args").Return(args)
path := &path{ path := &path{
env: env, env: env,
props: properties{ props: properties{

View file

@ -4,9 +4,8 @@ type php struct {
language language
} }
func (p *php) string() string { func (p *php) template() string {
segmentTemplate := p.language.props.getString(SegmentTemplate, "{{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }}") return languageTemplate
return p.language.string(segmentTemplate, p)
} }
func (p *php) init(props Properties, env Environment) { func (p *php) init(props Properties, env Environment) {

View file

@ -27,6 +27,6 @@ func TestPhp(t *testing.T) {
j := &php{} j := &php{}
j.init(props, env) j.init(props, env)
assert.True(t, j.enabled(), fmt.Sprintf("Failed in case: %s", tc.Case)) assert.True(t, j.enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
assert.Equal(t, tc.ExpectedString, j.string(), fmt.Sprintf("Failed in case: %s", tc.Case)) assert.Equal(t, tc.ExpectedString, renderTemplate(env, j.template(), j), fmt.Sprintf("Failed in case: %s", tc.Case))
} }
} }

View file

@ -39,21 +39,25 @@ func (p *plastic) init(props Properties, env Environment) {
p.env = env p.env = env
} }
func (p *plastic) template() string {
return "{{ .Selector }}"
}
func (p *plastic) enabled() bool { func (p *plastic) enabled() bool {
if !p.env.hasCommand("cm") { if !p.env.HasCommand("cm") {
return false return false
} }
wkdir, err := p.env.hasParentFilePath(".plastic") wkdir, err := p.env.HasParentFilePath(".plastic")
if err != nil { if err != nil {
return false return false
} }
if p.shouldIgnoreRootRepository(wkdir.parentFolder) { if p.shouldIgnoreRootRepository(wkdir.ParentFolder) {
return false return false
} }
if !wkdir.isDir { if !wkdir.IsDir {
return false return false
} }
p.plasticWorkspaceFolder = wkdir.parentFolder p.plasticWorkspaceFolder = wkdir.ParentFolder
displayStatus := p.props.getBool(FetchStatus, false) displayStatus := p.props.getBool(FetchStatus, false)
p.setSelector() p.setSelector()
if displayStatus { if displayStatus {
@ -62,20 +66,6 @@ func (p *plastic) enabled() bool {
return true return true
} }
func (p *plastic) string() string {
segmentTemplate := p.props.getString(SegmentTemplate, "{{ .Selector }}")
template := &textTemplate{
Template: segmentTemplate,
Context: p,
Env: p.env,
}
text, err := template.render()
if err != nil {
return err.Error()
}
return text
}
func (p *plastic) setPlasticStatus() { func (p *plastic) setPlasticStatus() {
output := p.getCmCommandOutput("status", "--all", "--machinereadable") output := p.getCmCommandOutput("status", "--all", "--machinereadable")
splittedOutput := strings.Split(output, "\n") splittedOutput := strings.Split(output, "\n")
@ -139,7 +129,7 @@ func (p *plastic) getHeadChangeset() int {
func (p *plastic) setSelector() { func (p *plastic) setSelector() {
var ref string var ref string
selector := p.getFileContents(p.plasticWorkspaceFolder+"/.plastic/", "plastic.selector") selector := p.FileContents(p.plasticWorkspaceFolder+"/.plastic/", "plastic.selector")
// changeset // changeset
ref = p.parseChangesetSelector(selector) ref = p.parseChangesetSelector(selector)
if len(ref) > 0 { if len(ref) > 0 {
@ -173,6 +163,6 @@ func (p *plastic) parseBranchSelector(selector string) string {
} }
func (p *plastic) getCmCommandOutput(args ...string) string { func (p *plastic) getCmCommandOutput(args ...string) string {
val, _ := p.env.runCommand("cm", args...) val, _ := p.env.RunCommand("cm", args...)
return val return val
} }

View file

@ -8,9 +8,9 @@ import (
func TestPlasticEnabledNotFound(t *testing.T) { func TestPlasticEnabledNotFound(t *testing.T) {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("hasCommand", "cm").Return(false) env.On("HasCommand", "cm").Return(false)
env.On("getRuntimeGOOS").Return("") env.On("GOOS").Return("")
env.On("isWsl").Return(false) env.On("IsWsl").Return(false)
p := &plastic{ p := &plastic{
scm: scm{ scm: scm{
env: env, env: env,
@ -22,16 +22,16 @@ func TestPlasticEnabledNotFound(t *testing.T) {
func TestPlasticEnabledInWorkspaceDirectory(t *testing.T) { func TestPlasticEnabledInWorkspaceDirectory(t *testing.T) {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("hasCommand", "cm").Return(true) env.On("HasCommand", "cm").Return(true)
env.On("getRuntimeGOOS").Return("") env.On("GOOS").Return("")
env.On("isWsl").Return(false) env.On("IsWsl").Return(false)
env.On("getFileContent", "/dir/.plastic//plastic.selector").Return("") env.On("FileContent", "/dir/.plastic//plastic.selector").Return("")
fileInfo := &fileInfo{ fileInfo := &FileInfo{
path: "/dir/hello", Path: "/dir/hello",
parentFolder: "/dir", ParentFolder: "/dir",
isDir: true, IsDir: true,
} }
env.On("hasParentFilePath", ".plastic").Return(fileInfo, nil) env.On("HasParentFilePath", ".plastic").Return(fileInfo, nil)
p := &plastic{ p := &plastic{
scm: scm{ scm: scm{
env: env, env: env,
@ -39,13 +39,13 @@ func TestPlasticEnabledInWorkspaceDirectory(t *testing.T) {
}, },
} }
assert.True(t, p.enabled()) assert.True(t, p.enabled())
assert.Equal(t, fileInfo.parentFolder, p.plasticWorkspaceFolder) assert.Equal(t, fileInfo.ParentFolder, p.plasticWorkspaceFolder)
} }
func setupCmStatusEnv(status, headStatus string) *plastic { func setupCmStatusEnv(status, headStatus string) *plastic {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("runCommand", "cm", []string{"status", "--all", "--machinereadable"}).Return(status, nil) env.On("RunCommand", "cm", []string{"status", "--all", "--machinereadable"}).Return(status, nil)
env.On("runCommand", "cm", []string{"status", "--head", "--machinereadable"}).Return(headStatus, nil) env.On("RunCommand", "cm", []string{"status", "--head", "--machinereadable"}).Return(headStatus, nil)
p := &plastic{ p := &plastic{
scm: scm{ scm: scm{
env: env, env: env,
@ -327,12 +327,10 @@ func TestPlasticTemplateString(t *testing.T) {
for _, tc := range cases { for _, tc := range cases {
props := properties{ props := properties{
FetchStatus: true, FetchStatus: true,
SegmentTemplate: tc.Template,
} }
tc.Plastic.props = props tc.Plastic.props = props
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.onTemplate()
tc.Plastic.env = env tc.Plastic.env = env
assert.Equal(t, tc.Expected, tc.Plastic.string(), tc.Case) assert.Equal(t, tc.Expected, renderTemplate(env, tc.Template, tc.Plastic), tc.Case)
} }
} }

View file

@ -13,24 +13,14 @@ const (
poshGitEnv = "POSH_GIT_STATUS" poshGitEnv = "POSH_GIT_STATUS"
) )
func (p *poshgit) enabled() bool { func (p *poshgit) template() string {
status := p.env.getenv(poshGitEnv) return "{{ .Status }}"
p.Status = strings.TrimSpace(status)
return p.Status != ""
} }
func (p *poshgit) string() string { func (p *poshgit) enabled() bool {
segmentTemplate := p.props.getString(SegmentTemplate, "{{ .Status }}") status := p.env.Getenv(poshGitEnv)
template := &textTemplate{ p.Status = strings.TrimSpace(status)
Template: segmentTemplate, return p.Status != ""
Context: p,
Env: p.env,
}
text, err := template.render()
if err != nil {
return err.Error()
}
return text
} }
func (p *poshgit) init(props Properties, env Environment) { func (p *poshgit) init(props Properties, env Environment) {

View file

@ -20,15 +20,14 @@ func TestPoshGitSegment(t *testing.T) {
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.onTemplate() env.On("Getenv", poshGitEnv).Return(tc.PoshGitPrompt)
env.On("getenv", poshGitEnv).Return(tc.PoshGitPrompt)
p := &poshgit{ p := &poshgit{
env: env, env: env,
props: &properties{}, props: &properties{},
} }
assert.Equal(t, tc.Enabled, p.enabled()) assert.Equal(t, tc.Enabled, p.enabled(), tc.Case)
if tc.Enabled { if tc.Enabled {
assert.Equal(t, tc.Expected, p.string()) assert.Equal(t, tc.Expected, renderTemplate(env, p.template(), p), tc.Case)
} }
} }
} }

View file

@ -11,9 +11,8 @@ const (
FetchVirtualEnv Property = "fetch_virtual_env" FetchVirtualEnv Property = "fetch_virtual_env"
) )
func (p *python) string() string { func (p *python) template() string {
segmentTemplate := p.language.props.getString(SegmentTemplate, "{{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }}") return languageTemplate
return p.language.string(segmentTemplate, p)
} }
func (p *python) init(props Properties, env Environment) { func (p *python) init(props Properties, env Environment) {
@ -57,7 +56,7 @@ func (p *python) loadContext() {
} }
var venv string var venv string
for _, venvVar := range venvVars { for _, venvVar := range venvVars {
venv = p.language.env.getenv(venvVar) venv = p.language.env.Getenv(venvVar)
name := base(venv, p.language.env) name := base(venv, p.language.env)
if p.canUseVenvName(name) { if p.canUseVenvName(name) {
p.Venv = name p.Venv = name

View file

@ -42,26 +42,27 @@ func TestPythonTemplate(t *testing.T) {
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("hasCommand", "python").Return(true) env.On("HasCommand", "python").Return(true)
env.On("runCommand", "python", []string{"--version"}).Return("Python 3.8.4", nil) env.On("RunCommand", "python", []string{"--version"}).Return("Python 3.8.4", nil)
env.On("hasFiles", "*.py").Return(true) env.On("HasFiles", "*.py").Return(true)
env.On("getenv", "VIRTUAL_ENV").Return(tc.VirtualEnvName) env.On("Getenv", "VIRTUAL_ENV").Return(tc.VirtualEnvName)
env.On("getenv", "CONDA_ENV_PATH").Return(tc.VirtualEnvName) env.On("Getenv", "CONDA_ENV_PATH").Return(tc.VirtualEnvName)
env.On("getenv", "CONDA_DEFAULT_ENV").Return(tc.VirtualEnvName) env.On("Getenv", "CONDA_DEFAULT_ENV").Return(tc.VirtualEnvName)
env.On("getenv", "PYENV_VERSION").Return(tc.VirtualEnvName) env.On("Getenv", "PYENV_VERSION").Return(tc.VirtualEnvName)
env.On("getPathSeperator").Return("") env.On("PathSeperator").Return("")
env.On("pwd").Return("/usr/home/project") env.On("Pwd").Return("/usr/home/project")
env.On("homeDir").Return("/usr/home") env.On("Home").Return("/usr/home")
env.onTemplate()
props := properties{ props := properties{
FetchVersion: tc.FetchVersion, FetchVersion: tc.FetchVersion,
SegmentTemplate: tc.Template,
DisplayMode: DisplayModeAlways, DisplayMode: DisplayModeAlways,
} }
env.On("TemplateCache").Return(&TemplateCache{
Env: make(map[string]string),
})
python := &python{} python := &python{}
python.init(props, env) python.init(props, env)
assert.Equal(t, !tc.ExpectedDisabled, python.enabled(), tc.Case) assert.Equal(t, !tc.ExpectedDisabled, python.enabled(), tc.Case)
assert.Equal(t, tc.Expected, python.string(), tc.Case) assert.Equal(t, tc.Expected, renderTemplate(env, tc.Template, python), tc.Case)
} }
} }
@ -76,11 +77,11 @@ func TestPythonPythonInContext(t *testing.T) {
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("getPathSeperator").Return("") env.On("PathSeperator").Return("")
env.On("getenv", "VIRTUAL_ENV").Return(tc.VirtualEnvName) env.On("Getenv", "VIRTUAL_ENV").Return(tc.VirtualEnvName)
env.On("getenv", "CONDA_ENV_PATH").Return("") env.On("Getenv", "CONDA_ENV_PATH").Return("")
env.On("getenv", "CONDA_DEFAULT_ENV").Return("") env.On("Getenv", "CONDA_DEFAULT_ENV").Return("")
env.On("getenv", "PYENV_VERSION").Return("") env.On("Getenv", "PYENV_VERSION").Return("")
python := &python{} python := &python{}
python.init(properties{}, env) python.init(properties{}, env)
python.loadContext() python.loadContext()

View file

@ -5,22 +5,12 @@ type root struct {
env Environment env Environment
} }
func (rt *root) enabled() bool { func (rt *root) template() string {
return rt.env.isRunningAsRoot() return "\uF0E7"
} }
func (rt *root) string() string { func (rt *root) enabled() bool {
segmentTemplate := rt.props.getString(SegmentTemplate, "\uF0E7") return rt.env.Root()
template := &textTemplate{
Template: segmentTemplate,
Context: rt,
Env: rt.env,
}
text, err := template.render()
if err != nil {
return err.Error()
}
return text
} }
func (rt *root) init(props Properties, env Environment) { func (rt *root) init(props Properties, env Environment) {

View file

@ -4,9 +4,8 @@ type ruby struct {
language language
} }
func (r *ruby) string() string { func (r *ruby) template() string {
segmentTemplate := r.language.props.getString(SegmentTemplate, "{{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }}") return languageTemplate
return r.language.string(segmentTemplate, r)
} }
func (r *ruby) init(props Properties, env Environment) { func (r *ruby) init(props Properties, env Environment) {

View file

@ -83,28 +83,27 @@ func TestRuby(t *testing.T) {
} }
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("hasCommand", "rbenv").Return(tc.HasRbenv) env.On("HasCommand", "rbenv").Return(tc.HasRbenv)
env.On("runCommand", "rbenv", []string{"version-name"}).Return(tc.Version, nil) env.On("RunCommand", "rbenv", []string{"version-name"}).Return(tc.Version, nil)
env.On("hasCommand", "rvm-prompt").Return(tc.HasRvmprompt) env.On("HasCommand", "rvm-prompt").Return(tc.HasRvmprompt)
env.On("runCommand", "rvm-prompt", []string{"i", "v", "g"}).Return(tc.Version, nil) env.On("RunCommand", "rvm-prompt", []string{"i", "v", "g"}).Return(tc.Version, nil)
env.On("hasCommand", "chruby").Return(tc.HasChruby) env.On("HasCommand", "chruby").Return(tc.HasChruby)
env.On("runCommand", "chruby", []string(nil)).Return(tc.Version, nil) env.On("RunCommand", "chruby", []string(nil)).Return(tc.Version, nil)
env.On("hasCommand", "asdf").Return(tc.HasAsdf) env.On("HasCommand", "asdf").Return(tc.HasAsdf)
env.On("runCommand", "asdf", []string{"current", "ruby"}).Return(tc.Version, nil) env.On("RunCommand", "asdf", []string{"current", "ruby"}).Return(tc.Version, nil)
env.On("hasCommand", "ruby").Return(tc.HasRuby) env.On("HasCommand", "ruby").Return(tc.HasRuby)
env.On("runCommand", "ruby", []string{"--version"}).Return(tc.Version, nil) env.On("RunCommand", "ruby", []string{"--version"}).Return(tc.Version, nil)
env.On("hasFiles", "*.rb").Return(tc.HasRubyFiles) env.On("HasFiles", "*.rb").Return(tc.HasRubyFiles)
env.On("hasFiles", "Rakefile").Return(tc.HasRakeFile) env.On("HasFiles", "Rakefile").Return(tc.HasRakeFile)
env.On("hasFiles", "Gemfile").Return(tc.HasGemFile) env.On("HasFiles", "Gemfile").Return(tc.HasGemFile)
env.On("pwd").Return("/usr/home/project") env.On("Pwd").Return("/usr/home/project")
env.On("homeDir").Return("/usr/home") env.On("Home").Return("/usr/home")
env.onTemplate()
props := properties{ props := properties{
FetchVersion: tc.FetchVersion, FetchVersion: tc.FetchVersion,
} }
ruby := &ruby{} ruby := &ruby{}
ruby.init(props, env) ruby.init(props, env)
assert.Equal(t, tc.ExpectedEnabled, ruby.enabled(), fmt.Sprintf("Failed in case: %s", tc.Case)) assert.Equal(t, tc.ExpectedEnabled, ruby.enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
assert.Equal(t, tc.ExpectedString, ruby.string(), fmt.Sprintf("Failed in case: %s", tc.Case)) assert.Equal(t, tc.ExpectedString, renderTemplate(env, ruby.template(), ruby), fmt.Sprintf("Failed in case: %s", tc.Case))
} }
} }

View file

@ -4,9 +4,8 @@ type rust struct {
language language
} }
func (r *rust) string() string { func (r *rust) template() string {
segmentTemplate := r.language.props.getString(SegmentTemplate, "{{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }}") return languageTemplate
return r.language.string(segmentTemplate, r)
} }
func (r *rust) init(props Properties, env Environment) { func (r *rust) init(props Properties, env Environment) {

View file

@ -26,6 +26,6 @@ func TestRust(t *testing.T) {
r := &rust{} r := &rust{}
r.init(props, env) r.init(props, env)
assert.True(t, r.enabled(), fmt.Sprintf("Failed in case: %s", tc.Case)) assert.True(t, r.enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
assert.Equal(t, tc.ExpectedString, r.string(), fmt.Sprintf("Failed in case: %s", tc.Case)) assert.Equal(t, tc.ExpectedString, renderTemplate(env, r.template(), r), fmt.Sprintf("Failed in case: %s", tc.Case))
} }
} }

View file

@ -16,18 +16,8 @@ func (s *session) enabled() bool {
return true return true
} }
func (s *session) string() string { func (s *session) template() string {
segmentTemplate := s.props.getString(SegmentTemplate, "{{ .UserName}}@{{ .HostName }}") return "{{ .UserName }}@{{ .HostName }}"
template := &textTemplate{
Template: segmentTemplate,
Context: s,
Env: s.env,
}
text, err := template.render()
if err != nil {
text = err.Error()
}
return text
} }
func (s *session) init(props Properties, env Environment) { func (s *session) init(props Properties, env Environment) {
@ -41,7 +31,7 @@ func (s *session) activeSSHSession() bool {
"SSH_CLIENT", "SSH_CLIENT",
} }
for _, key := range keys { for _, key := range keys {
content := s.env.getenv(key) content := s.env.Getenv(key)
if content != "" { if content != "" {
return true return true
} }

View file

@ -87,16 +87,16 @@ func TestSessionSegmentTemplate(t *testing.T) {
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("getCurrentUser").Return(tc.UserName) env.On("User").Return(tc.UserName)
env.On("getRuntimeGOOS").Return("burp") env.On("GOOS").Return("burp")
env.On("getHostName").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("templateCache").Return(&templateCache{ env.On("TemplateCache").Return(&TemplateCache{
UserName: tc.UserName, UserName: tc.UserName,
HostName: tc.ComputerName, HostName: tc.ComputerName,
Env: map[string]string{ Env: map[string]string{
@ -108,11 +108,9 @@ func TestSessionSegmentTemplate(t *testing.T) {
}) })
session := &session{ session := &session{
env: env, env: env,
props: properties{ props: properties{},
SegmentTemplate: tc.Template,
},
} }
_ = session.enabled() _ = session.enabled()
assert.Equal(t, tc.ExpectedString, session.string(), tc.Case) assert.Equal(t, tc.ExpectedString, renderTemplate(env, tc.Template, session), tc.Case)
} }
} }

View file

@ -14,9 +14,13 @@ const (
MappedShellNames Property = "mapped_shell_names" MappedShellNames Property = "mapped_shell_names"
) )
func (s *shell) template() string {
return "{{ .Name }}"
}
func (s *shell) enabled() bool { func (s *shell) enabled() bool {
mappedNames := s.props.getKeyValueMap(MappedShellNames, make(map[string]string)) mappedNames := s.props.getKeyValueMap(MappedShellNames, make(map[string]string))
s.Name = s.env.getShellName() s.Name = s.env.Shell()
for key, val := range mappedNames { for key, val := range mappedNames {
if strings.EqualFold(s.Name, key) { if strings.EqualFold(s.Name, key) {
s.Name = val s.Name = val
@ -26,20 +30,6 @@ func (s *shell) enabled() bool {
return true return true
} }
func (s *shell) string() string {
segmentTemplate := s.props.getString(SegmentTemplate, "{{.Name}}")
template := &textTemplate{
Template: segmentTemplate,
Context: s,
Env: s.env,
}
text, err := template.render()
if err != nil {
return err.Error()
}
return text
}
func (s *shell) init(props Properties, env Environment) { func (s *shell) init(props Properties, env Environment) {
s.props = props s.props = props
s.env = env s.env = env

View file

@ -9,14 +9,13 @@ import (
func TestWriteCurrentShell(t *testing.T) { func TestWriteCurrentShell(t *testing.T) {
expected := "zsh" expected := "zsh"
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("getShellName").Return(expected, nil) env.On("Shell").Return(expected, nil)
env.onTemplate()
s := &shell{ s := &shell{
env: env, env: env,
props: properties{}, props: properties{},
} }
_ = s.enabled() _ = s.enabled()
assert.Equal(t, expected, s.string()) assert.Equal(t, expected, renderTemplate(env, s.template(), s))
} }
func TestUseMappedShellNames(t *testing.T) { func TestUseMappedShellNames(t *testing.T) {
@ -30,8 +29,7 @@ func TestUseMappedShellNames(t *testing.T) {
} }
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("getShellName").Return(tc.Expected, nil) env.On("Shell").Return(tc.Expected, nil)
env.onTemplate()
s := &shell{ s := &shell{
env: env, env: env,
props: properties{ props: properties{
@ -39,7 +37,7 @@ func TestUseMappedShellNames(t *testing.T) {
}, },
} }
_ = s.enabled() _ = s.enabled()
got := s.string() got := renderTemplate(env, s.template(), s)
assert.Equal(t, tc.Expected, got) assert.Equal(t, tc.Expected, got)
} }
} }

View file

@ -27,19 +27,10 @@ const (
paused = "paused" paused = "paused"
) )
func (s *spotify) string() string { func (s *spotify) template() string {
segmentTemplate := s.props.getString(SegmentTemplate, "{{.Icon}}{{ if ne .Status \"stopped\"}}{{.Artist}} - {{.Track}}{{ end }}") return "{{ .Icon }}{{ if ne .Status \"stopped\" }}{{ .Artist }} - {{ .Track }}{{ end }}"
template := &textTemplate{
Template: segmentTemplate,
Context: s,
Env: s.env,
}
text, err := template.render()
if err != nil {
return err.Error()
}
return text
} }
func (s *spotify) resolveIcon() { func (s *spotify) resolveIcon() {
switch s.Status { switch s.Status {
case stopped: case stopped:

View file

@ -7,10 +7,12 @@ func (s *spotify) enabled() bool {
// Check if running // Check if running
running := s.runAppleScriptCommand("application \"Spotify\" is running") running := s.runAppleScriptCommand("application \"Spotify\" is running")
if running == "false" || running == "" { if running == "false" || running == "" {
s.Status = stopped
return false return false
} }
s.Status = s.runAppleScriptCommand("tell application \"Spotify\" to player state as string") s.Status = s.runAppleScriptCommand("tell application \"Spotify\" to player state as string")
if err != nil { if err != nil {
s.Status = stopped
return false return false
} }
if s.Status == stopped { if s.Status == stopped {
@ -23,6 +25,6 @@ func (s *spotify) enabled() bool {
} }
func (s *spotify) runAppleScriptCommand(command string) string { func (s *spotify) runAppleScriptCommand(command string) string {
val, _ := s.env.runCommand("osascript", "-e", command) val, _ := s.env.RunCommand("osascript", "-e", command)
return val return val
} }

View file

@ -3,61 +3,37 @@
package main package main
import ( import (
"errors"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
type spotifyArgs struct { func TestSpotifyDarwinEnabledAndSpotifyPlaying(t *testing.T) {
running string cases := []struct {
status string Running string
artist string Expected string
track string Status string
runError error Artist string
} Track string
Error error
func bootStrapSpotifyDarwinTest(args *spotifyArgs) *spotify { }{
{Running: "false", Expected: ""},
{Running: "false", Expected: "", Error: errors.New("oops")},
{Running: "true", Expected: "\ue602 Candlemass - Spellbreaker", Status: "playing", Artist: "Candlemass", Track: "Spellbreaker"},
{Running: "true", Expected: "\uF8E3 Candlemass - Spellbreaker", Status: "paused", Artist: "Candlemass", Track: "Spellbreaker"},
}
for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("runCommand", "osascript", []string{"-e", "application \"Spotify\" is running"}).Return(args.running, args.runError) env.On("RunCommand", "osascript", []string{"-e", "application \"Spotify\" is running"}).Return(tc.Running, tc.Error)
env.On("runCommand", "osascript", []string{"-e", "tell application \"Spotify\" to player state as string"}).Return(args.status, nil) env.On("RunCommand", "osascript", []string{"-e", "tell application \"Spotify\" to player state as string"}).Return(tc.Status, nil)
env.On("runCommand", "osascript", []string{"-e", "tell application \"Spotify\" to artist of current track as string"}).Return(args.artist, nil) env.On("RunCommand", "osascript", []string{"-e", "tell application \"Spotify\" to artist of current track as string"}).Return(tc.Artist, nil)
env.On("runCommand", "osascript", []string{"-e", "tell application \"Spotify\" to name of current track as string"}).Return(args.track, nil) env.On("RunCommand", "osascript", []string{"-e", "tell application \"Spotify\" to name of current track as string"}).Return(tc.Track, nil)
env.onTemplate()
s := &spotify{ s := &spotify{
env: env, env: env,
props: properties{}, props: properties{},
} }
return s assert.Equal(t, tc.Running == "true", s.enabled())
} assert.Equal(t, tc.Expected, renderTemplate(env, s.template(), s))
func TestSpotifyDarwinEnabledAndSpotifyNotRunning(t *testing.T) {
args := &spotifyArgs{
running: "false",
} }
s := bootStrapSpotifyDarwinTest(args)
assert.Equal(t, false, s.enabled())
}
func TestSpotifyDarwinEnabledAndSpotifyPlaying(t *testing.T) {
args := &spotifyArgs{
running: "true",
status: "playing",
artist: "Candlemass",
track: "Spellbreaker",
}
s := bootStrapSpotifyDarwinTest(args)
assert.Equal(t, true, s.enabled())
assert.Equal(t, "\ue602 Candlemass - Spellbreaker", s.string())
}
func TestSpotifyDarwinEnabledAndSpotifyPaused(t *testing.T) {
args := &spotifyArgs{
running: "true",
status: "paused",
artist: "Candlemass",
track: "Spellbreaker",
}
s := bootStrapSpotifyDarwinTest(args)
assert.Equal(t, true, s.enabled())
assert.Equal(t, "\uF8E3 Candlemass - Spellbreaker", s.string())
} }

View file

@ -9,7 +9,6 @@ import (
func TestSpotifyStringPlayingSong(t *testing.T) { func TestSpotifyStringPlayingSong(t *testing.T) {
expected := "\ue602 Candlemass - Spellbreaker" expected := "\ue602 Candlemass - Spellbreaker"
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.onTemplate()
s := &spotify{ s := &spotify{
MusicPlayer: MusicPlayer{ MusicPlayer: MusicPlayer{
Artist: "Candlemass", Artist: "Candlemass",
@ -20,13 +19,12 @@ func TestSpotifyStringPlayingSong(t *testing.T) {
props: properties{}, props: properties{},
env: env, env: env,
} }
assert.Equal(t, expected, s.string()) assert.Equal(t, expected, renderTemplate(env, s.template(), s))
} }
func TestSpotifyStringStoppedSong(t *testing.T) { func TestSpotifyStringStoppedSong(t *testing.T) {
expected := "\uf04d " expected := "\uf04d "
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.onTemplate()
s := &spotify{ s := &spotify{
MusicPlayer: MusicPlayer{ MusicPlayer: MusicPlayer{
Artist: "Candlemass", Artist: "Candlemass",
@ -37,5 +35,5 @@ func TestSpotifyStringStoppedSong(t *testing.T) {
props: properties{}, props: properties{},
env: env, env: env,
} }
assert.Equal(t, expected, s.string()) assert.Equal(t, expected, renderTemplate(env, s.template(), s))
} }

View file

@ -9,7 +9,7 @@ import (
func (s *spotify) enabled() bool { func (s *spotify) enabled() bool {
// search for spotify window to retrieve the title // search for spotify window to retrieve the title
// Can be either "Spotify xxx" or the song name "Candlemass - Spellbreaker" // Can be either "Spotify xxx" or the song name "Candlemass - Spellbreaker"
spotifyWindowTitle, err := s.env.getWindowTitle("spotify.exe", "^(Spotify.*)|(.*\\s-\\s.*)$") spotifyWindowTitle, err := s.env.WindowTitle("spotify.exe", "^(Spotify.*)|(.*\\s-\\s.*)$")
if err != nil { if err != nil {
return false return false
} }

View file

@ -16,7 +16,7 @@ type spotifyArgs struct {
func bootStrapSpotifyWindowsTest(args *spotifyArgs) *spotify { func bootStrapSpotifyWindowsTest(args *spotifyArgs) *spotify {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("getWindowTitle", "spotify.exe").Return(args.title, args.runError) env.On("WindowTitle", "spotify.exe").Return(args.title, args.runError)
env.onTemplate() env.onTemplate()
s := &spotify{ s := &spotify{
env: env, env: env,

View file

@ -8,10 +8,10 @@ import (
) )
func (s *spotify) enabled() bool { func (s *spotify) enabled() bool {
if !s.env.isWsl() { if !s.env.IsWsl() {
return false return false
} }
tlist, err := s.env.runCommand("tasklist.exe", "/V", "/FI", "Imagename eq Spotify.exe", "/FO", "CSV", "/NH") tlist, err := s.env.RunCommand("tasklist.exe", "/V", "/FI", "Imagename eq Spotify.exe", "/FO", "CSV", "/NH")
if err != nil || strings.HasPrefix(tlist, "INFO") { if err != nil || strings.HasPrefix(tlist, "INFO") {
return false return false
} }

View file

@ -52,8 +52,8 @@ func TestSpotifyWsl(t *testing.T) {
} }
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("isWsl").Return(true) env.On("IsWsl").Return(true)
env.On("runCommand", "tasklist.exe", []string{"/V", "/FI", "Imagename eq Spotify.exe", "/FO", "CSV", "/NH"}).Return(tc.ExecOutput, nil) env.On("RunCommand", "tasklist.exe", []string{"/V", "/FI", "Imagename eq Spotify.exe", "/FO", "CSV", "/NH"}).Return(tc.ExecOutput, nil)
env.onTemplate() env.onTemplate()
s := &spotify{ s := &spotify{
env: env, env: env,

View file

@ -68,6 +68,10 @@ func (a *AuthError) Error() string {
return a.message return a.message
} }
func (s *strava) template() string {
return "{{ if .Error }}{{ .Error }}{{ else }}{{ .Ago }}{{ end }}"
}
func (s *strava) enabled() bool { func (s *strava) enabled() bool {
data, err := s.getResult() data, err := s.getResult()
if err == nil { if err == nil {
@ -75,6 +79,7 @@ func (s *strava) enabled() bool {
s.Icon = s.getActivityIcon() s.Icon = s.getActivityIcon()
s.Hours = s.getHours() s.Hours = s.getHours()
s.Ago = s.getAgo() s.Ago = s.getAgo()
s.URL = fmt.Sprintf("https://www.strava.com/activities/%d", s.ID)
return true return true
} }
if _, s.Authenticate = err.(*AuthError); s.Authenticate { if _, s.Authenticate = err.(*AuthError); s.Authenticate {
@ -117,31 +122,13 @@ func (s *strava) getActivityIcon() string {
return s.props.getString(UnknownActivityIcon, "\ue213") return s.props.getString(UnknownActivityIcon, "\ue213")
} }
func (s *strava) string() string {
if s.Error != "" {
return s.Error
}
segmentTemplate := s.props.getString(SegmentTemplate, "{{ .Ago }}")
template := &textTemplate{
Template: segmentTemplate,
Context: s,
Env: s.env,
}
text, err := template.render()
if err != nil {
return err.Error()
}
s.URL = fmt.Sprintf("https://www.strava.com/activities/%d", s.ID)
return text
}
func (s *strava) getAccessToken() (string, error) { func (s *strava) getAccessToken() (string, error) {
// get directly from cache // get directly from cache
if acccessToken, OK := s.env.cache().get(StravaAccessToken); OK { if acccessToken, OK := s.env.Cache().Get(StravaAccessToken); OK {
return acccessToken, nil return acccessToken, nil
} }
// use cached refersh token to get new access token // use cached refersh token to get new access token
if refreshToken, OK := s.env.cache().get(StravaRefreshToken); OK { if refreshToken, OK := s.env.Cache().Get(StravaRefreshToken); OK {
if acccessToken, err := s.refreshToken(refreshToken); err == nil { if acccessToken, err := s.refreshToken(refreshToken); err == nil {
return acccessToken, nil return acccessToken, nil
} }
@ -176,8 +163,8 @@ func (s *strava) refreshToken(refreshToken string) (string, error) {
} }
} }
// add tokens to cache // add tokens to cache
s.env.cache().set(StravaAccessToken, tokens.AccessToken, tokens.ExpiresIn/60) s.env.Cache().Set(StravaAccessToken, tokens.AccessToken, tokens.ExpiresIn/60)
s.env.cache().set(StravaRefreshToken, tokens.RefreshToken, 2*525960) // it should never expire unless revoked, default to 2 year s.env.Cache().Set(StravaRefreshToken, tokens.RefreshToken, 2*525960) // it should never expire unless revoked, default to 2 year
return tokens.AccessToken, nil return tokens.AccessToken, nil
} }
@ -194,7 +181,7 @@ func (s *strava) getResult() (*StravaData, error) {
return result[0], nil return result[0], nil
} }
getCacheValue := func(key string) (*StravaData, error) { getCacheValue := func(key string) (*StravaData, error) {
val, found := s.env.cache().get(key) val, found := s.env.Cache().Get(key)
// we got something from the cache // we got something from the cache
if found { if found {
if data, err := parseSingleElement([]byte(val)); err == nil { if data, err := parseSingleElement([]byte(val)); err == nil {
@ -237,7 +224,7 @@ func (s *strava) getResult() (*StravaData, error) {
} }
if cacheTimeout > 0 { if cacheTimeout > 0 {
// persist new sugars in cache // persist new sugars in cache
s.env.cache().set(url, string(body), cacheTimeout) s.env.Cache().Set(url, string(body), cacheTimeout)
} }
return data, nil return data, nil
} }

View file

@ -142,23 +142,19 @@ func TestStravaSegment(t *testing.T) {
CacheTimeout: tc.CacheTimeout, CacheTimeout: tc.CacheTimeout,
} }
cache := &MockedCache{} cache := &MockedCache{}
cache.On("get", url).Return(tc.JSONResponse, !tc.CacheFoundFail) cache.On("Get", url).Return(tc.JSONResponse, !tc.CacheFoundFail)
cache.On("set", url, tc.JSONResponse, tc.CacheTimeout).Return() cache.On("Set", url, tc.JSONResponse, tc.CacheTimeout).Return()
cache.On("get", StravaAccessToken).Return(tc.AccessToken, !tc.AccessTokenCacheFoundFail) cache.On("Get", StravaAccessToken).Return(tc.AccessToken, !tc.AccessTokenCacheFoundFail)
cache.On("get", StravaRefreshToken).Return(tc.RefreshToken, !tc.RefreshTokenCacheFoundFail) cache.On("Get", StravaRefreshToken).Return(tc.RefreshToken, !tc.RefreshTokenCacheFoundFail)
cache.On("set", StravaRefreshToken, "NEW_REFRESHTOKEN", 2*525960) cache.On("Set", StravaRefreshToken, "NEW_REFRESHTOKEN", 2*525960)
cache.On("set", StravaAccessToken, "NEW_ACCESSTOKEN", 20) cache.On("Set", StravaAccessToken, "NEW_ACCESSTOKEN", 20)
env.On("HTTPRequest", url).Return([]byte(tc.JSONResponse), tc.Error) env.On("HTTPRequest", url).Return([]byte(tc.JSONResponse), tc.Error)
env.On("HTTPRequest", tokenURL).Return([]byte(tc.TokenResponse), tc.Error) env.On("HTTPRequest", tokenURL).Return([]byte(tc.TokenResponse), tc.Error)
env.On("cache").Return(cache) env.On("Cache").Return(cache)
env.onTemplate()
if tc.Template != "" {
props[SegmentTemplate] = tc.Template
}
if tc.InitialAccessToken != "" { if tc.InitialAccessToken != "" {
props[AccessToken] = tc.InitialAccessToken props[AccessToken] = tc.InitialAccessToken
} }
@ -192,8 +188,11 @@ func TestStravaSegment(t *testing.T) {
continue continue
} }
var a = ns.string() if tc.Template == "" {
tc.Template = ns.template()
}
var got = renderTemplate(env, tc.Template, ns)
assert.Equal(t, tc.ExpectedString, a, tc.Case) assert.Equal(t, tc.ExpectedString, got, tc.Case)
} }
} }

View file

@ -31,6 +31,10 @@ const (
Precision Property = "precision" Precision Property = "precision"
) )
func (s *sysinfo) template() string {
return "{{ round .PhysicalPercentUsed .Precision }}"
}
func (s *sysinfo) enabled() bool { func (s *sysinfo) enabled() bool {
if s.PhysicalPercentUsed == 0 && s.SwapPercentUsed == 0 { if s.PhysicalPercentUsed == 0 && s.SwapPercentUsed == 0 {
return false return false
@ -38,21 +42,6 @@ func (s *sysinfo) enabled() bool {
return true return true
} }
func (s *sysinfo) string() string {
// keep old memory segment template
segmentTemplate := s.props.getString(SegmentTemplate, "{{ round .PhysicalPercentUsed .Precision }}")
template := &textTemplate{
Template: segmentTemplate,
Context: s,
Env: s.env,
}
text, err := template.render()
if err != nil {
return err.Error()
}
return text
}
func (s *sysinfo) init(props Properties, env Environment) { func (s *sysinfo) init(props Properties, env Environment) {
s.props = props s.props = props
s.env = env s.env = env

View file

@ -50,17 +50,15 @@ func TestSysInfo(t *testing.T) {
for _, tc := range cases { for _, tc := range cases {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.onTemplate()
tc.SysInfo.env = env tc.SysInfo.env = env
tc.SysInfo.props = properties{ tc.SysInfo.props = properties{
Precision: tc.Precision, Precision: tc.Precision,
SegmentTemplate: tc.Template,
} }
enabled := tc.SysInfo.enabled() enabled := tc.SysInfo.enabled()
if tc.ExpectDisabled { if tc.ExpectDisabled {
assert.Equal(t, false, enabled, tc.Case) assert.Equal(t, false, enabled, tc.Case)
} else { } else {
assert.Equal(t, tc.ExpectedString, tc.SysInfo.string(), tc.Case) assert.Equal(t, tc.ExpectedString, renderTemplate(env, tc.Template, tc.SysInfo), tc.Case)
} }
} }
} }

View file

@ -6,18 +6,8 @@ type terraform struct {
WorkspaceName string WorkspaceName string
} }
func (tf *terraform) string() string { func (tf *terraform) template() string {
segmentTemplate := tf.props.getString(SegmentTemplate, "{{.WorkspaceName}}") return "{{ .WorkspaceName }}"
template := &textTemplate{
Template: segmentTemplate,
Context: tf,
Env: tf.env,
}
text, err := template.render()
if err != nil {
return err.Error()
}
return text
} }
func (tf *terraform) init(props Properties, env Environment) { func (tf *terraform) init(props Properties, env Environment) {
@ -27,9 +17,9 @@ func (tf *terraform) init(props Properties, env Environment) {
func (tf *terraform) enabled() bool { func (tf *terraform) enabled() bool {
cmd := "terraform" cmd := "terraform"
if !tf.env.hasCommand(cmd) || !tf.env.hasFolder(tf.env.pwd()+"/.terraform") { if !tf.env.HasCommand(cmd) || !tf.env.HasFolder(tf.env.Pwd()+"/.terraform") {
return false return false
} }
tf.WorkspaceName, _ = tf.env.runCommand(cmd, "workspace", "show") tf.WorkspaceName, _ = tf.env.RunCommand(cmd, "workspace", "show")
return true return true
} }

View file

@ -14,11 +14,10 @@ type terraformArgs struct {
func bootStrapTerraformTest(args *terraformArgs) *terraform { func bootStrapTerraformTest(args *terraformArgs) *terraform {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("hasCommand", "terraform").Return(args.hasTfCommand) env.On("HasCommand", "terraform").Return(args.hasTfCommand)
env.On("hasFolder", "/.terraform").Return(args.hasTfFolder) env.On("HasFolder", "/.terraform").Return(args.hasTfFolder)
env.On("pwd").Return("") env.On("Pwd").Return("")
env.On("runCommand", "terraform", []string{"workspace", "show"}).Return(args.workspaceName, nil) env.On("RunCommand", "terraform", []string{"workspace", "show"}).Return(args.workspaceName, nil)
env.onTemplate()
k := &terraform{ k := &terraform{
env: env, env: env,
props: properties{}, props: properties{},
@ -62,5 +61,4 @@ func TestTerraformEnabled(t *testing.T) {
} }
terraform := bootStrapTerraformTest(args) terraform := bootStrapTerraformTest(args)
assert.True(t, terraform.enabled()) assert.True(t, terraform.enabled())
assert.Equal(t, expected, terraform.string())
} }

Some files were not shown because too many files have changed in this diff Show more