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
// environment and configuration.
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)
}

View file

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

View file

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

View file

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

View file

@ -35,7 +35,7 @@ func (e *engine) string() string {
func (e *engine) canWriteRPrompt() bool {
prompt := e.string()
consoleWidth, err := e.env.getTerminalWidth()
consoleWidth, err := e.env.TerminalWidth()
if err != nil || consoleWidth == 0 {
return true
}
@ -66,7 +66,7 @@ func (e *engine) render() string {
if !e.config.OSC99 {
return e.print()
}
cwd := e.env.pwd()
cwd := e.env.Pwd()
e.writeANSI(e.ansi.consolePwd(cwd))
return e.print()
}
@ -74,7 +74,7 @@ func (e *engine) render() string {
func (e *engine) renderBlock(block *Block) {
// when in bash, for rprompt blocks we need to write plain
// 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)
} else {
block.init(e.env, e.writer, e.ansi)
@ -107,7 +107,7 @@ func (e *engine) renderBlock(block *Block) {
}
case RPrompt:
blockText := block.renderSegments()
if e.env.getShellName() == bash {
if e.env.Shell() == bash {
blockText = fmt.Sprintf(e.ansi.bashFormat, 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("\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(e.env.logs())
e.write(e.env.Logs())
return e.string()
}
func (e *engine) print() string {
switch e.env.getShellName() {
switch e.env.Shell() {
case zsh:
if !*e.env.getArgs().Eval {
if !*e.env.Args().Eval {
break
}
// escape double quotes contained in the prompt
@ -214,7 +214,7 @@ func (e *engine) renderTooltip(tip string) string {
Alignment: Right,
Segments: []*Segment{tooltip},
}
switch e.env.getShellName() {
switch e.env.Shell() {
case zsh, winCMD:
block.init(e.env, e.writer, e.ansi)
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.write(e.config.TransientPrompt.Background, e.config.TransientPrompt.Foreground, prompt)
switch e.env.getShellName() {
switch e.env.Shell() {
case zsh:
// escape double quotes contained in the prompt
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 {
env := new(MockedEnvironment)
env.On("getTerminalWidth").Return(tc.TerminalWidth, tc.TerminalWidthError)
env.On("TerminalWidth").Return(tc.TerminalWidth, tc.TerminalWidthError)
ansi := &ansiUtils{}
ansi.init(plain)
engine := &engine{
@ -73,7 +73,7 @@ func engineRender(configPath string) error {
execTime = 917.0
)
args := &args{
args := &Args{
Debug: &debug,
Config: &configPath,
Eval: &eval,
@ -87,13 +87,13 @@ func engineRender(configPath string) error {
env := &environment{}
env.init(args)
defer env.close()
defer env.Close()
cfg := GetConfig(env)
defer testClearDefaultConfig()
ansi := &ansiUtils{}
ansi.init(env.getShellName())
ansi.init(env.Shell())
writerColors := MakeColors(env, cfg)
writer := &AnsiWriter{
ansi: ansi,

View file

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

View file

@ -21,7 +21,7 @@ type fileCache struct {
cachePath string
}
func (fc *fileCache) init(cachePath string) {
func (fc *fileCache) Init(cachePath string) {
fc.cache = newConcurrentMap()
fc.cachePath = cachePath
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()
if len(cache) == 0 {
return
@ -51,7 +51,7 @@ func (fc *fileCache) close() {
// returns the value for the given key as long as
// 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)
if !found {
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)
func (fc *fileCache) set(key, value string, ttl int) {
func (fc *fileCache) Set(key, value string, ttl int) {
fc.cache.set(key, &cacheObject{
Value: value,
Timestamp: time.Now().Unix(),

View file

@ -8,12 +8,12 @@ type MockedCache struct {
}
// close provides a mock function with given fields:
func (_m *MockedCache) close() {
func (_m *MockedCache) Close() {
_m.Called()
}
// 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)
var r0 string
@ -34,11 +34,11 @@ func (_m *MockedCache) get(key string) (string, bool) {
}
// init provides a mock function with given fields: home
func (_m *MockedCache) init(home string) {
func (_m *MockedCache) Init(home string) {
_m.Called(home)
}
// 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)
}

View file

@ -37,10 +37,10 @@ func TestWindowsPathWithDriveLetter(t *testing.T) {
}
for _, tc := range cases {
env := &environment{
args: &args{
args: &Args{
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"
)
func (env *environment) isRunningAsRoot() bool {
defer env.trace(time.Now(), "isRunningAsRoot")
func (env *environment) Root() bool {
defer env.trace(time.Now(), "Root")
return os.Geteuid() == 0
}
func (env *environment) homeDir() string {
func (env *environment) Home() string {
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")
}
func (env *environment) isWsl() bool {
defer env.trace(time.Now(), "isWsl")
func (env *environment) IsWsl() bool {
defer env.trace(time.Now(), "IsWsl")
// one way to check
// version := env.getFileContent("/proc/version")
// version := env.FileContent("/proc/version")
// return strings.Contains(version, "microsoft")
// using env variable
return env.getenv("WSL_DISTRO_NAME") != ""
return env.Getenv("WSL_DISTRO_NAME") != ""
}
func (env *environment) isWsl2() bool {
defer env.trace(time.Now(), "isWsl2")
if !env.isWsl() {
func (env *environment) IsWsl2() bool {
defer env.trace(time.Now(), "IsWsl2")
if !env.IsWsl() {
return false
}
uname := env.getFileContent("/proc/sys/kernel/osrelease")
uname := env.FileContent("/proc/sys/kernel/osrelease")
return strings.Contains(uname, "WSL2")
}
func (env *environment) getTerminalWidth() (int, error) {
defer env.trace(time.Now(), "getTerminalWidth")
func (env *environment) TerminalWidth() (int, error) {
defer env.trace(time.Now(), "TerminalWidth")
width, err := terminal.Width()
if err != nil {
env.log(Error, "runCommand", err.Error())
env.log(Error, "RunCommand", err.Error())
}
return int(width), err
}
func (env *environment) getPlatform() string {
func (env *environment) Platform() string {
const key = "environment_platform"
if val, found := env.cache().get(key); found {
if val, found := env.Cache().Get(key); found {
return val
}
var platform string
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)
return platform
}
@ -69,43 +69,43 @@ func (env *environment) getPlatform() string {
return platform
}
func (env *environment) getCachePath() string {
defer env.trace(time.Now(), "getCachePath")
func (env *environment) CachePath() string {
defer env.trace(time.Now(), "CachePath")
// 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
}
// HOME cache folder
if cachePath := returnOrBuildCachePath(env.homeDir() + "/.cache"); len(cachePath) != 0 {
if cachePath := returnOrBuildCachePath(env.Home() + "/.cache"); len(cachePath) != 0 {
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")
}
func (env *environment) inWSLSharedDrive() bool {
return env.isWsl() && strings.HasPrefix(env.pwd(), "/mnt/")
func (env *environment) InWSLSharedDrive() bool {
return env.IsWsl() && strings.HasPrefix(env.Pwd(), "/mnt/")
}
func (env *environment) convertToWindowsPath(path string) string {
windowsPath, err := env.runCommand("wslpath", "-w", path)
func (env *environment) ConvertToWindowsPath(path string) string {
windowsPath, err := env.RunCommand("wslpath", "-w", path)
if err == nil {
return windowsPath
}
return path
}
func (env *environment) convertToLinuxPath(path string) string {
linuxPath, err := env.runCommand("wslpath", "-u", path)
func (env *environment) ConvertToLinuxPath(path string) string {
linuxPath, err := env.RunCommand("wslpath", "-u", path)
if err == nil {
return linuxPath
}
return path
}
func (env *environment) getWifiNetwork() (*wifiInfo, error) {
func (env *environment) WifiNetwork() (*WifiInfo, error) {
return nil, errors.New("not implemented")
}

View file

@ -16,8 +16,8 @@ import (
"golang.org/x/sys/windows"
)
func (env *environment) isRunningAsRoot() bool {
defer env.trace(time.Now(), "isRunningAsRoot")
func (env *environment) Root() bool {
defer env.trace(time.Now(), "Root")
var sid *windows.SID
// 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,
&sid)
if err != nil {
env.log(Error, "isRunningAsRoot", err.Error())
env.log(Error, "Root", err.Error())
return false
}
defer func() {
@ -46,17 +46,17 @@ func (env *environment) isRunningAsRoot() bool {
member, err := token.IsMember(sid)
if err != nil {
env.log(Error, "isRunningAsRoot", err.Error())
env.log(Error, "Root", err.Error())
return false
}
return member
}
func (env *environment) homeDir() string {
func (env *environment) Home() string {
home := os.Getenv("HOME")
defer func() {
env.log(Debug, "homeDir", home)
env.log(Debug, "Home", home)
}()
if len(home) > 0 {
return home
@ -69,48 +69,48 @@ func (env *environment) homeDir() string {
return home
}
func (env *environment) getWindowTitle(imageName, windowTitleRegex string) (string, error) {
defer env.trace(time.Now(), "getWindowTitle", imageName, windowTitleRegex)
return getWindowTitle(imageName, windowTitleRegex)
func (env *environment) WindowTitle(imageName, windowTitleRegex string) (string, error) {
defer env.trace(time.Now(), "WindowTitle", imageName, windowTitleRegex)
return WindowTitle(imageName, windowTitleRegex)
}
func (env *environment) isWsl() bool {
defer env.trace(time.Now(), "isWsl")
func (env *environment) IsWsl() bool {
defer env.trace(time.Now(), "IsWsl")
return false
}
func (env *environment) isWsl2() bool {
defer env.trace(time.Now(), "isWsl2")
func (env *environment) IsWsl2() bool {
defer env.trace(time.Now(), "IsWsl2")
return false
}
func (env *environment) getTerminalWidth() (int, error) {
defer env.trace(time.Now(), "getTerminalWidth")
func (env *environment) TerminalWidth() (int, error) {
defer env.trace(time.Now(), "TerminalWidth")
handle, err := syscall.Open("CONOUT$", syscall.O_RDWR, 0)
if err != nil {
env.log(Error, "getTerminalWidth", err.Error())
env.log(Error, "TerminalWidth", err.Error())
return 0, err
}
info, err := winterm.GetConsoleScreenBufferInfo(uintptr(handle))
if err != nil {
env.log(Error, "getTerminalWidth", err.Error())
env.log(Error, "TerminalWidth", err.Error())
return 0, err
}
// return int(float64(info.Size.X) * 0.57), nil
return int(info.Size.X), nil
}
func (env *environment) getPlatform() string {
func (env *environment) Platform() string {
return windowsPlatform
}
func (env *environment) getCachePath() string {
defer env.trace(time.Now(), "getCachePath")
func (env *environment) CachePath() string {
defer env.trace(time.Now(), "CachePath")
// 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 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.
//
func (env *environment) getWindowsRegistryKeyValue(path string) (*windowsRegistryValue, error) {
env.trace(time.Now(), "getWindowsRegistryKeyValue", path)
func (env *environment) WindowsRegistryKeyValue(path string) (*windowsRegistryValue, error) {
env.trace(time.Now(), "WindowsRegistryKeyValue", path)
// Format:
// "HKLM\Software\Microsoft\Windows NT\CurrentVersion\EditionID"
@ -142,14 +142,14 @@ func (env *environment) getWindowsRegistryKeyValue(path string) (*windowsRegistr
if len(regPathParts) < 2 {
errorLogMsg := fmt.Sprintf("Error, malformed registry path: '%s'", path)
env.log(Error, "getWindowsRegistryKeyValue", errorLogMsg)
env.log(Error, "WindowsRegistryKeyValue", errorLogMsg)
return nil, errors.New(errorLogMsg)
}
regRootHKeyHandle := getHKEYHandleFromAbbrString(regPathParts[0])
if regRootHKeyHandle == 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)
}
@ -158,7 +158,7 @@ func (env *environment) getWindowsRegistryKeyValue(path string) (*windowsRegistr
if lastSlash < 0 {
errorLogMsg := fmt.Sprintf("Error, malformed registry path: '%s'", path)
env.log(Error, "getWindowsRegistryKeyValue", errorLogMsg)
env.log(Error, "WindowsRegistryKeyValue", errorLogMsg)
return nil, errors.New(errorLogMsg)
}
@ -170,13 +170,13 @@ func (env *environment) getWindowsRegistryKeyValue(path string) (*windowsRegistr
if len(regKeyLogged) == 0 {
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
regPathUTF16, err := windows.UTF16FromString(regPath)
if err != nil {
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)
}
@ -185,14 +185,14 @@ func (env *environment) getWindowsRegistryKeyValue(path string) (*windowsRegistr
regOpenErr := windows.RegOpenKeyEx(regRootHKeyHandle, &regPathUTF16[0], 0, windows.KEY_READ, &hKeyHandle)
if regOpenErr != nil {
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)
}
// Success - from here on out, when returning make sure to close that reg key with a deferred call to close:
defer func() {
err := windows.RegCloseKey(hKeyHandle)
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)
if err != nil {
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)
}
@ -211,7 +211,7 @@ func (env *environment) getWindowsRegistryKeyValue(path string) (*windowsRegistr
regQueryErr := windows.RegQueryValueEx(hKeyHandle, &regKeyUTF16[0], nil, &keyBufType, nil, &keyBufSize)
if regQueryErr != nil {
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)
}
@ -221,7 +221,7 @@ func (env *environment) getWindowsRegistryKeyValue(path string) (*windowsRegistr
regQueryErr = windows.RegQueryValueEx(hKeyHandle, &regKeyUTF16[0], nil, &keyBufType, &keyBuf[0], &keyBufSize)
if regQueryErr != nil {
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)
}
@ -232,20 +232,20 @@ func (env *environment) getWindowsRegistryKeyValue(path string) (*windowsRegistr
uint16p = (*uint16)(unsafe.Pointer(&keyBuf[0])) // nasty casty
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
case windows.REG_DWORD:
var uint32p *uint32
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
case windows.REG_QWORD:
var uint64p *uint64
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
default:
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
}
func (env *environment) convertToWindowsPath(path string) string {
func (env *environment) ConvertToWindowsPath(path string) string {
return path
}
func (env *environment) convertToLinuxPath(path string) string {
func (env *environment) ConvertToLinuxPath(path string) string {
return path
}
@ -273,8 +273,8 @@ var (
hWlanQueryInterface = hapi.NewProc("WlanQueryInterface")
)
func (env *environment) getWifiNetwork() (*wifiInfo, error) {
env.trace(time.Now(), "getWifiNetwork")
func (env *environment) WifiNetwork() (*wifiInfo, error) {
env.trace(time.Now(), "WifiNetwork")
// Open handle
var pdwNegotiatedVersion uint32
var phClientHandle uint32

View file

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

View file

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

View file

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

View file

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

View file

@ -32,8 +32,8 @@ func TestDirMatchesOneOf(t *testing.T) {
for _, tc := range cases {
env := new(MockedEnvironment)
env.On("getRuntimeGOOS").Return(tc.GOOS)
env.On("homeDir").Return(tc.HomeDir)
env.On("GOOS").Return(tc.GOOS)
env.On("Home").Return(tc.HomeDir)
got := dirMatchesOneOf(env, tc.Dir, []string{tc.Pattern})
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)
}
func (s *scm) getFileContents(folder, file string) string {
return strings.Trim(s.env.getFileContent(folder+"/"+file), " \r\n")
func (s *scm) FileContents(folder, file string) string {
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.On("homeDir").Return("/home/bill")
env.On("getRuntimeGOOS").Return(windowsPlatform)
env.On("Home").Return("/home/bill")
env.On("GOOS").Return(windowsPlatform)
s := &scm{
props: props,
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
type SegmentWriter interface {
enabled() bool
string() string
template() string
init(props Properties, env Environment)
}
@ -156,7 +156,16 @@ const (
)
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 {
@ -191,7 +200,7 @@ func (segment *Segment) cwdIncluded() bool {
return true
}
return dirMatchesOneOf(segment.env, segment.env.pwd(), list)
return dirMatchesOneOf(segment.env, segment.env.Pwd(), list)
}
func (segment *Segment) cwdExcluded() bool {
@ -200,7 +209,7 @@ func (segment *Segment) cwdExcluded() bool {
value = segment.Properties[IgnoreFolders]
}
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 {

View file

@ -9,9 +9,8 @@ type angular struct {
language
}
func (a *angular) string() string {
segmentTemplate := a.language.props.getString(SegmentTemplate, "{{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }}")
return a.language.string(segmentTemplate, a)
func (a *angular) template() string {
return languageTemplate
}
func (a *angular) init(props Properties, env Environment) {
@ -25,13 +24,13 @@ func (a *angular) init(props Properties, env Environment) {
getVersion: func() (string, error) {
const fileName string = "package.json"
const fileFolder string = "/node_modules/@angular/core"
angularFilePath := a.language.env.pwd() + fileFolder
if !a.language.env.hasFilesInDir(angularFilePath, fileName) {
angularFilePath := a.language.env.Pwd() + fileFolder
if !a.language.env.HasFilesInDir(angularFilePath, fileName) {
return "", fmt.Errorf("%s not found in %s", fileName, angularFilePath)
}
// parse file
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)
if err != nil {
return "", err

View file

@ -9,12 +9,12 @@ import (
func TestAngularCliVersionDisplayed(t *testing.T) {
cases := []struct {
Case string
ExpectedString string
Version string
Case string
FullVersion string
Version string
}{
{Case: "Angular 13.0.3", ExpectedString: "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 13.0.3", FullVersion: "13.0.3", Version: "{ \"name\": \"@angular/core\",\"version\": \"13.0.3\"}"},
{Case: "Angular 11.0.1", FullVersion: "11.0.1", Version: "{ \"name\": \"@angular/core\",\"version\": \"11.0.1\"}"},
}
for _, ta := range cases {
@ -24,16 +24,18 @@ func TestAngularCliVersionDisplayed(t *testing.T) {
var env = new(MockedEnvironment)
// mock getVersion methods
env.On("pwd").Return("/usr/home/dev/my-app")
env.On("homeDir").Return("/usr/home")
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("getFileContent", "/usr/home/dev/my-app/node_modules/@angular/core/package.json").Return(ta.Version)
env.onTemplate()
env.On("Pwd").Return("/usr/home/dev/my-app")
env.On("Home").Return("/usr/home")
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("FileContent", "/usr/home/dev/my-app/node_modules/@angular/core/package.json").Return(ta.Version)
env.On("TemplateCache").Return(&TemplateCache{
Env: make(map[string]string),
})
props := properties{}
angular := &angular{}
angular.init(props, env)
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"
)
func (a *aws) template() string {
return "{{ .Profile }}{{ if .Region }}@{{ .Region }}{{ end }}"
}
func (a *aws) init(props Properties, env Environment) {
a.props = props
a.env = env
@ -24,7 +28,7 @@ func (a *aws) init(props Properties, env Environment) {
func (a *aws) enabled() bool {
getEnvFirstMatch := func(envs ...string) string {
for _, env := range envs {
value := a.env.getenv(env)
value := a.env.Getenv(env)
if value != "" {
return value
}
@ -52,11 +56,11 @@ func (a *aws) enabled() bool {
}
func (a *aws) getConfigFileInfo() {
configPath := a.env.getenv("AWS_CONFIG_FILE")
configPath := a.env.Getenv("AWS_CONFIG_FILE")
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]"
if a.Profile != "" {
configSection = fmt.Sprintf("[profile %s]", a.Profile)
@ -80,17 +84,3 @@ func (a *aws) getConfigFileInfo() {
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 {
env := new(MockedEnvironment)
env.On("getenv", "AWS_VAULT").Return(tc.Vault)
env.On("getenv", "AWS_PROFILE").Return(tc.Profile)
env.On("getenv", "AWS_REGION").Return(tc.Region)
env.On("getenv", "AWS_DEFAULT_REGION").Return(tc.DefaultRegion)
env.On("getenv", "AWS_CONFIG_FILE").Return(tc.ConfigFile)
env.On("getFileContent", "/usr/home/.aws/config").Return("")
env.On("homeDir").Return("/usr/home")
env.onTemplate()
env.On("Getenv", "AWS_VAULT").Return(tc.Vault)
env.On("Getenv", "AWS_PROFILE").Return(tc.Profile)
env.On("Getenv", "AWS_REGION").Return(tc.Region)
env.On("Getenv", "AWS_DEFAULT_REGION").Return(tc.DefaultRegion)
env.On("Getenv", "AWS_CONFIG_FILE").Return(tc.ConfigFile)
env.On("FileContent", "/usr/home/.aws/config").Return("")
env.On("Home").Return("/usr/home")
props := properties{
DisplayDefault: tc.DisplayDefault,
}
if tc.Template != "" {
props[SegmentTemplate] = tc.Template
}
aws := &aws{
env: env,
props: props,
}
if tc.Template == "" {
tc.Template = aws.template()
}
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"`
}
func (a *az) string() string {
segmentTemplate := a.props.getString(SegmentTemplate, "{{ .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) template() string {
return "{{ .Name }}"
}
func (a *az) init(props Properties, env Environment) {
@ -101,16 +91,16 @@ func (a *az) enabled() bool {
return a.getAzureProfile() || a.getAzureRmContext()
}
func (a *az) getFileContentWithoutBom(file string) string {
config := a.env.getFileContent(file)
func (a *az) FileContentWithoutBom(file string) string {
config := a.env.FileContent(file)
const ByteOrderMark = "\ufeff"
return strings.TrimLeft(config, ByteOrderMark)
}
func (a *az) getAzureProfile() bool {
var content string
profile := filepath.Join(a.env.homeDir(), ".azure", "azureProfile.json")
if content = a.getFileContentWithoutBom(profile); len(content) == 0 {
profile := filepath.Join(a.env.Home(), ".azure", "azureProfile.json")
if content = a.FileContentWithoutBom(profile); len(content) == 0 {
return false
}
var config AzureConfig
@ -130,11 +120,11 @@ func (a *az) getAzureProfile() bool {
func (a *az) getAzureRmContext() bool {
var content string
profiles := []string{
filepath.Join(a.env.homeDir(), ".azure", "AzureRmContext.json"),
filepath.Join(a.env.homeDir(), ".Azure", "AzureRmContext.json"),
filepath.Join(a.env.Home(), ".azure", "AzureRmContext.json"),
filepath.Join(a.env.Home(), ".Azure", "AzureRmContext.json"),
}
for _, profile := range profiles {
if content = a.getFileContentWithoutBom(profile); len(content) != 0 {
if content = a.FileContentWithoutBom(profile); len(content) != 0 {
break
}
}

View file

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

View file

@ -69,7 +69,7 @@ func TestAzSegment(t *testing.T) {
for _, tc := range cases {
env := new(MockedEnvironment)
home := "/Users/posh"
env.On("homeDir").Return(home)
env.On("Home").Return(home)
var azureProfile, azureRmContext, azureRMContext string
if tc.HasCLI {
content, _ := ioutil.ReadFile("./test/azureProfile.json")
@ -83,19 +83,15 @@ func TestAzSegment(t *testing.T) {
content, _ := ioutil.ReadFile("./test/AzureRmContext.json")
azureRMContext = string(content)
}
env.On("getRuntimeGOOS").Return(linuxPlatform)
env.On("getFileContent", filepath.Join(home, ".azure", "azureProfile.json")).Return(azureProfile)
env.On("getFileContent", filepath.Join(home, ".Azure", "AzureRmContext.json")).Return(azureRmContext)
env.On("getFileContent", filepath.Join(home, ".azure", "AzureRmContext.json")).Return(azureRMContext)
env.onTemplate()
props := properties{
SegmentTemplate: tc.Template,
}
env.On("GOOS").Return(linuxPlatform)
env.On("FileContent", filepath.Join(home, ".azure", "azureProfile.json")).Return(azureProfile)
env.On("FileContent", filepath.Join(home, ".Azure", "AzureRmContext.json")).Return(azureRmContext)
env.On("FileContent", filepath.Join(home, ".azure", "AzureRmContext.json")).Return(azureRMContext)
az := &az{
env: env,
props: props,
props: properties{},
}
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"
)
func (b *batt) template() string {
return "{{ if not .Error }}{{.Icon}}{{.Percentage}}{{ end }}{{.Error}}"
}
func (b *batt) enabled() bool {
batteries, err := b.env.getBatteryInfo()
batteries, err := b.env.BatteryInfo()
if !b.enabledWhileError(err) {
return false
@ -99,20 +103,6 @@ func (b *batt) mapMostLogicalState(currentState, newState battery.State) battery
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) {
b.props = props
b.env = env

View file

@ -7,82 +7,6 @@ import (
"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) {
cases := []struct {
Case string

View file

@ -98,6 +98,10 @@ type Batch struct {
TemperatureTrend float64 // diff between this and last, short term trend
}
func (bf *brewfather) template() string {
return DefaultTemplate
}
func (bf *brewfather) enabled() bool {
data, err := bf.getResult()
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) {
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
if found {
var result Batch
@ -232,7 +221,7 @@ func (bf *brewfather) getResult() (*Batch, error) {
return err
}
bf.env.cache().set(key, string(cacheJSON), cacheTimeout)
bf.env.Cache().Set(key, string(cacheJSON), cacheTimeout)
return nil
}

View file

@ -145,16 +145,12 @@ func TestBrewfatherSegment(t *testing.T) {
}
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("set", BFCacheKey, tc.JSONResponse, tc.CacheTimeout).Return()
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()
env.On("HTTPRequest", BFBatchURL).Return([]byte(tc.BatchJSONResponse), tc.Error)
env.On("HTTPRequest", BFBatchReadingsURL).Return([]byte(tc.BatchReadingsJSONResponse), tc.Error)
env.On("cache").Return(cache)
env.onTemplate()
if tc.Template != "" {
props[SegmentTemplate] = tc.Template
}
env.On("Cache").Return(cache)
ns := &brewfather{
props: props,
@ -167,6 +163,9 @@ func TestBrewfatherSegment(t *testing.T) {
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"
)
func (c *command) template() string {
return "{{ .Output }}"
}
func (c *command) enabled() bool {
shell := c.props.getString(ExecutableShell, "bash")
if !c.env.hasCommand(shell) {
if !c.env.HasCommand(shell) {
return false
}
command := c.props.getString(Command, "echo no command specified")
if strings.Contains(command, "||") {
commands := strings.Split(command, "||")
for _, cmd := range commands {
output := c.env.runShellCommand(shell, strings.TrimSpace(cmd))
output := c.env.RunShellCommand(shell, strings.TrimSpace(cmd))
if output != "" {
c.Output = output
return true
@ -36,29 +40,15 @@ func (c *command) enabled() bool {
var output string
commands := strings.Split(command, "&&")
for _, cmd := range commands {
output += c.env.runShellCommand(shell, strings.TrimSpace(cmd))
output += c.env.RunShellCommand(shell, strings.TrimSpace(cmd))
}
c.Output = 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 != ""
}
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) {
c.props = props
c.env = env

View file

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

View file

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

View file

@ -26,6 +26,6 @@ func TestCrystal(t *testing.T) {
c := &crystal{}
c.init(props, env)
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
}
func (d *dart) string() string {
segmentTemplate := d.language.props.getString(SegmentTemplate, "{{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }}")
return d.language.string(segmentTemplate, d)
func (d *dart) template() string {
return languageTemplate
}
func (d *dart) init(props Properties, env Environment) {

View file

@ -26,6 +26,6 @@ func TestDart(t *testing.T) {
d := &dart{}
d.init(props, env)
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
}
func (d *dotnet) string() string {
segmentTemplate := d.language.props.getString(SegmentTemplate, "{{ if .Unsupported }}\uf071{{ else }}{{ .Full }}{{ end }}")
return d.language.string(segmentTemplate, d)
func (d *dotnet) template() string {
return "{{ if .Unsupported }}\uf071{{ else }}{{ .Full }}{{ end }}"
}
func (d *dotnet) init(props Properties, env Environment) {

View file

@ -6,76 +6,44 @@ import (
"github.com/stretchr/testify/assert"
)
type dotnetArgs struct {
enabled bool
version string
exitCode int
unsupportedIcon string
displayVersion bool
}
func bootStrapDotnetTest(args *dotnetArgs) *dotnet {
env := new(MockedEnvironment)
env.On("hasCommand", "dotnet").Return(args.enabled)
if args.exitCode != 0 {
err := &commandError{exitCode: args.exitCode}
env.On("runCommand", "dotnet", []string{"--version"}).Return("", err)
} else {
env.On("runCommand", "dotnet", []string{"--version"}).Return(args.version, nil)
func TestDotnetSegment(t *testing.T) {
cases := []struct {
Case string
Expected string
ExitCode int
HasCommand bool
Version string
FetchVersion bool
}{
{Case: "Unsupported version", Expected: "\uf071", HasCommand: true, FetchVersion: true, ExitCode: dotnetExitCode, Version: "3.1.402"},
{Case: "Regular version", Expected: "3.1.402", HasCommand: true, FetchVersion: true, Version: "3.1.402"},
{Case: "Regular version", Expected: "", HasCommand: true, FetchVersion: false, Version: "3.1.402"},
{Case: "Regular version", Expected: "", HasCommand: false, FetchVersion: false, Version: "3.1.402"},
}
env.On("hasFiles", "*.cs").Return(true)
env.On("getPathSeperator").Return("")
env.On("pwd").Return("/usr/home/project")
env.On("homeDir").Return("/usr/home")
env.onTemplate()
props := properties{
FetchVersion: args.displayVersion,
}
dotnet := &dotnet{}
dotnet.init(props, env)
return dotnet
}
for _, tc := range cases {
env := new(MockedEnvironment)
env.On("HasCommand", "dotnet").Return(tc.HasCommand)
if tc.ExitCode != 0 {
err := &commandError{exitCode: tc.ExitCode}
env.On("RunCommand", "dotnet", []string{"--version"}).Return("", err)
} else {
env.On("RunCommand", "dotnet", []string{"--version"}).Return(tc.Version, nil)
}
func TestEnabledDotnetNotFound(t *testing.T) {
args := &dotnetArgs{
enabled: false,
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{
FetchVersion: tc.FetchVersion,
}
dotnet := &dotnet{}
dotnet.init(props, env)
assert.True(t, dotnet.enabled())
assert.Equal(t, tc.Expected, renderTemplate(env, dotnet.template(), dotnet), tc.Case)
}
dotnet := bootStrapDotnetTest(args)
assert.True(t, dotnet.enabled())
}
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 {
alwaysEnabled := t.props.getBool(AlwaysEnabled, false)
executionTimeMs := t.env.executionTime()
executionTimeMs := t.env.ExecutionTime()
thresholdMs := t.props.getFloat64(ThresholdProperty, float64(500))
if !alwaysEnabled && executionTimeMs < thresholdMs {
return false
@ -59,18 +59,8 @@ func (t *executiontime) enabled() bool {
return t.FormattedMs != ""
}
func (t *executiontime) string() string {
segmentTemplate := t.props.getString(SegmentTemplate, "{{.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) template() string {
return "{{ .FormattedMs }}"
}
func (t *executiontime) init(props Properties, env Environment) {

View file

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

View file

@ -9,26 +9,16 @@ type exit struct {
Text string
}
func (e *exit) template() string {
return "{{ .Text }}"
}
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) {
return true
}
return e.env.lastErrorCode() != 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
return e.env.ErrorCode() != 0
}
func (e *exit) init(props Properties, env Environment) {

View file

@ -18,7 +18,7 @@ func TestExitWriterEnabled(t *testing.T) {
for _, tc := range cases {
env := new(MockedEnvironment)
env.On("lastErrorCode").Return(tc.ExitCode)
env.On("ErrorCode").Return(tc.ExitCode)
e := &exit{
env: env,
props: properties{},
@ -75,18 +75,14 @@ func TestExitWriterTemplateString(t *testing.T) {
for _, tc := range cases {
env := new(MockedEnvironment)
env.On("lastErrorCode").Return(tc.ExitCode)
env.On("templateCache").Return(&templateCache{
env.On("ErrorCode").Return(tc.ExitCode)
env.On("TemplateCache").Return(&TemplateCache{
Code: tc.ExitCode,
})
env.onTemplate()
props := properties{
SegmentTemplate: tc.Template,
}
e := &exit{
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/"
)
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 {
if !g.shouldDisplay() {
return false
@ -134,28 +138,28 @@ func (g *git) shouldDisplay() bool {
// when in wsl/wsl2 and in a windows shared folder
// we must use git.exe and convert paths accordingly
// for worktrees, stashes, and path to work
g.IsWslSharedPath = g.env.inWSLSharedDrive()
if !g.env.hasCommand(g.getGitCommand()) {
g.IsWslSharedPath = g.env.InWSLSharedDrive()
if !g.env.HasCommand(g.getGitCommand()) {
return false
}
gitdir, err := g.env.hasParentFilePath(".git")
gitdir, err := g.env.HasParentFilePath(".git")
if err != nil {
return false
}
if g.shouldIgnoreRootRepository(gitdir.parentFolder) {
if g.shouldIgnoreRootRepository(gitdir.ParentFolder) {
return false
}
if gitdir.isDir {
g.gitWorkingFolder = gitdir.path
g.gitRootFolder = gitdir.path
if gitdir.IsDir {
g.gitWorkingFolder = gitdir.Path
g.gitRootFolder = gitdir.Path
// 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
}
// handle worktree
g.gitRootFolder = gitdir.path
dirPointer := strings.Trim(g.env.getFileContent(gitdir.path), " \r\n")
g.gitRootFolder = gitdir.Path
dirPointer := strings.Trim(g.env.FileContent(gitdir.Path), " \r\n")
matches := findNamedRegexMatch(`^gitdir: (?P<dir>.*)$`, dirPointer)
if matches != nil && matches["dir"] != "" {
// 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")
if ind > -1 {
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
return true
}
@ -176,7 +180,7 @@ func (g *git) shouldDisplay() bool {
// we need the parent folder to detect where the real .git folder is
ind = strings.LastIndex(g.gitWorkingFolder, "/.git/modules")
if ind > -1 {
g.gitRootFolder = gitdir.parentFolder + "/" + g.gitWorkingFolder
g.gitRootFolder = gitdir.ParentFolder + "/" + g.gitWorkingFolder
g.gitRealFolder = g.gitRootFolder
g.gitWorkingFolder = g.gitRootFolder
return true
@ -187,24 +191,6 @@ func (g *git) shouldDisplay() bool {
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() {
getBranchStatus := func() string {
if g.Ahead > 0 && g.Behind > 0 {
@ -301,7 +287,7 @@ func (g *git) getGitCommand() string {
return g.gitCommand
}
g.gitCommand = "git"
if g.env.getRuntimeGOOS() == windowsPlatform || g.IsWslSharedPath {
if g.env.GOOS() == windowsPlatform || g.IsWslSharedPath {
g.gitCommand = "git.exe"
}
return g.gitCommand
@ -309,7 +295,7 @@ func (g *git) getGitCommand() 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...)
val, err := g.env.runCommand(g.getGitCommand(), args...)
val, err := g.env.RunCommand(g.getGitCommand(), args...)
if err != nil {
return ""
}
@ -334,7 +320,7 @@ func (g *git) setGitHEADContext() {
getPrettyNameOrigin := func(file string) string {
var origin string
head := g.getFileContents(g.gitWorkingFolder, file)
head := g.FileContents(g.gitWorkingFolder, file)
if head == "detached HEAD" {
origin = formatDetached()
} else {
@ -344,20 +330,20 @@ func (g *git) setGitHEADContext() {
return origin
}
if g.env.hasFolder(g.gitWorkingFolder + "/rebase-merge") {
if g.env.HasFolder(g.gitWorkingFolder + "/rebase-merge") {
origin := getPrettyNameOrigin("rebase-merge/head-name")
onto := g.getGitRefFileSymbolicName("rebase-merge/onto")
onto = g.formatHEAD(onto)
step := g.getFileContents(g.gitWorkingFolder, "rebase-merge/msgnum")
total := g.getFileContents(g.gitWorkingFolder, "rebase-merge/end")
step := g.FileContents(g.gitWorkingFolder, "rebase-merge/msgnum")
total := g.FileContents(g.gitWorkingFolder, "rebase-merge/end")
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)
return
}
if g.env.hasFolder(g.gitWorkingFolder + "/rebase-apply") {
if g.env.HasFolder(g.gitWorkingFolder + "/rebase-apply") {
origin := getPrettyNameOrigin("rebase-apply/head-name")
step := g.getFileContents(g.gitWorkingFolder, "rebase-apply/next")
total := g.getFileContents(g.gitWorkingFolder, "rebase-apply/last")
step := g.FileContents(g.gitWorkingFolder, "rebase-apply/next")
total := g.FileContents(g.gitWorkingFolder, "rebase-apply/last")
icon := g.props.getString(RebaseIcon, "\uE728 ")
g.HEAD = fmt.Sprintf("%s%s (%s/%s) at %s", icon, origin, step, total, g.HEAD)
return
@ -366,7 +352,7 @@ func (g *git) setGitHEADContext() {
commitIcon := g.props.getString(CommitIcon, "\uF417")
if g.hasGitFile("MERGE_MSG") {
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)
// head := g.getGitRefFileSymbolicName("ORIG_HEAD")
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
// the todo file.
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 ")
g.HEAD = fmt.Sprintf("%s%s%s onto %s", cherry, commitIcon, g.formatSHA(sha), formatDetached())
return
}
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 ")
g.HEAD = fmt.Sprintf("%s%s%s onto %s", revert, commitIcon, g.formatSHA(sha), formatDetached())
return
}
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)
if matches != nil && matches["sha"] != "" {
action := matches["action"]
@ -441,18 +427,18 @@ func (g *git) formatSHA(sha string) string {
}
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 {
ref := g.getFileContents(g.gitWorkingFolder, refFile)
ref := g.FileContents(g.gitWorkingFolder, refFile)
return g.getGitCommandOutput("name-rev", "--name-only", "--exclude=tags/*", ref)
}
func (g *git) setPrettyHEADName() {
// we didn't fetch status, fallback to parsing the HEAD file
if len(g.Hash) == 0 {
HEADRef := g.getFileContents(g.gitWorkingFolder, "HEAD")
HEADRef := g.FileContents(g.gitWorkingFolder, "HEAD")
if strings.HasPrefix(HEADRef, BRANCHPREFIX) {
branchName := strings.TrimPrefix(HEADRef, BRANCHPREFIX)
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 {
stashContent := g.getFileContents(g.gitRootFolder, "logs/refs/stash")
stashContent := g.FileContents(g.gitRootFolder, "logs/refs/stash")
if stashContent == "" {
return 0
}
@ -487,10 +473,10 @@ func (g *git) getStashContext() int {
}
func (g *git) getWorktreeContext() int {
if !g.env.hasFolder(g.gitRootFolder + "/worktrees") {
if !g.env.HasFolder(g.gitRootFolder + "/worktrees") {
return 0
}
worktreeFolders := g.env.getFoldersList(g.gitRootFolder + "/worktrees")
worktreeFolders := g.env.FolderList(g.gitRootFolder + "/worktrees")
return len(worktreeFolders)
}
@ -522,12 +508,12 @@ func (g *git) convertToWindowsPath(path string) string {
if !g.IsWslSharedPath {
return path
}
return g.env.convertToWindowsPath(path)
return g.env.ConvertToWindowsPath(path)
}
func (g *git) convertToLinuxPath(path string) string {
if !g.IsWslSharedPath {
return path
}
return g.env.convertToLinuxPath(path)
return g.env.ConvertToLinuxPath(path)
}

View file

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

View file

@ -18,12 +18,14 @@ type mockedLanguageParams struct {
func getMockedLanguageEnv(params *mockedLanguageParams) (*MockedEnvironment, properties) {
env := new(MockedEnvironment)
env.On("hasCommand", params.cmd).Return(true)
env.On("runCommand", params.cmd, []string{params.versionParam}).Return(params.versionOutput, nil)
env.On("hasFiles", params.extension).Return(true)
env.On("pwd").Return("/usr/home/project")
env.On("homeDir").Return("/usr/home")
env.onTemplate()
env.On("HasCommand", params.cmd).Return(true)
env.On("RunCommand", params.cmd, []string{params.versionParam}).Return(params.versionOutput, nil)
env.On("HasFiles", params.extension).Return(true)
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{
FetchVersion: true,
}
@ -62,28 +64,28 @@ func TestGolang(t *testing.T) {
env, props := getMockedLanguageEnv(params)
if tc.ParseModFile {
props[ParseModFile] = tc.ParseModFile
fileInfo := &fileInfo{
path: "./go.mod",
parentFolder: "./",
isDir: false,
fileInfo := &FileInfo{
Path: "./go.mod",
ParentFolder: "./",
IsDir: false,
}
var err error
if !tc.HasModFileInParentDir {
err = errors.New("no match")
}
env.On("hasParentFilePath", "go.mod").Return(fileInfo, err)
env.On("HasParentFilePath", "go.mod").Return(fileInfo, err)
var content string
if tc.InvalidModfile {
content = "invalid go.mod file"
} else {
tmp, _ := ioutil.ReadFile(fileInfo.path)
tmp, _ := ioutil.ReadFile(fileInfo.Path)
content = string(tmp)
}
env.On("getFileContent", fileInfo.path).Return(content)
env.On("FileContent", fileInfo.Path).Return(content)
}
g := &golang{}
g.init(props, env)
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"
)
func (i *ipify) template() string {
return "{{ .IP }}"
}
func (i *ipify) enabled() bool {
ip, err := i.getResult()
if err != nil {
@ -20,21 +24,6 @@ func (i *ipify) enabled() bool {
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) {
cacheTimeout := i.props.getInt(CacheTimeout, DefaultCacheTimeout)
@ -42,7 +31,7 @@ func (i *ipify) getResult() (string, error) {
if cacheTimeout > 0 {
// 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
if found {
return val, nil
@ -61,7 +50,7 @@ func (i *ipify) getResult() (string, error) {
if cacheTimeout > 0 {
// persist public ip in cache
i.env.cache().set(url, response, cacheTimeout)
i.env.Cache().Set(url, response, cacheTimeout)
}
return response, nil
}

View file

@ -46,25 +46,22 @@ func TestIpifySegment(t *testing.T) {
props := properties{
CacheTimeout: 0,
}
env.On("HTTPRequest", IPIFYAPIURL).Return([]byte(tc.Response), tc.Error)
env.onTemplate()
if tc.Template != "" {
props[SegmentTemplate] = tc.Template
}
o := &ipify{
ipify := &ipify{
props: props,
env: env,
}
enabled := o.enabled()
enabled := ipify.enabled()
assert.Equal(t, tc.ExpectedEnabled, enabled, tc.Case)
if !enabled {
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
}
func (j *java) string() string {
segmentTemplate := j.language.props.getString(SegmentTemplate, "{{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }}")
return j.language.string(segmentTemplate, j)
func (j *java) template() string {
return languageTemplate
}
func (j *java) init(props Properties, env Environment) {
@ -37,7 +36,7 @@ func (j *java) init(props Properties, env Environment) {
"*.cljc",
},
}
javaHome := j.language.env.getenv("JAVA_HOME")
javaHome := j.language.env.Getenv("JAVA_HOME")
if len(javaHome) > 0 {
java := fmt.Sprintf("%s/bin/java", javaHome)
j.language.commands = []*cmd{

View file

@ -54,25 +54,24 @@ func TestJava(t *testing.T) {
}
for _, tc := range cases {
env := new(MockedEnvironment)
env.On("hasCommand", "java").Return(true)
env.On("runCommand", "java", []string{"-Xinternalversion"}).Return(tc.Version, nil)
env.On("hasFiles", "pom.xml").Return(true)
env.On("pwd").Return("/usr/home/project")
env.On("homeDir").Return("/usr/home")
env.On("HasCommand", "java").Return(true)
env.On("RunCommand", "java", []string{"-Xinternalversion"}).Return(tc.Version, nil)
env.On("HasFiles", "pom.xml").Return(true)
env.On("Pwd").Return("/usr/home/project")
env.On("Home").Return("/usr/home")
if tc.JavaHomeEnabled {
env.On("getenv", "JAVA_HOME").Return("/usr/java")
env.On("hasCommand", "/usr/java/bin/java").Return(true)
env.On("runCommand", "/usr/java/bin/java", []string{"-Xinternalversion"}).Return(tc.JavaHomeVersion, nil)
env.On("Getenv", "JAVA_HOME").Return("/usr/java")
env.On("HasCommand", "/usr/java/bin/java").Return(true)
env.On("RunCommand", "/usr/java/bin/java", []string{"-Xinternalversion"}).Return(tc.JavaHomeVersion, nil)
} else {
env.On("getenv", "JAVA_HOME").Return("")
env.On("Getenv", "JAVA_HOME").Return("")
}
env.onTemplate()
props := properties{
FetchVersion: true,
}
j := &java{}
j.init(props, env)
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
}
func (j *julia) string() string {
segmentTemplate := j.language.props.getString(SegmentTemplate, "{{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }}")
return j.language.string(segmentTemplate, j)
func (j *julia) template() string {
return languageTemplate
}
func (j *julia) init(props Properties, env Environment) {

View file

@ -27,6 +27,6 @@ func TestJulia(t *testing.T) {
j := &julia{}
j.init(props, env)
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"`
}
func (k *kubectl) string() string {
segmentTemplate := k.props.getString(SegmentTemplate, "{{.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) template() string {
return "{{ .Context }}{{ if .Namespace }} :: {{ .Namespace }}{{ end }}"
}
func (k *kubectl) init(props Properties, env Environment) {
@ -60,9 +50,9 @@ func (k *kubectl) enabled() 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)
// 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 {
kubeconfigs = []string{filepath.Join(k.env.homeDir(), ".kube/config")}
kubeconfigs = []string{filepath.Join(k.env.Home(), ".kube/config")}
}
contexts := make(map[string]*KubeContext)
k.Context = ""
@ -71,7 +61,7 @@ func (k *kubectl) doParseKubeConfig() bool {
continue
}
content := k.env.getFileContent(kubeconfig)
content := k.env.FileContent(kubeconfig)
var config KubeConfig
err := yaml.Unmarshal([]byte(content), &config)
@ -109,10 +99,10 @@ func (k *kubectl) doParseKubeConfig() bool {
func (k *kubectl) doCallKubectl() bool {
cmd := "kubectl"
if !k.env.hasCommand(cmd) {
if !k.env.HasCommand(cmd) {
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)
if err != nil && displayError {
k.setError("KUBECTL ERR")

View file

@ -106,7 +106,7 @@ func TestKubectlSegment(t *testing.T) {
for _, tc := range cases {
env := new(MockedEnvironment)
env.On("hasCommand", "kubectl").Return(tc.KubectlExists)
env.On("HasCommand", "kubectl").Return(tc.KubectlExists)
var kubeconfig string
content, err := ioutil.ReadFile("./test/kubectl.yml")
if err == nil {
@ -119,25 +119,23 @@ func TestKubectlSegment(t *testing.T) {
exitCode: 1,
}
}
env.On("runCommand", "kubectl", []string{"config", "view", "--output", "yaml", "--minify"}).Return(kubeconfig, kubectlErr)
env.On("getenv", "KUBECONFIG").Return(tc.Kubeconfig)
env.On("RunCommand", "kubectl", []string{"config", "view", "--output", "yaml", "--minify"}).Return(kubeconfig, kubectlErr)
env.On("Getenv", "KUBECONFIG").Return(tc.Kubeconfig)
for path, content := range tc.Files {
env.On("getFileContent", path).Return(content)
env.On("FileContent", path).Return(content)
}
env.On("homeDir").Return("testhome")
env.onTemplate()
env.On("Home").Return("testhome")
k := &kubectl{
env: env,
props: properties{
SegmentTemplate: tc.Template,
DisplayError: tc.DisplayError,
ParseKubeConfig: tc.ParseKubeConfig,
},
}
assert.Equal(t, tc.ExpectedEnabled, k.enabled(), tc.Case)
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"
)
const (
languageTemplate = "{{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }}"
)
type loadContext func()
type inContext func() bool
@ -83,24 +87,11 @@ const (
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 {
// override default extensions if needed
l.extensions = l.props.getStringArray(LanguageExtensions, l.extensions)
inHomeDir := func() bool {
return l.env.pwd() == l.env.homeDir()
return l.env.Pwd() == l.env.Home()
}
var enabled bool
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
func (l *language) hasLanguageFiles() bool {
for i, extension := range l.extensions {
if l.env.hasFiles(extension) {
if l.env.HasFiles(extension) {
break
}
if i == len(l.extensions)-1 {
@ -155,10 +146,10 @@ func (l *language) setVersion() error {
var versionStr string
var err error
if command.getVersion == nil {
if !l.env.hasCommand(command.executable) {
if !l.env.HasCommand(command.executable) {
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 {
l.exitCode = exitErr.exitCode
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 {
env := new(MockedEnvironment)
for _, command := range args.commands {
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("HasCommand", command.executable).Return(args.hasvalue(command.executable, args.enabledCommands))
env.On("RunCommand", command.executable, command.args).Return(args.version, args.expectedError)
}
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"
cwd := "/usr/home/project"
if args.inHome {
cwd = home
}
env.On("pwd").Return(cwd)
env.On("homeDir").Return(home)
env.onTemplate()
env.On("Pwd").Return(cwd)
env.On("Home").Return(home)
env.On("TemplateCache").Return(&TemplateCache{
Env: make(map[string]string),
})
if args.properties == nil {
args.properties = properties{}
}

View file

@ -7,10 +7,11 @@ import (
type nbgv struct {
props Properties
env Environment
nbgv *versionInfo
VersionInfo
}
type versionInfo struct {
type VersionInfo struct {
VersionFileFound bool `json:"VersionFileFound"`
Version string `json:"Version"`
AssemblyVersion string `json:"AssemblyVersion"`
@ -21,35 +22,25 @@ type versionInfo struct {
SimpleVersion string `json:"SimpleVersion"`
}
func (n *nbgv) enabled() bool {
nbgv := "nbgv"
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) template() string {
return "{{ .Version }}"
}
func (n *nbgv) string() string {
segmentTemplate := n.props.getString(SegmentTemplate, "{{ .Version }}")
template := &textTemplate{
Template: segmentTemplate,
Context: n.nbgv,
Env: n.env,
func (n *nbgv) enabled() bool {
nbgv := "nbgv"
if !n.env.HasCommand(nbgv) {
return false
}
text, err := template.render()
response, err := n.env.RunCommand(nbgv, "get-version", "--format=json")
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) {

View file

@ -14,7 +14,7 @@ func TestNbgv(t *testing.T) {
ExpectedString string
Response string
HasNbgv bool
SegmentTemplate string
Template string
Error error
}{
{Case: "nbgv not installed"},
@ -26,7 +26,7 @@ func TestNbgv(t *testing.T) {
ExpectedString: "invalid template text",
HasNbgv: true,
Response: "{ \"VersionFileFound\": true }",
SegmentTemplate: "{{ err }}",
Template: "{{ err }}",
},
{
Case: "command error",
@ -44,7 +44,7 @@ func TestNbgv(t *testing.T) {
ExpectedString: "bump",
HasNbgv: true,
Response: "{ \"VersionFileFound\": true, \"Version\": \"bump\" }",
SegmentTemplate: "{{ .Version }}",
Template: "{{ .Version }}",
},
{
Case: "AssemblyVersion",
@ -52,25 +52,25 @@ func TestNbgv(t *testing.T) {
ExpectedString: "bump",
HasNbgv: true,
Response: "{ \"VersionFileFound\": true, \"AssemblyVersion\": \"bump\" }",
SegmentTemplate: "{{ .AssemblyVersion }}",
Template: "{{ .AssemblyVersion }}",
},
}
for _, tc := range cases {
env := new(MockedEnvironment)
env.On("hasCommand", "nbgv").Return(tc.HasNbgv)
env.On("runCommand", "nbgv", []string{"get-version", "--format=json"}).Return(tc.Response, tc.Error)
env.onTemplate()
env.On("HasCommand", "nbgv").Return(tc.HasNbgv)
env.On("RunCommand", "nbgv", []string{"get-version", "--format=json"}).Return(tc.Response, tc.Error)
nbgv := &nbgv{
env: env,
props: properties{
SegmentTemplate: tc.SegmentTemplate,
},
env: env,
props: properties{},
}
enabled := nbgv.enabled()
assert.Equal(t, tc.ExpectedEnabled, enabled, tc.Case)
if tc.Template == "" {
tc.Template = nbgv.template()
}
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"`
}
func (ns *nightscout) template() string {
return "{{ .Sgv }}"
}
func (ns *nightscout) enabled() bool {
data, err := ns.getResult()
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) {
parseSingleElement := func(data []byte) (*NightscoutData, error) {
var result []*NightscoutData
@ -105,7 +94,7 @@ func (ns *nightscout) getResult() (*NightscoutData, error) {
return result[0], nil
}
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
if found {
if data, err := parseSingleElement([]byte(val)); err == nil {
@ -143,7 +132,7 @@ func (ns *nightscout) getResult() (*NightscoutData, error) {
if cacheTimeout > 0 {
// persist new sugars in cache
ns.env.cache().set(url, string(body), cacheTimeout)
ns.env.Cache().Set(url, string(body), cacheTimeout)
}
return data, nil
}

View file

@ -136,16 +136,11 @@ func TestNSSegment(t *testing.T) {
}
cache := &MockedCache{}
cache.On("get", FAKEAPIURL).Return(tc.JSONResponse, !tc.CacheFoundFail)
cache.On("set", FAKEAPIURL, tc.JSONResponse, tc.CacheTimeout).Return()
cache.On("Get", FAKEAPIURL).Return(tc.JSONResponse, !tc.CacheFoundFail)
cache.On("Set", FAKEAPIURL, tc.JSONResponse, tc.CacheTimeout).Return()
env.On("HTTPRequest", FAKEAPIURL).Return([]byte(tc.JSONResponse), tc.Error)
env.On("cache").Return(cache)
env.onTemplate()
if tc.Template != "" {
props[SegmentTemplate] = tc.Template
}
env.On("Cache").Return(cache)
ns := &nightscout{
props: props,
@ -158,6 +153,9 @@ func TestNSSegment(t *testing.T) {
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"
)
func (n *node) string() string {
segmentTemplate := n.language.props.getString(SegmentTemplate, "{{ if .PackageManagerIcon }}{{ .PackageManagerIcon }} {{ end }}{{ .Full }}")
return n.language.string(segmentTemplate, n)
func (n *node) template() string {
return "{{ if .PackageManagerIcon }}{{ .PackageManagerIcon }} {{ end }}{{ .Full }}"
}
func (n *node) init(props Properties, env Environment) {
@ -48,17 +47,17 @@ func (n *node) loadContext() {
if !n.language.props.getBool(FetchPackageManager, false) {
return
}
if n.language.env.hasFiles("yarn.lock") {
if n.language.env.HasFiles("yarn.lock") {
n.PackageManagerIcon = n.language.props.getString(YarnIcon, " \uF61A")
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")
}
}
func (n *node) matchesVersionFile() bool {
fileVersion := n.language.env.getFileContent(".nvmrc")
fileVersion := n.language.env.FileContent(".nvmrc")
if len(fileVersion) == 0 {
return true
}

View file

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

View file

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

View file

@ -61,9 +61,9 @@ func TestOSInfo(t *testing.T) {
}
for _, tc := range cases {
env := new(MockedEnvironment)
env.On("getRuntimeGOOS").Return(tc.GOOS)
env.On("getPlatform").Return(tc.Platform)
env.On("templateCache").Return(&templateCache{
env.On("GOOS").Return(tc.GOOS)
env.On("Platform").Return(tc.Platform)
env.On("TemplateCache").Return(&TemplateCache{
Env: make(map[string]string),
WSL: tc.IsWSL,
})
@ -76,6 +76,6 @@ func TestOSInfo(t *testing.T) {
},
}
_ = 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
}
func (d *owm) string() string {
segmentTemplate := d.props.getString(SegmentTemplate, "{{.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) template() string {
return "{{ .Weather }} ({{ .Temperature }}{{ .UnitIcon }})"
}
func (d *owm) getResult() (*owmDataResponse, error) {
@ -69,14 +59,14 @@ func (d *owm) getResult() (*owmDataResponse, error) {
response := new(owmDataResponse)
if cacheTimeout > 0 {
// 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
if found {
err := json.Unmarshal([]byte(val), response)
if err != nil {
return nil, err
}
d.URL, _ = d.env.cache().get(CacheKeyURL)
d.URL, _ = d.env.Cache().Get(CacheKeyURL)
return response, nil
}
}
@ -98,8 +88,8 @@ func (d *owm) getResult() (*owmDataResponse, error) {
if cacheTimeout > 0 {
// persist new forecasts in cache
d.env.cache().set(CacheKeyResponse, string(body), cacheTimeout)
d.env.cache().set(CacheKeyURL, d.URL, cacheTimeout)
d.env.Cache().Set(CacheKeyResponse, string(body), cacheTimeout)
d.env.Cache().Set(CacheKeyURL, d.URL, cacheTimeout)
}
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.onTemplate()
if tc.Template != "" {
props[SegmentTemplate] = tc.Template
}
o := &owm{
props: props,
@ -76,7 +71,10 @@ func TestOWMSegmentSingle(t *testing.T) {
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)
env.On("HTTPRequest", OWMAPIURL).Return([]byte(response), nil)
env.onTemplate()
o := &owm{
props: properties{
@ -199,7 +196,7 @@ func TestOWMSegmentIcons(t *testing.T) {
}
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
@ -210,21 +207,19 @@ 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)
env.On("HTTPRequest", OWMAPIURL).Return([]byte(response), nil)
env.onTemplate()
o := &owm{
props: properties{
APIKey: "key",
Location: "AMSTERDAM,NL",
Units: "metric",
CacheTimeout: 0,
SegmentTemplate: "[{{.Weather}} ({{.Temperature}}{{.UnitIcon}})]({{.URL}})",
APIKey: "key",
Location: "AMSTERDAM,NL",
Units: "metric",
CacheTimeout: 0,
},
env: env,
}
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) {
@ -241,14 +236,13 @@ func TestOWMSegmentFromCache(t *testing.T) {
},
env: env,
}
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("set").Return()
env.On("cache").Return(cache)
env.onTemplate()
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("Set").Return()
env.On("Cache").Return(cache)
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) {
@ -260,19 +254,17 @@ func TestOWMSegmentFromCacheWithHyperlink(t *testing.T) {
o := &owm{
props: properties{
APIKey: "key",
Location: "AMSTERDAM,NL",
Units: "metric",
SegmentTemplate: "[{{.Weather}} ({{.Temperature}}{{.UnitIcon}})]({{.URL}})",
APIKey: "key",
Location: "AMSTERDAM,NL",
Units: "metric",
},
env: env,
}
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("set").Return()
env.On("cache").Return(cache)
env.onTemplate()
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("Set").Return()
env.On("Cache").Return(cache)
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"
)
func (pt *path) template() string {
return "{{ .Path }}"
}
func (pt *path) enabled() bool {
pt.pwd = pt.env.pwd()
pt.pwd = pt.env.Pwd()
switch style := pt.props.getString(Style, Agnoster); style {
case Agnoster:
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 = pt.formatWindowsDrive(pt.Path)
if pt.env.isWsl() {
pt.Location, _ = pt.env.runCommand("wslpath", "-m", pt.pwd)
if pt.env.IsWsl() {
pt.Location, _ = pt.env.RunCommand("wslpath", "-m", pt.pwd)
} else {
pt.Location = pt.pwd
}
pt.StackCount = pt.env.stackCount()
pt.StackCount = pt.env.StackCount()
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 {
if pt.env.getRuntimeGOOS() != windowsPlatform || !strings.HasSuffix(pwd, ":") {
if pt.env.GOOS() != windowsPlatform || !strings.HasSuffix(pwd, ":") {
return pwd
}
return pwd + "\\"
@ -119,7 +109,7 @@ func (pt *path) init(props Properties, env Environment) {
func (pt *path) getMixedPath() string {
var buffer strings.Builder
pwd := pt.getPwd()
splitted := strings.Split(pwd, pt.env.getPathSeperator())
splitted := strings.Split(pwd, pt.env.PathSeperator())
threshold := int(pt.props.getFloat64(MixedThreshold, 4))
for i, part := range splitted {
if part == "" {
@ -130,7 +120,7 @@ func (pt *path) getMixedPath() string {
if len(part) > threshold && i != 0 && i != len(splitted)-1 {
folder = pt.props.getString(FolderIcon, "..")
}
separator := pt.props.getString(FolderSeparatorIcon, pt.env.getPathSeperator())
separator := pt.props.getString(FolderSeparatorIcon, pt.env.PathSeperator())
if i == 0 {
separator = ""
}
@ -146,7 +136,7 @@ func (pt *path) getAgnosterPath() string {
buffer.WriteString(pt.rootLocation())
pathDepth := pt.pathDepth(pwd)
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++ {
buffer.WriteString(fmt.Sprintf("%s%s", separator, folderIcon))
}
@ -158,7 +148,7 @@ func (pt *path) getAgnosterPath() string {
func (pt *path) getAgnosterLeftPath() string {
pwd := pt.getPwd()
separator := pt.env.getPathSeperator()
separator := pt.env.PathSeperator()
pwd = strings.Trim(pwd, separator)
splitted := strings.Split(pwd, separator)
folderIcon := pt.props.getString(FolderIcon, "..")
@ -182,8 +172,8 @@ func (pt *path) getAgnosterLeftPath() string {
func (pt *path) getLetterPath() string {
var buffer strings.Builder
pwd := pt.getPwd()
splitted := strings.Split(pwd, pt.env.getPathSeperator())
separator := pt.props.getString(FolderSeparatorIcon, pt.env.getPathSeperator())
splitted := strings.Split(pwd, pt.env.PathSeperator())
separator := pt.props.getString(FolderSeparatorIcon, pt.env.PathSeperator())
for i := 0; i < len(splitted)-1; i++ {
folder := splitted[i]
if len(folder) == 0 {
@ -213,7 +203,7 @@ func (pt *path) getLetterPath() string {
func (pt *path) getAgnosterFullPath() string {
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:]
}
return pt.replaceFolderSeparators(pwd)
@ -229,7 +219,7 @@ func (pt *path) getAgnosterShortPath() string {
if pathDepth <= maxDepth {
return pt.getAgnosterFullPath()
}
pathSeparator := pt.env.getPathSeperator()
pathSeparator := pt.env.PathSeperator()
folderSeparator := pt.props.getString(FolderSeparatorIcon, pathSeparator)
folderIcon := pt.props.getString(FolderIcon, "..")
root := pt.rootLocation()
@ -256,9 +246,9 @@ func (pt *path) getFolderPath() string {
}
func (pt *path) getPwd() string {
pwd := *pt.env.getArgs().PSWD
pwd := *pt.env.Args().PSWD
if pwd == "" {
pwd = pt.env.pwd()
pwd = pt.env.Pwd()
}
pwd = pt.replaceMappedLocations(pwd)
return pwd
@ -267,10 +257,10 @@ func (pt *path) getPwd() string {
func (pt *path) normalize(inputPath string) string {
normalized := inputPath
if strings.HasPrefix(inputPath, "~") {
normalized = pt.env.homeDir() + normalized[1:]
normalized = pt.env.Home() + normalized[1:]
}
normalized = strings.ReplaceAll(normalized, "\\", "/")
goos := pt.env.getRuntimeGOOS()
goos := pt.env.GOOS()
if goos == windowsPlatform || goos == darwinPlatform {
normalized = strings.ToLower(normalized)
}
@ -286,7 +276,7 @@ func (pt *path) replaceMappedLocations(pwd string) string {
if pt.props.getBool(MappedLocationsEnabled, true) {
mappedLocations["HKCU:"] = 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
@ -318,7 +308,7 @@ func (pt *path) replaceMappedLocations(pwd string) string {
}
func (pt *path) replaceFolderSeparators(pwd string) string {
defaultSeparator := pt.env.getPathSeperator()
defaultSeparator := pt.env.PathSeperator()
if pwd == defaultSeparator {
return pwd
}
@ -332,19 +322,19 @@ func (pt *path) replaceFolderSeparators(pwd string) string {
}
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 {
pwd := pt.getPwd()
pwd = strings.TrimPrefix(pwd, pt.env.getPathSeperator())
splitted := strings.Split(pwd, pt.env.getPathSeperator())
pwd = strings.TrimPrefix(pwd, pt.env.PathSeperator())
splitted := strings.Split(pwd, pt.env.PathSeperator())
rootLocation := splitted[0]
return rootLocation
}
func (pt *path) pathDepth(pwd string) int {
splitted := strings.Split(pwd, pt.env.getPathSeperator())
splitted := strings.Split(pwd, pt.env.PathSeperator())
depth := 0
for _, part := range splitted {
if part != "" {
@ -363,7 +353,7 @@ func base(path string, env Environment) string {
}
volumeName := filepath.VolumeName(path)
// 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]
}
if volumeName == path {
@ -373,7 +363,7 @@ func base(path string, env Environment) string {
path = path[len(filepath.VolumeName(path)):]
// Find the last element
i := len(path) - 1
for i >= 0 && string(path[i]) != env.getPathSeperator() {
for i >= 0 && string(path[i]) != env.PathSeperator() {
i--
}
if i >= 0 {
@ -381,7 +371,7 @@ func base(path string, env Environment) string {
}
// If empty now, it had only slashes.
if path == "" {
return env.getPathSeperator()
return env.PathSeperator()
}
return path
}

View file

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

View file

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

View file

@ -27,6 +27,6 @@ func TestPhp(t *testing.T) {
j := &php{}
j.init(props, env)
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
}
func (p *plastic) template() string {
return "{{ .Selector }}"
}
func (p *plastic) enabled() bool {
if !p.env.hasCommand("cm") {
if !p.env.HasCommand("cm") {
return false
}
wkdir, err := p.env.hasParentFilePath(".plastic")
wkdir, err := p.env.HasParentFilePath(".plastic")
if err != nil {
return false
}
if p.shouldIgnoreRootRepository(wkdir.parentFolder) {
if p.shouldIgnoreRootRepository(wkdir.ParentFolder) {
return false
}
if !wkdir.isDir {
if !wkdir.IsDir {
return false
}
p.plasticWorkspaceFolder = wkdir.parentFolder
p.plasticWorkspaceFolder = wkdir.ParentFolder
displayStatus := p.props.getBool(FetchStatus, false)
p.setSelector()
if displayStatus {
@ -62,20 +66,6 @@ func (p *plastic) enabled() bool {
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() {
output := p.getCmCommandOutput("status", "--all", "--machinereadable")
splittedOutput := strings.Split(output, "\n")
@ -139,7 +129,7 @@ func (p *plastic) getHeadChangeset() int {
func (p *plastic) setSelector() {
var ref string
selector := p.getFileContents(p.plasticWorkspaceFolder+"/.plastic/", "plastic.selector")
selector := p.FileContents(p.plasticWorkspaceFolder+"/.plastic/", "plastic.selector")
// changeset
ref = p.parseChangesetSelector(selector)
if len(ref) > 0 {
@ -173,6 +163,6 @@ func (p *plastic) parseBranchSelector(selector string) string {
}
func (p *plastic) getCmCommandOutput(args ...string) string {
val, _ := p.env.runCommand("cm", args...)
val, _ := p.env.RunCommand("cm", args...)
return val
}

View file

@ -8,9 +8,9 @@ import (
func TestPlasticEnabledNotFound(t *testing.T) {
env := new(MockedEnvironment)
env.On("hasCommand", "cm").Return(false)
env.On("getRuntimeGOOS").Return("")
env.On("isWsl").Return(false)
env.On("HasCommand", "cm").Return(false)
env.On("GOOS").Return("")
env.On("IsWsl").Return(false)
p := &plastic{
scm: scm{
env: env,
@ -22,16 +22,16 @@ func TestPlasticEnabledNotFound(t *testing.T) {
func TestPlasticEnabledInWorkspaceDirectory(t *testing.T) {
env := new(MockedEnvironment)
env.On("hasCommand", "cm").Return(true)
env.On("getRuntimeGOOS").Return("")
env.On("isWsl").Return(false)
env.On("getFileContent", "/dir/.plastic//plastic.selector").Return("")
fileInfo := &fileInfo{
path: "/dir/hello",
parentFolder: "/dir",
isDir: true,
env.On("HasCommand", "cm").Return(true)
env.On("GOOS").Return("")
env.On("IsWsl").Return(false)
env.On("FileContent", "/dir/.plastic//plastic.selector").Return("")
fileInfo := &FileInfo{
Path: "/dir/hello",
ParentFolder: "/dir",
IsDir: true,
}
env.On("hasParentFilePath", ".plastic").Return(fileInfo, nil)
env.On("HasParentFilePath", ".plastic").Return(fileInfo, nil)
p := &plastic{
scm: scm{
env: env,
@ -39,13 +39,13 @@ func TestPlasticEnabledInWorkspaceDirectory(t *testing.T) {
},
}
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 {
env := new(MockedEnvironment)
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", "--all", "--machinereadable"}).Return(status, nil)
env.On("RunCommand", "cm", []string{"status", "--head", "--machinereadable"}).Return(headStatus, nil)
p := &plastic{
scm: scm{
env: env,
@ -326,13 +326,11 @@ func TestPlasticTemplateString(t *testing.T) {
for _, tc := range cases {
props := properties{
FetchStatus: true,
SegmentTemplate: tc.Template,
FetchStatus: true,
}
tc.Plastic.props = props
env := new(MockedEnvironment)
env.onTemplate()
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"
)
func (p *poshgit) enabled() bool {
status := p.env.getenv(poshGitEnv)
p.Status = strings.TrimSpace(status)
return p.Status != ""
func (p *poshgit) template() string {
return "{{ .Status }}"
}
func (p *poshgit) string() string {
segmentTemplate := p.props.getString(SegmentTemplate, "{{ .Status }}")
template := &textTemplate{
Template: segmentTemplate,
Context: p,
Env: p.env,
}
text, err := template.render()
if err != nil {
return err.Error()
}
return text
func (p *poshgit) enabled() bool {
status := p.env.Getenv(poshGitEnv)
p.Status = strings.TrimSpace(status)
return p.Status != ""
}
func (p *poshgit) init(props Properties, env Environment) {

View file

@ -20,15 +20,14 @@ func TestPoshGitSegment(t *testing.T) {
for _, tc := range cases {
env := new(MockedEnvironment)
env.onTemplate()
env.On("getenv", poshGitEnv).Return(tc.PoshGitPrompt)
env.On("Getenv", poshGitEnv).Return(tc.PoshGitPrompt)
p := &poshgit{
env: env,
props: &properties{},
}
assert.Equal(t, tc.Enabled, p.enabled())
assert.Equal(t, tc.Enabled, p.enabled(), tc.Case)
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"
)
func (p *python) string() string {
segmentTemplate := p.language.props.getString(SegmentTemplate, "{{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }}")
return p.language.string(segmentTemplate, p)
func (p *python) template() string {
return languageTemplate
}
func (p *python) init(props Properties, env Environment) {
@ -57,7 +56,7 @@ func (p *python) loadContext() {
}
var venv string
for _, venvVar := range venvVars {
venv = p.language.env.getenv(venvVar)
venv = p.language.env.Getenv(venvVar)
name := base(venv, p.language.env)
if p.canUseVenvName(name) {
p.Venv = name

View file

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

View file

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

View file

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

View file

@ -83,28 +83,27 @@ func TestRuby(t *testing.T) {
}
for _, tc := range cases {
env := new(MockedEnvironment)
env.On("hasCommand", "rbenv").Return(tc.HasRbenv)
env.On("runCommand", "rbenv", []string{"version-name"}).Return(tc.Version, nil)
env.On("hasCommand", "rvm-prompt").Return(tc.HasRvmprompt)
env.On("runCommand", "rvm-prompt", []string{"i", "v", "g"}).Return(tc.Version, nil)
env.On("hasCommand", "chruby").Return(tc.HasChruby)
env.On("runCommand", "chruby", []string(nil)).Return(tc.Version, nil)
env.On("hasCommand", "asdf").Return(tc.HasAsdf)
env.On("runCommand", "asdf", []string{"current", "ruby"}).Return(tc.Version, nil)
env.On("hasCommand", "ruby").Return(tc.HasRuby)
env.On("runCommand", "ruby", []string{"--version"}).Return(tc.Version, nil)
env.On("hasFiles", "*.rb").Return(tc.HasRubyFiles)
env.On("hasFiles", "Rakefile").Return(tc.HasRakeFile)
env.On("hasFiles", "Gemfile").Return(tc.HasGemFile)
env.On("pwd").Return("/usr/home/project")
env.On("homeDir").Return("/usr/home")
env.onTemplate()
env.On("HasCommand", "rbenv").Return(tc.HasRbenv)
env.On("RunCommand", "rbenv", []string{"version-name"}).Return(tc.Version, nil)
env.On("HasCommand", "rvm-prompt").Return(tc.HasRvmprompt)
env.On("RunCommand", "rvm-prompt", []string{"i", "v", "g"}).Return(tc.Version, nil)
env.On("HasCommand", "chruby").Return(tc.HasChruby)
env.On("RunCommand", "chruby", []string(nil)).Return(tc.Version, nil)
env.On("HasCommand", "asdf").Return(tc.HasAsdf)
env.On("RunCommand", "asdf", []string{"current", "ruby"}).Return(tc.Version, nil)
env.On("HasCommand", "ruby").Return(tc.HasRuby)
env.On("RunCommand", "ruby", []string{"--version"}).Return(tc.Version, nil)
env.On("HasFiles", "*.rb").Return(tc.HasRubyFiles)
env.On("HasFiles", "Rakefile").Return(tc.HasRakeFile)
env.On("HasFiles", "Gemfile").Return(tc.HasGemFile)
env.On("Pwd").Return("/usr/home/project")
env.On("Home").Return("/usr/home")
props := properties{
FetchVersion: tc.FetchVersion,
}
ruby := &ruby{}
ruby.init(props, env)
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
}
func (r *rust) string() string {
segmentTemplate := r.language.props.getString(SegmentTemplate, "{{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }}")
return r.language.string(segmentTemplate, r)
func (r *rust) template() string {
return languageTemplate
}
func (r *rust) init(props Properties, env Environment) {

View file

@ -26,6 +26,6 @@ func TestRust(t *testing.T) {
r := &rust{}
r.init(props, env)
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
}
func (s *session) string() string {
segmentTemplate := s.props.getString(SegmentTemplate, "{{ .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) template() string {
return "{{ .UserName }}@{{ .HostName }}"
}
func (s *session) init(props Properties, env Environment) {
@ -41,7 +31,7 @@ func (s *session) activeSSHSession() bool {
"SSH_CLIENT",
}
for _, key := range keys {
content := s.env.getenv(key)
content := s.env.Getenv(key)
if content != "" {
return true
}

View file

@ -87,16 +87,16 @@ func TestSessionSegmentTemplate(t *testing.T) {
for _, tc := range cases {
env := new(MockedEnvironment)
env.On("getCurrentUser").Return(tc.UserName)
env.On("getRuntimeGOOS").Return("burp")
env.On("getHostName").Return(tc.ComputerName, nil)
env.On("User").Return(tc.UserName)
env.On("GOOS").Return("burp")
env.On("Host").Return(tc.ComputerName, nil)
var SSHSession string
if tc.SSHSession {
SSHSession = "zezzion"
}
env.On("getenv", "SSH_CONNECTION").Return(SSHSession)
env.On("getenv", "SSH_CLIENT").Return(SSHSession)
env.On("templateCache").Return(&templateCache{
env.On("Getenv", "SSH_CONNECTION").Return(SSHSession)
env.On("Getenv", "SSH_CLIENT").Return(SSHSession)
env.On("TemplateCache").Return(&TemplateCache{
UserName: tc.UserName,
HostName: tc.ComputerName,
Env: map[string]string{
@ -107,12 +107,10 @@ func TestSessionSegmentTemplate(t *testing.T) {
Root: tc.Root,
})
session := &session{
env: env,
props: properties{
SegmentTemplate: tc.Template,
},
env: env,
props: properties{},
}
_ = 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"
)
func (s *shell) template() string {
return "{{ .Name }}"
}
func (s *shell) enabled() bool {
mappedNames := s.props.getKeyValueMap(MappedShellNames, make(map[string]string))
s.Name = s.env.getShellName()
s.Name = s.env.Shell()
for key, val := range mappedNames {
if strings.EqualFold(s.Name, key) {
s.Name = val
@ -26,20 +30,6 @@ func (s *shell) enabled() bool {
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) {
s.props = props
s.env = env

View file

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

View file

@ -27,19 +27,10 @@ const (
paused = "paused"
)
func (s *spotify) string() string {
segmentTemplate := s.props.getString(SegmentTemplate, "{{.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) template() string {
return "{{ .Icon }}{{ if ne .Status \"stopped\" }}{{ .Artist }} - {{ .Track }}{{ end }}"
}
func (s *spotify) resolveIcon() {
switch s.Status {
case stopped:

View file

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

View file

@ -3,61 +3,37 @@
package main
import (
"errors"
"testing"
"github.com/stretchr/testify/assert"
)
type spotifyArgs struct {
running string
status string
artist string
track string
runError error
}
func bootStrapSpotifyDarwinTest(args *spotifyArgs) *spotify {
env := new(MockedEnvironment)
env.On("runCommand", "osascript", []string{"-e", "application \"Spotify\" is running"}).Return(args.running, args.runError)
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 artist of current track as string"}).Return(args.artist, nil)
env.On("runCommand", "osascript", []string{"-e", "tell application \"Spotify\" to name of current track as string"}).Return(args.track, nil)
env.onTemplate()
s := &spotify{
env: env,
props: properties{},
}
return 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",
cases := []struct {
Running string
Expected string
Status string
Artist string
Track string
Error error
}{
{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"},
}
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",
for _, tc := range cases {
env := new(MockedEnvironment)
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(tc.Status, 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(tc.Track, nil)
s := &spotify{
env: env,
props: properties{},
}
assert.Equal(t, tc.Running == "true", s.enabled())
assert.Equal(t, tc.Expected, renderTemplate(env, s.template(), s))
}
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) {
expected := "\ue602 Candlemass - Spellbreaker"
env := new(MockedEnvironment)
env.onTemplate()
s := &spotify{
MusicPlayer: MusicPlayer{
Artist: "Candlemass",
@ -20,13 +19,12 @@ func TestSpotifyStringPlayingSong(t *testing.T) {
props: properties{},
env: env,
}
assert.Equal(t, expected, s.string())
assert.Equal(t, expected, renderTemplate(env, s.template(), s))
}
func TestSpotifyStringStoppedSong(t *testing.T) {
expected := "\uf04d "
env := new(MockedEnvironment)
env.onTemplate()
s := &spotify{
MusicPlayer: MusicPlayer{
Artist: "Candlemass",
@ -37,5 +35,5 @@ func TestSpotifyStringStoppedSong(t *testing.T) {
props: properties{},
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 {
// search for spotify window to retrieve the title
// 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 {
return false
}

View file

@ -16,7 +16,7 @@ type spotifyArgs struct {
func bootStrapSpotifyWindowsTest(args *spotifyArgs) *spotify {
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()
s := &spotify{
env: env,

View file

@ -8,10 +8,10 @@ import (
)
func (s *spotify) enabled() bool {
if !s.env.isWsl() {
if !s.env.IsWsl() {
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") {
return false
}

View file

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

View file

@ -68,6 +68,10 @@ func (a *AuthError) Error() string {
return a.message
}
func (s *strava) template() string {
return "{{ if .Error }}{{ .Error }}{{ else }}{{ .Ago }}{{ end }}"
}
func (s *strava) enabled() bool {
data, err := s.getResult()
if err == nil {
@ -75,6 +79,7 @@ func (s *strava) enabled() bool {
s.Icon = s.getActivityIcon()
s.Hours = s.getHours()
s.Ago = s.getAgo()
s.URL = fmt.Sprintf("https://www.strava.com/activities/%d", s.ID)
return true
}
if _, s.Authenticate = err.(*AuthError); s.Authenticate {
@ -117,31 +122,13 @@ func (s *strava) getActivityIcon() string {
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) {
// 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
}
// 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 {
return acccessToken, nil
}
@ -176,8 +163,8 @@ func (s *strava) refreshToken(refreshToken string) (string, error) {
}
}
// add tokens to cache
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(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
return tokens.AccessToken, nil
}
@ -194,7 +181,7 @@ func (s *strava) getResult() (*StravaData, error) {
return result[0], nil
}
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
if found {
if data, err := parseSingleElement([]byte(val)); err == nil {
@ -237,7 +224,7 @@ func (s *strava) getResult() (*StravaData, error) {
}
if cacheTimeout > 0 {
// persist new sugars in cache
s.env.cache().set(url, string(body), cacheTimeout)
s.env.Cache().Set(url, string(body), cacheTimeout)
}
return data, nil
}

View file

@ -142,23 +142,19 @@ func TestStravaSegment(t *testing.T) {
CacheTimeout: tc.CacheTimeout,
}
cache := &MockedCache{}
cache.On("get", url).Return(tc.JSONResponse, !tc.CacheFoundFail)
cache.On("set", url, tc.JSONResponse, tc.CacheTimeout).Return()
cache.On("Get", url).Return(tc.JSONResponse, !tc.CacheFoundFail)
cache.On("Set", url, tc.JSONResponse, tc.CacheTimeout).Return()
cache.On("get", StravaAccessToken).Return(tc.AccessToken, !tc.AccessTokenCacheFoundFail)
cache.On("get", StravaRefreshToken).Return(tc.RefreshToken, !tc.RefreshTokenCacheFoundFail)
cache.On("Get", StravaAccessToken).Return(tc.AccessToken, !tc.AccessTokenCacheFoundFail)
cache.On("Get", StravaRefreshToken).Return(tc.RefreshToken, !tc.RefreshTokenCacheFoundFail)
cache.On("set", StravaRefreshToken, "NEW_REFRESHTOKEN", 2*525960)
cache.On("set", StravaAccessToken, "NEW_ACCESSTOKEN", 20)
cache.On("Set", StravaRefreshToken, "NEW_REFRESHTOKEN", 2*525960)
cache.On("Set", StravaAccessToken, "NEW_ACCESSTOKEN", 20)
env.On("HTTPRequest", url).Return([]byte(tc.JSONResponse), tc.Error)
env.On("HTTPRequest", tokenURL).Return([]byte(tc.TokenResponse), tc.Error)
env.On("cache").Return(cache)
env.onTemplate()
env.On("Cache").Return(cache)
if tc.Template != "" {
props[SegmentTemplate] = tc.Template
}
if tc.InitialAccessToken != "" {
props[AccessToken] = tc.InitialAccessToken
}
@ -192,8 +188,11 @@ func TestStravaSegment(t *testing.T) {
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"
)
func (s *sysinfo) template() string {
return "{{ round .PhysicalPercentUsed .Precision }}"
}
func (s *sysinfo) enabled() bool {
if s.PhysicalPercentUsed == 0 && s.SwapPercentUsed == 0 {
return false
@ -38,21 +42,6 @@ func (s *sysinfo) enabled() bool {
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) {
s.props = props
s.env = env

View file

@ -50,17 +50,15 @@ func TestSysInfo(t *testing.T) {
for _, tc := range cases {
env := new(MockedEnvironment)
env.onTemplate()
tc.SysInfo.env = env
tc.SysInfo.props = properties{
Precision: tc.Precision,
SegmentTemplate: tc.Template,
Precision: tc.Precision,
}
enabled := tc.SysInfo.enabled()
if tc.ExpectDisabled {
assert.Equal(t, false, enabled, tc.Case)
} 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
}
func (tf *terraform) string() string {
segmentTemplate := tf.props.getString(SegmentTemplate, "{{.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) template() string {
return "{{ .WorkspaceName }}"
}
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 {
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
}
tf.WorkspaceName, _ = tf.env.runCommand(cmd, "workspace", "show")
tf.WorkspaceName, _ = tf.env.RunCommand(cmd, "workspace", "show")
return true
}

View file

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