refactor: move environment into it's own module

This commit is contained in:
Jan De Dobbeleer 2022-01-26 10:23:18 +01:00 committed by Jan De Dobbeleer
parent f7a07c6b62
commit 906ece2af9
116 changed files with 1016 additions and 870 deletions

View file

@ -2,6 +2,7 @@ package main
import (
"fmt"
"oh-my-posh/regex"
"strings"
)
@ -122,16 +123,16 @@ func (a *ansiUtils) lenWithoutANSI(text string) int {
return 0
}
// replace hyperlinks(file/http/https)
matches := findAllNamedRegexMatch(`(?P<STR>\x1b]8;;(file|http|https):\/\/(.+?)\x1b\\(?P<URL>.+?)\x1b]8;;\x1b\\)`, text)
matches := regex.FindAllNamedRegexMatch(`(?P<STR>\x1b]8;;(file|http|https):\/\/(.+?)\x1b\\(?P<URL>.+?)\x1b]8;;\x1b\\)`, text)
for _, match := range matches {
text = strings.ReplaceAll(text, match[str], match[url])
}
// replace console title
matches = findAllNamedRegexMatch(`(?P<STR>\x1b\]0;(.+)\007)`, text)
matches = regex.FindAllNamedRegexMatch(`(?P<STR>\x1b\]0;(.+)\007)`, text)
for _, match := range matches {
text = strings.ReplaceAll(text, match[str], "")
}
stripped := replaceAllString(ansiRegex, text, "")
stripped := regex.ReplaceAllString(ansiRegex, text, "")
stripped = strings.ReplaceAll(stripped, a.escapeLeft, "")
stripped = strings.ReplaceAll(stripped, a.escapeRight, "")
runeText := []rune(stripped)
@ -140,7 +141,7 @@ func (a *ansiUtils) lenWithoutANSI(text string) int {
func (a *ansiUtils) generateHyperlink(text string) string {
// hyperlink matching
results := findNamedRegexMatch("(?P<all>(?:\\[(?P<name>.+)\\])(?:\\((?P<url>.*)\\)))", text)
results := regex.FindNamedRegexMatch("(?P<all>(?:\\[(?P<name>.+)\\])(?:\\((?P<url>.*)\\)))", text)
if len(results) != 3 {
return text
}
@ -151,7 +152,7 @@ func (a *ansiUtils) generateHyperlink(text string) string {
}
func (a *ansiUtils) formatText(text string) string {
results := findAllNamedRegexMatch("(?P<context><(?P<format>[buis])>(?P<text>[^<]+)</[buis]>)", text)
results := regex.FindAllNamedRegexMatch("(?P<context><(?P<format>[buis])>(?P<text>[^<]+)</[buis]>)", text)
for _, result := range results {
var formatted string
switch result["format"] {

View file

@ -1,6 +1,7 @@
package main
import (
"oh-my-posh/environment"
"sync"
"time"
)
@ -33,7 +34,7 @@ type Block struct {
Segments []*Segment `config:"segments"`
Newline bool `config:"newline"`
env Environment
env environment.Environment
writer promptWriter
ansi *ansiUtils
activeSegment *Segment
@ -42,13 +43,13 @@ type Block struct {
activeForeground string
}
func (b *Block) init(env Environment, writer promptWriter, ansi *ansiUtils) {
func (b *Block) init(env environment.Environment, writer promptWriter, ansi *ansiUtils) {
b.env = env
b.writer = writer
b.ansi = ansi
}
func (b *Block) initPlain(env Environment, config *Config) {
func (b *Block) initPlain(env environment.Environment, config *Config) {
b.ansi = &ansiUtils{}
b.ansi.init(plain)
b.writer = &AnsiWriter{

View file

@ -2,13 +2,14 @@ package main
import (
"fmt"
"oh-my-posh/environment"
"github.com/gookit/color"
)
// MakeColors creates instance of AnsiColors to use in AnsiWriter according to
// environment and configuration.
func MakeColors(env Environment, cfg *Config) AnsiColors {
func MakeColors(env environment.Environment, cfg *Config) AnsiColors {
cacheDisabled := env.Getenv("OMP_CACHE_DISABLED") == "1"
return makeColors(cfg.Palette, !cacheDisabled)
}

View file

@ -7,6 +7,7 @@ import (
json2 "encoding/json"
"errors"
"fmt"
"oh-my-posh/environment"
"os"
"strconv"
"strings"
@ -56,7 +57,7 @@ func printConfigError(err error, eval bool) {
}
// GetConfig returns the default configuration including possible user overrides
func GetConfig(env Environment) *Config {
func GetConfig(env environment.Environment) *Config {
cfg, err := loadConfig(env)
if err != nil {
return getDefaultConfig(err.Error())
@ -64,7 +65,7 @@ func GetConfig(env Environment) *Config {
return cfg
}
func loadConfig(env Environment) (*Config, error) {
func loadConfig(env environment.Environment) (*Config, error) {
var cfg Config
configFile := *env.Args().Config
eval := *env.Args().Eval

View file

@ -2,11 +2,12 @@ package main
import (
"fmt"
"oh-my-posh/environment"
"strings"
)
type consoleTitle struct {
env Environment
env environment.Environment
config *Config
ansi *ansiUtils
}
@ -33,7 +34,7 @@ func (t *consoleTitle) getConsoleTitle() string {
case FolderName:
fallthrough
default:
title = base(t.getPwd(), t.env)
title = environment.Base(t.env, t.getPwd())
}
title = t.ansi.escapeText(title)
return fmt.Sprintf(t.ansi.title, title)

View file

@ -1,6 +1,8 @@
package main
import (
"oh-my-posh/environment"
"oh-my-posh/mock"
"testing"
"github.com/stretchr/testify/assert"
@ -52,11 +54,11 @@ func TestGetConsoleTitle(t *testing.T) {
ConsoleTitleStyle: tc.Style,
ConsoleTitleTemplate: tc.Template,
}
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("Pwd").Return(tc.Cwd)
env.On("Home").Return("/usr/home")
env.On("PathSeperator").Return(tc.PathSeperator)
env.On("TemplateCache").Return(&TemplateCache{
env.On("TemplateCache").Return(&environment.TemplateCache{
Env: map[string]string{
"USERDOMAIN": "MyCompany",
},
@ -65,7 +67,7 @@ func TestGetConsoleTitle(t *testing.T) {
Root: tc.Root,
HostName: "MyHost",
PWD: tc.Cwd,
Folder: base(tc.Cwd, env),
Folder: "vagrant",
})
ansi := &ansiUtils{}
ansi.init(tc.ShellName)
@ -113,10 +115,10 @@ func TestGetConsoleTitleIfGethostnameReturnsError(t *testing.T) {
ConsoleTitleStyle: tc.Style,
ConsoleTitleTemplate: tc.Template,
}
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("Pwd").Return(tc.Cwd)
env.On("Home").Return("/usr/home")
env.On("TemplateCache").Return(&TemplateCache{
env.On("TemplateCache").Return(&environment.TemplateCache{
Env: map[string]string{
"USERDOMAIN": "MyCompany",
},

View file

@ -1,33 +0,0 @@
package main
const (
FHSS WifiType = "FHSS"
DSSS WifiType = "DSSS"
IR WifiType = "IR"
A WifiType = "802.11a"
HRDSSS WifiType = "HRDSSS"
G WifiType = "802.11g"
N WifiType = "802.11n"
AC WifiType = "802.11ac"
Infrastructure WifiType = "Infrastructure"
Independent WifiType = "Independent"
Any WifiType = "Any"
OpenSystem WifiType = "802.11 Open System"
SharedKey WifiType = "802.11 Shared Key"
WPA WifiType = "WPA"
WPAPSK WifiType = "WPA PSK"
WPANone WifiType = "WPA NONE"
WPA2 WifiType = "WPA2"
WPA2PSK WifiType = "WPA2 PSK"
Disabled WifiType = "disabled"
Unknown WifiType = "Unknown"
None WifiType = "None"
WEP40 WifiType = "WEP40"
TKIP WifiType = "TKIP"
CCMP WifiType = "CCMP"
WEP104 WifiType = "WEP104"
WEP WifiType = "WEP"
)

View file

@ -2,13 +2,14 @@ package main
import (
"fmt"
"oh-my-posh/environment"
"strings"
"time"
)
type engine struct {
config *Config
env Environment
env environment.Environment
writer promptWriter
ansi *ansiUtils
consoleTitle *consoleTitle

View file

@ -2,6 +2,8 @@ package main
import (
"errors"
"oh-my-posh/environment"
"oh-my-posh/mock"
"os"
"path/filepath"
"strings"
@ -29,7 +31,7 @@ func TestCanWriteRPrompt(t *testing.T) {
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("TerminalWidth").Return(tc.TerminalWidth, tc.TerminalWidthError)
ansi := &ansiUtils{}
ansi.init(plain)
@ -73,7 +75,7 @@ func engineRender(configPath string) error {
execTime = 917.0
)
args := &Args{
args := &environment.Args{
Debug: &debug,
Config: &configPath,
Eval: &eval,
@ -85,8 +87,8 @@ func engineRender(configPath string) error {
ExecutionTime: &execTime,
}
env := &environment{}
env.init(args)
env := &environment.ShellEnvironment{}
env.Init(args)
defer env.Close()
cfg := GetConfig(env)

View file

@ -1,4 +1,4 @@
package main
package environment
import (
"encoding/json"

View file

@ -1,4 +1,4 @@
package main
package environment
import "sync"

View file

@ -1,4 +1,4 @@
package main
package environment
import (
"net/http"

View file

@ -1,4 +1,4 @@
package main
package environment
import (
"bytes"
@ -8,6 +8,7 @@ import (
"io/ioutil"
"log"
"net/http"
"oh-my-posh/regex"
"os"
"os/exec"
"path/filepath"
@ -20,24 +21,53 @@ import (
)
const (
unknown = "unknown"
windowsPlatform = "windows"
darwinPlatform = "darwin"
linuxPlatform = "linux"
Unknown = "unknown"
WindowsPlatform = "windows"
DarwinPlatform = "darwin"
LinuxPlatform = "linux"
)
type commandError struct {
err string
exitCode int
type Args struct {
ErrorCode *int
PrintConfig *bool
ConfigFormat *string
PrintShell *bool
Config *string
Shell *string
PWD *string
PSWD *string
Version *bool
Debug *bool
ExecutionTime *float64
Millis *bool
Eval *bool
Init *bool
PrintInit *bool
ExportPNG *bool
Author *string
CursorPadding *int
RPromptOffset *int
RPrompt *bool
BGColor *string
StackCount *int
Command *string
PrintTransient *bool
Plain *bool
CachePath *bool
}
func (e *commandError) Error() string {
return e.err
type CommandError struct {
Err string
ExitCode int
}
type noBatteryError struct{}
func (e *CommandError) Error() string {
return e.Err
}
func (m *noBatteryError) Error() string {
type NoBatteryError struct{}
func (m *NoBatteryError) Error() string {
return "no battery"
}
@ -57,19 +87,19 @@ type Cache interface {
type HTTPRequestModifier func(request *http.Request)
type windowsRegistryValueType int
type WindowsRegistryValueType int
const (
regQword windowsRegistryValueType = iota
regDword
regString
RegQword WindowsRegistryValueType = iota
RegDword
RegString
)
type WindowsRegistryValue struct {
valueType windowsRegistryValueType
qword uint64
dword uint32
str string
ValueType WindowsRegistryValueType
Qword uint64
Dword uint32
Str string
}
type WifiType string
@ -88,6 +118,19 @@ type WifiInfo struct {
Error string
}
type TemplateCache struct {
Root bool
PWD string
Folder string
Shell string
UserName string
HostName string
Code int
Env map[string]string
OS string
WSL bool
}
type Environment interface {
Getenv(key string) string
Pwd() string
@ -154,7 +197,7 @@ const (
Debug logType = "debug"
)
type environment struct {
type ShellEnvironment struct {
args *Args
cwd string
cmdCache *commandCache
@ -164,11 +207,11 @@ type environment struct {
debug bool
}
func (env *environment) init(args *Args) {
func (env *ShellEnvironment) Init(args *Args) {
env.args = args
env.fileCache = &fileCache{}
env.fileCache.Init(env.CachePath())
env.resolveConfigPath()
env.ResolveConfigPath()
env.cmdCache = &commandCache{
commands: newConcurrentMap(),
}
@ -178,13 +221,13 @@ func (env *environment) init(args *Args) {
}
}
func (env *environment) resolveConfigPath() {
func (env *ShellEnvironment) ResolveConfigPath() {
if env.args == nil || env.args.Config == nil || len(*env.args.Config) == 0 {
return
}
// 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.Platform() == windowsPlatform && env.Shell() == bash {
if env.Platform() == WindowsPlatform && env.Shell() == "bash" {
return
}
configFile := *env.args.Config
@ -200,7 +243,7 @@ func (env *environment) resolveConfigPath() {
*env.args.Config = filepath.Clean(configFile)
}
func (env *environment) trace(start time.Time, function string, args ...string) {
func (env *ShellEnvironment) trace(start time.Time, function string, args ...string) {
if !env.debug {
return
}
@ -209,7 +252,7 @@ func (env *environment) trace(start time.Time, function string, args ...string)
log.Println(trace)
}
func (env *environment) log(lt logType, function, message string) {
func (env *ShellEnvironment) log(lt logType, function, message string) {
if !env.debug {
return
}
@ -217,14 +260,14 @@ func (env *environment) log(lt logType, function, message string) {
log.Println(trace)
}
func (env *environment) Getenv(key string) string {
func (env *ShellEnvironment) Getenv(key string) string {
defer env.trace(time.Now(), "Getenv", key)
val := os.Getenv(key)
env.log(Debug, "Getenv", val)
return val
}
func (env *environment) Pwd() string {
func (env *ShellEnvironment) Pwd() string {
defer env.trace(time.Now(), "Pwd")
defer func() {
env.log(Debug, "Pwd", env.cwd)
@ -234,7 +277,7 @@ func (env *environment) Pwd() string {
}
correctPath := func(pwd string) string {
// on Windows, and being case sensitive and not consistent and all, this gives silly issues
driveLetter := getCompiledRegex(`^[a-z]:`)
driveLetter := regex.GetCompiledRegex(`^[a-z]:`)
return driveLetter.ReplaceAllStringFunc(pwd, strings.ToUpper)
}
if env.args != nil && *env.args.PWD != "" {
@ -250,7 +293,7 @@ func (env *environment) Pwd() string {
return env.cwd
}
func (env *environment) HasFiles(pattern string) bool {
func (env *ShellEnvironment) HasFiles(pattern string) bool {
defer env.trace(time.Now(), "HasFiles", pattern)
cwd := env.Pwd()
pattern = cwd + env.PathSeperator() + pattern
@ -262,7 +305,7 @@ func (env *environment) HasFiles(pattern string) bool {
return len(matches) > 0
}
func (env *environment) HasFilesInDir(dir, pattern string) bool {
func (env *ShellEnvironment) HasFilesInDir(dir, pattern string) bool {
defer env.trace(time.Now(), "HasFilesInDir", pattern)
pattern = dir + env.PathSeperator() + pattern
matches, err := filepath.Glob(pattern)
@ -273,13 +316,13 @@ func (env *environment) HasFilesInDir(dir, pattern string) bool {
return len(matches) > 0
}
func (env *environment) HasFolder(folder string) bool {
func (env *ShellEnvironment) HasFolder(folder string) bool {
defer env.trace(time.Now(), "HasFolder", folder)
_, err := os.Stat(folder)
return !os.IsNotExist(err)
}
func (env *environment) FileContent(file string) string {
func (env *ShellEnvironment) FileContent(file string) string {
defer env.trace(time.Now(), "FileContent", file)
content, err := ioutil.ReadFile(file)
if err != nil {
@ -289,7 +332,7 @@ func (env *environment) FileContent(file string) string {
return string(content)
}
func (env *environment) FolderList(path string) []string {
func (env *ShellEnvironment) FolderList(path string) []string {
defer env.trace(time.Now(), "FolderList", path)
content, err := os.ReadDir(path)
if err != nil {
@ -305,12 +348,12 @@ func (env *environment) FolderList(path string) []string {
return folderNames
}
func (env *environment) PathSeperator() string {
func (env *ShellEnvironment) PathSeperator() string {
defer env.trace(time.Now(), "PathSeperator")
return string(os.PathSeparator)
}
func (env *environment) User() string {
func (env *ShellEnvironment) User() string {
defer env.trace(time.Now(), "User")
user := os.Getenv("USER")
if user == "" {
@ -319,7 +362,7 @@ func (env *environment) User() string {
return user
}
func (env *environment) Host() (string, error) {
func (env *ShellEnvironment) Host() (string, error) {
defer env.trace(time.Now(), "Host")
hostName, err := os.Hostname()
if err != nil {
@ -329,12 +372,12 @@ func (env *environment) Host() (string, error) {
return cleanHostName(hostName), nil
}
func (env *environment) GOOS() string {
func (env *ShellEnvironment) GOOS() string {
defer env.trace(time.Now(), "GOOS")
return runtime.GOOS
}
func (env *environment) RunCommand(command string, args ...string) (string, error) {
func (env *ShellEnvironment) 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
@ -356,13 +399,13 @@ func (env *environment) RunCommand(command string, args ...string) (string, erro
return output, nil
}
func (env *environment) RunShellCommand(shell, command string) string {
func (env *ShellEnvironment) 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 {
func (env *ShellEnvironment) HasCommand(command string) bool {
defer env.trace(time.Now(), "HasCommand", command)
if _, ok := env.cmdCache.get(command); ok {
return true
@ -376,12 +419,12 @@ func (env *environment) HasCommand(command string) bool {
return false
}
func (env *environment) ErrorCode() int {
func (env *ShellEnvironment) ErrorCode() int {
defer env.trace(time.Now(), "ErrorCode")
return *env.args.ErrorCode
}
func (env *environment) ExecutionTime() float64 {
func (env *ShellEnvironment) ExecutionTime() float64 {
defer env.trace(time.Now(), "ExecutionTime")
if *env.args.ExecutionTime < 0 {
return 0
@ -389,12 +432,12 @@ func (env *environment) ExecutionTime() float64 {
return *env.args.ExecutionTime
}
func (env *environment) Args() *Args {
func (env *ShellEnvironment) Args() *Args {
defer env.trace(time.Now(), "Args")
return env.args
}
func (env *environment) BatteryInfo() ([]*battery.Battery, error) {
func (env *ShellEnvironment) BatteryInfo() ([]*battery.Battery, error) {
defer env.trace(time.Now(), "BatteryInfo")
batteries, err := battery.GetAll()
// actual error, return it
@ -404,7 +447,7 @@ func (env *environment) BatteryInfo() ([]*battery.Battery, error) {
}
// there are no batteries found
if len(batteries) == 0 {
return nil, &noBatteryError{}
return nil, &NoBatteryError{}
}
// some batteries fail to get retrieved, filter them out if present
validBatteries := []*battery.Battery{}
@ -454,7 +497,7 @@ func (env *environment) BatteryInfo() ([]*battery.Battery, error) {
return validBatteries, nil
}
func (env *environment) Shell() string {
func (env *ShellEnvironment) Shell() string {
defer env.trace(time.Now(), "Shell")
if *env.args.Shell != "" {
return *env.args.Shell
@ -464,7 +507,7 @@ func (env *environment) Shell() string {
name, err := p.Name()
if err != nil {
env.log(Error, "Shell", err.Error())
return unknown
return Unknown
}
if name == "cmd.exe" {
p, _ = p.Parent()
@ -472,14 +515,14 @@ func (env *environment) Shell() string {
}
if err != nil {
env.log(Error, "Shell", err.Error())
return unknown
return Unknown
}
// Cache the shell value to speed things up.
*env.args.Shell = strings.Trim(strings.Replace(name, ".exe", "", 1), " ")
return *env.args.Shell
}
func (env *environment) HTTPRequest(url string, timeout int, requestModifiers ...HTTPRequestModifier) ([]byte, error) {
func (env *ShellEnvironment) HTTPRequest(url string, timeout int, requestModifiers ...HTTPRequestModifier) ([]byte, error) {
defer env.trace(time.Now(), "HTTPRequest", url)
ctx, cncl := context.WithTimeout(context.Background(), time.Millisecond*time.Duration(timeout))
defer cncl()
@ -504,7 +547,7 @@ func (env *environment) HTTPRequest(url string, timeout int, requestModifiers ..
return body, nil
}
func (env *environment) HasParentFilePath(path string) (*FileInfo, error) {
func (env *ShellEnvironment) HasParentFilePath(path string) (*FileInfo, error) {
defer env.trace(time.Now(), "HasParentFilePath", path)
currentFolder := env.Pwd()
for {
@ -529,7 +572,7 @@ func (env *environment) HasParentFilePath(path string) (*FileInfo, error) {
}
}
func (env *environment) StackCount() int {
func (env *ShellEnvironment) StackCount() int {
defer env.trace(time.Now(), "StackCount")
if *env.args.StackCount < 0 {
return 0
@ -537,19 +580,19 @@ func (env *environment) StackCount() int {
return *env.args.StackCount
}
func (env *environment) Cache() Cache {
func (env *ShellEnvironment) Cache() Cache {
return env.fileCache
}
func (env *environment) Close() {
func (env *ShellEnvironment) Close() {
env.fileCache.Close()
}
func (env *environment) Logs() string {
func (env *ShellEnvironment) Logs() string {
return env.logBuilder.String()
}
func (env *environment) TemplateCache() *TemplateCache {
func (env *ShellEnvironment) TemplateCache() *TemplateCache {
defer env.trace(time.Now(), "TemplateCache")
if env.tmplCache != nil {
return env.tmplCache
@ -575,7 +618,7 @@ func (env *environment) TemplateCache() *TemplateCache {
pwd := env.Pwd()
pwd = strings.Replace(pwd, env.Home(), "~", 1)
tmplCache.PWD = pwd
tmplCache.Folder = base(pwd, env)
tmplCache.Folder = Base(env, pwd)
tmplCache.UserName = env.User()
if host, err := env.Host(); err == nil {
tmplCache.HostName = host
@ -586,6 +629,60 @@ func (env *environment) TemplateCache() *TemplateCache {
return env.tmplCache
}
func DirMatchesOneOf(env Environment, dir string, regexes []string) bool {
normalizedCwd := strings.ReplaceAll(dir, "\\", "/")
normalizedHomeDir := strings.ReplaceAll(env.Home(), "\\", "/")
for _, element := range regexes {
normalizedElement := strings.ReplaceAll(element, "\\\\", "/")
if strings.HasPrefix(normalizedElement, "~") {
normalizedElement = strings.Replace(normalizedElement, "~", normalizedHomeDir, 1)
}
pattern := fmt.Sprintf("^%s$", normalizedElement)
goos := env.GOOS()
if goos == WindowsPlatform || goos == DarwinPlatform {
pattern = "(?i)" + pattern
}
matched := regex.MatchString(pattern, normalizedCwd)
if matched {
return true
}
}
return false
}
// Base returns the last element of path.
// Trailing path separators are removed before extracting the last element.
// If the path consists entirely of separators, Base returns a single separator.
func Base(env Environment, path string) string {
if path == "/" {
return path
}
volumeName := filepath.VolumeName(path)
// Strip trailing slashes.
for len(path) > 0 && string(path[len(path)-1]) == env.PathSeperator() {
path = path[0 : len(path)-1]
}
if volumeName == path {
return path
}
// Throw away volume name
path = path[len(filepath.VolumeName(path)):]
// Find the last element
i := len(path) - 1
for i >= 0 && string(path[i]) != env.PathSeperator() {
i--
}
if i >= 0 {
path = path[i+1:]
}
// If empty now, it had only slashes.
if path == "" {
return env.PathSeperator()
}
return path
}
func cleanHostName(hostName string) string {
garbage := []string{
".lan",

View file

@ -1,4 +1,4 @@
package main
package environment
import (
"testing"
@ -36,7 +36,7 @@ func TestWindowsPathWithDriveLetter(t *testing.T) {
{Case: "registry drive", CWD: `HKLM:\SOFTWARE\magnetic:test\`, Expected: `HKLM:\SOFTWARE\magnetic:test\`},
}
for _, tc := range cases {
env := &environment{
env := &ShellEnvironment{
args: &Args{
PWD: &tc.CWD,
},

View file

@ -1,6 +1,6 @@
//go:build !windows
package main
package environment
import (
"errors"
@ -12,20 +12,20 @@ import (
terminal "github.com/wayneashleyberry/terminal-dimensions"
)
func (env *environment) Root() bool {
func (env *ShellEnvironment) Root() bool {
defer env.trace(time.Now(), "Root")
return os.Geteuid() == 0
}
func (env *environment) Home() string {
func (env *ShellEnvironment) Home() string {
return os.Getenv("HOME")
}
func (env *environment) WindowTitle(imageName, windowTitleRegex string) (string, error) {
func (env *ShellEnvironment) WindowTitle(imageName, windowTitleRegex string) (string, error) {
return "", errors.New("not implemented")
}
func (env *environment) IsWsl() bool {
func (env *ShellEnvironment) IsWsl() bool {
defer env.trace(time.Now(), "IsWsl")
// one way to check
// version := env.FileContent("/proc/version")
@ -34,7 +34,7 @@ func (env *environment) IsWsl() bool {
return env.Getenv("WSL_DISTRO_NAME") != ""
}
func (env *environment) IsWsl2() bool {
func (env *ShellEnvironment) IsWsl2() bool {
defer env.trace(time.Now(), "IsWsl2")
if !env.IsWsl() {
return false
@ -43,7 +43,7 @@ func (env *environment) IsWsl2() bool {
return strings.Contains(uname, "WSL2")
}
func (env *environment) TerminalWidth() (int, error) {
func (env *ShellEnvironment) TerminalWidth() (int, error) {
defer env.trace(time.Now(), "TerminalWidth")
width, err := terminal.Width()
if err != nil {
@ -52,7 +52,7 @@ func (env *environment) TerminalWidth() (int, error) {
return int(width), err
}
func (env *environment) Platform() string {
func (env *ShellEnvironment) Platform() string {
const key = "environment_platform"
if val, found := env.Cache().Get(key); found {
return val
@ -69,7 +69,7 @@ func (env *environment) Platform() string {
return platform
}
func (env *environment) CachePath() string {
func (env *ShellEnvironment) 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 {
@ -82,15 +82,15 @@ func (env *environment) CachePath() string {
return env.Home()
}
func (env *environment) WindowsRegistryKeyValue(path string) (*WindowsRegistryValue, error) {
func (env *ShellEnvironment) WindowsRegistryKeyValue(path string) (*WindowsRegistryValue, error) {
return nil, errors.New("not implemented")
}
func (env *environment) InWSLSharedDrive() bool {
func (env *ShellEnvironment) InWSLSharedDrive() bool {
return env.IsWsl() && strings.HasPrefix(env.Pwd(), "/mnt/")
}
func (env *environment) ConvertToWindowsPath(path string) string {
func (env *ShellEnvironment) ConvertToWindowsPath(path string) string {
windowsPath, err := env.RunCommand("wslpath", "-w", path)
if err == nil {
return windowsPath
@ -98,7 +98,7 @@ func (env *environment) ConvertToWindowsPath(path string) string {
return path
}
func (env *environment) ConvertToLinuxPath(path string) string {
func (env *ShellEnvironment) ConvertToLinuxPath(path string) string {
linuxPath, err := env.RunCommand("wslpath", "-u", path)
if err == nil {
return linuxPath
@ -106,6 +106,6 @@ func (env *environment) ConvertToLinuxPath(path string) string {
return path
}
func (env *environment) WifiNetwork() (*WifiInfo, error) {
func (env *ShellEnvironment) WifiNetwork() (*WifiInfo, error) {
return nil, errors.New("not implemented")
}

View file

@ -1,6 +1,6 @@
//go:build windows
package main
package environment
import (
"errors"
@ -16,7 +16,7 @@ import (
"golang.org/x/sys/windows"
)
func (env *environment) Root() bool {
func (env *ShellEnvironment) Root() bool {
defer env.trace(time.Now(), "Root")
var sid *windows.SID
@ -53,7 +53,7 @@ func (env *environment) Root() bool {
return member
}
func (env *environment) Home() string {
func (env *ShellEnvironment) Home() string {
home := os.Getenv("HOME")
defer func() {
env.log(Debug, "Home", home)
@ -69,22 +69,22 @@ func (env *environment) Home() string {
return home
}
func (env *environment) WindowTitle(imageName, windowTitleRegex string) (string, error) {
func (env *ShellEnvironment) WindowTitle(imageName, windowTitleRegex string) (string, error) {
defer env.trace(time.Now(), "WindowTitle", imageName, windowTitleRegex)
return WindowTitle(imageName, windowTitleRegex)
}
func (env *environment) IsWsl() bool {
func (env *ShellEnvironment) IsWsl() bool {
defer env.trace(time.Now(), "IsWsl")
return false
}
func (env *environment) IsWsl2() bool {
func (env *ShellEnvironment) IsWsl2() bool {
defer env.trace(time.Now(), "IsWsl2")
return false
}
func (env *environment) TerminalWidth() (int, error) {
func (env *ShellEnvironment) TerminalWidth() (int, error) {
defer env.trace(time.Now(), "TerminalWidth")
handle, err := syscall.Open("CONOUT$", syscall.O_RDWR, 0)
if err != nil {
@ -100,11 +100,11 @@ func (env *environment) TerminalWidth() (int, error) {
return int(info.Size.X), nil
}
func (env *environment) Platform() string {
return windowsPlatform
func (env *ShellEnvironment) Platform() string {
return WindowsPlatform
}
func (env *environment) CachePath() string {
func (env *ShellEnvironment) CachePath() string {
defer env.trace(time.Now(), "CachePath")
// get LOCALAPPDATA if present
if cachePath := returnOrBuildCachePath(env.Getenv("LOCALAPPDATA")); len(cachePath) != 0 {
@ -123,7 +123,7 @@ func (env *environment) CachePath() string {
//
// Returns a variant type if successful; nil and an error if not.
//
func (env *environment) WindowsRegistryKeyValue(path string) (*windowsRegistryValue, error) {
func (env *ShellEnvironment) WindowsRegistryKeyValue(path string) (*WindowsRegistryValue, error) {
env.trace(time.Now(), "WindowsRegistryKeyValue", path)
// Format:
@ -234,34 +234,34 @@ func (env *environment) WindowsRegistryKeyValue(path string) (*windowsRegistryVa
valueString := windows.UTF16PtrToString(uint16p)
env.log(Debug, "WindowsRegistryKeyValue", fmt.Sprintf("success, string: %s", valueString))
return &windowsRegistryValue{valueType: regString, str: valueString}, nil
return &WindowsRegistryValue{ValueType: RegString, Str: valueString}, nil
case windows.REG_DWORD:
var uint32p *uint32
uint32p = (*uint32)(unsafe.Pointer(&keyBuf[0])) // more casting goodness
env.log(Debug, "WindowsRegistryKeyValue", fmt.Sprintf("success, DWORD, 0x%08X", *uint32p))
return &windowsRegistryValue{valueType: regDword, dword: *uint32p}, nil
return &WindowsRegistryValue{ValueType: RegDword, Dword: *uint32p}, nil
case windows.REG_QWORD:
var uint64p *uint64
uint64p = (*uint64)(unsafe.Pointer(&keyBuf[0])) // more casting goodness
env.log(Debug, "WindowsRegistryKeyValue", fmt.Sprintf("success, QWORD, 0x%016X", *uint64p))
return &windowsRegistryValue{valueType: regQword, qword: *uint64p}, nil
return &WindowsRegistryValue{ValueType: RegQword, Qword: *uint64p}, nil
default:
errorLogMsg := fmt.Sprintf("Error, no formatter for REG_? type:%d, data size:%d bytes", keyBufType, keyBufSize)
return nil, errors.New(errorLogMsg)
}
}
func (env *environment) InWSLSharedDrive() bool {
func (env *ShellEnvironment) InWSLSharedDrive() bool {
return false
}
func (env *environment) ConvertToWindowsPath(path string) string {
func (env *ShellEnvironment) ConvertToWindowsPath(path string) string {
return path
}
func (env *environment) ConvertToLinuxPath(path string) string {
func (env *ShellEnvironment) ConvertToLinuxPath(path string) string {
return path
}
@ -273,7 +273,38 @@ var (
hWlanQueryInterface = hapi.NewProc("WlanQueryInterface")
)
func (env *environment) WifiNetwork() (*wifiInfo, error) {
const (
FHSS WifiType = "FHSS"
DSSS WifiType = "DSSS"
IR WifiType = "IR"
A WifiType = "802.11a"
HRDSSS WifiType = "HRDSSS"
G WifiType = "802.11g"
N WifiType = "802.11n"
AC WifiType = "802.11ac"
Infrastructure WifiType = "Infrastructure"
Independent WifiType = "Independent"
Any WifiType = "Any"
OpenSystem WifiType = "802.11 Open System"
SharedKey WifiType = "802.11 Shared Key"
WPA WifiType = "WPA"
WPAPSK WifiType = "WPA PSK"
WPANone WifiType = "WPA NONE"
WPA2 WifiType = "WPA2"
WPA2PSK WifiType = "WPA2 PSK"
Disabled WifiType = "disabled"
None WifiType = "None"
WEP40 WifiType = "WEP40"
TKIP WifiType = "TKIP"
CCMP WifiType = "CCMP"
WEP104 WifiType = "WEP104"
WEP WifiType = "WEP"
)
func (env *ShellEnvironment) WifiNetwork() (*WifiInfo, error) {
env.trace(time.Now(), "WifiNetwork")
// Open handle
var pdwNegotiatedVersion uint32
@ -308,8 +339,8 @@ func (env *environment) WifiNetwork() (*wifiInfo, error) {
return nil, errors.New("Not connected")
}
func (env *environment) parseNetworkInterface(network *WLAN_INTERFACE_INFO, clientHandle uint32) (*wifiInfo, error) {
info := wifiInfo{}
func (env *ShellEnvironment) parseNetworkInterface(network *WLAN_INTERFACE_INFO, clientHandle uint32) (*WifiInfo, error) {
info := WifiInfo{}
info.Interface = strings.TrimRight(string(utf16.Decode(network.strInterfaceDescription[:])), "\x00")
// Query wifi connection state

View file

@ -1,9 +1,10 @@
//go:build windows
package main
package environment
import (
"fmt"
"oh-my-posh/regex"
"strings"
"syscall"
"unsafe"
@ -162,7 +163,7 @@ func GetWindowTitle(pid int, windowTitleRegex string) (syscall.Handle, string) {
return 1 // continue enumeration
}
title = syscall.UTF16ToString(b)
if matchString(windowTitleRegex, title) {
if regex.MatchString(windowTitleRegex, title) {
// will cause EnumWindows to return 0 (error)
// but we don't want to enumerate all windows since we got what we want
hwnd = h

View file

@ -26,6 +26,7 @@ import (
_ "embed"
"fmt"
"math"
"oh-my-posh/regex"
"strconv"
"strings"
@ -421,8 +422,8 @@ func (ir *ImageRenderer) SavePNG(path string) error {
}
func (ir *ImageRenderer) shouldPrint() bool {
for sequence, regex := range ir.ansiSequenceRegexMap {
match := findNamedRegexMatch(regex, ir.ansiString)
for sequence, re := range ir.ansiSequenceRegexMap {
match := regex.FindNamedRegexMatch(re, ir.ansiString)
if len(match) == 0 {
continue
}

View file

@ -4,6 +4,8 @@ import (
_ "embed"
"flag"
"fmt"
"oh-my-posh/environment"
"oh-my-posh/regex"
"os"
"strings"
"time"
@ -40,37 +42,8 @@ const (
plain = "shell"
)
type Args struct {
ErrorCode *int
PrintConfig *bool
ConfigFormat *string
PrintShell *bool
Config *string
Shell *string
PWD *string
PSWD *string
Version *bool
Debug *bool
ExecutionTime *float64
Millis *bool
Eval *bool
Init *bool
PrintInit *bool
ExportPNG *bool
Author *string
CursorPadding *int
RPromptOffset *int
RPrompt *bool
BGColor *string
StackCount *int
Command *string
PrintTransient *bool
Plain *bool
CachePath *bool
}
func main() {
args := &Args{
args := &environment.Args{
ErrorCode: flag.Int(
"error",
0,
@ -181,8 +154,8 @@ func main() {
fmt.Println(Version)
return
}
env := &environment{}
env.init(args)
env := &environment.ShellEnvironment{}
env.Init(args)
defer env.Close()
if *args.PrintShell {
fmt.Println(env.Shell())
@ -267,7 +240,7 @@ func main() {
ansi: ansi,
}
imageCreator.init()
match := findNamedRegexMatch(`.*(\/|\\)(?P<STR>.+).omp.(json|yaml|toml)`, *args.Config)
match := regex.FindNamedRegexMatch(`.*(\/|\\)(?P<STR>.+).omp.(json|yaml|toml)`, *args.Config)
err := imageCreator.SavePNG(fmt.Sprintf("%s.png", match[str]))
if err != nil {
fmt.Print(err.Error())
@ -332,7 +305,7 @@ func getShellInitScript(executable, configFile, script string) string {
return script
}
func getConsoleBackgroundColor(env Environment, backgroundColorTemplate string) string {
func getConsoleBackgroundColor(env environment.Environment, backgroundColorTemplate string) string {
if len(backgroundColorTemplate) == 0 {
return backgroundColorTemplate
}

View file

@ -1,6 +1,8 @@
package main
import (
"oh-my-posh/environment"
"oh-my-posh/mock"
"testing"
"github.com/stretchr/testify/assert"
@ -17,8 +19,8 @@ func TestConsoleBackgroundColorTemplate(t *testing.T) {
}
for _, tc := range cases {
env := new(MockedEnvironment)
env.On("TemplateCache").Return(&TemplateCache{
env := new(mock.MockedEnvironment)
env.On("TemplateCache").Return(&environment.TemplateCache{
Env: map[string]string{
"TERM_PROGRAM": tc.Term,
},
@ -27,3 +29,40 @@ func TestConsoleBackgroundColorTemplate(t *testing.T) {
assert.Equal(t, tc.Expected, color, tc.Case)
}
}
// This can only be tested here due to circular dependencies
// Which might be an indaction of a fault architecture but
// I honestly could not figure out how to do this better
// without making the solution worse.
func TestDirMatchesOneOf(t *testing.T) {
cases := []struct {
GOOS string
HomeDir string
Dir string
Pattern string
Expected bool
}{
{GOOS: environment.LinuxPlatform, HomeDir: "/home/bill", Dir: "/home/bill", Pattern: "/home/bill", Expected: true},
{GOOS: environment.LinuxPlatform, HomeDir: "/home/bill", Dir: "/home/bill/foo", Pattern: "~/foo", Expected: true},
{GOOS: environment.LinuxPlatform, HomeDir: "/home/bill", Dir: "/home/bill/foo", Pattern: "~/Foo", Expected: false},
{GOOS: environment.LinuxPlatform, HomeDir: "/home/bill", Dir: "/home/bill/foo", Pattern: "~\\\\foo", Expected: true},
{GOOS: environment.LinuxPlatform, HomeDir: "/home/bill", Dir: "/home/bill/foo/bar", Pattern: "~/fo.*", Expected: true},
{GOOS: environment.LinuxPlatform, HomeDir: "/home/bill", Dir: "/home/bill/foo", Pattern: "~/fo\\w", Expected: true},
{GOOS: environment.WindowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill", Pattern: "C:\\\\Users\\\\Bill", Expected: true},
{GOOS: environment.WindowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill", Pattern: "C:/Users/Bill", Expected: true},
{GOOS: environment.WindowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill", Pattern: "c:/users/bill", Expected: true},
{GOOS: environment.WindowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill", Pattern: "~", Expected: true},
{GOOS: environment.WindowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill\\Foo", Pattern: "~/Foo", Expected: true},
{GOOS: environment.WindowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill\\Foo", Pattern: "~/foo", Expected: true},
{GOOS: environment.WindowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill\\Foo\\Bar", Pattern: "~/fo.*", Expected: true},
{GOOS: environment.WindowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill\\Foo", Pattern: "~/fo\\w", Expected: true},
}
for _, tc := range cases {
env := new(mock.MockedEnvironment)
env.On("GOOS").Return(tc.GOOS)
env.On("Home").Return(tc.HomeDir)
got := environment.DirMatchesOneOf(env, tc.Dir, []string{tc.Pattern})
assert.Equal(t, tc.Expected, got)
}
}

View file

@ -1,4 +1,4 @@
package main
package mock
import mock "github.com/stretchr/testify/mock"

211
src/mock/environment.go Normal file
View file

@ -0,0 +1,211 @@
package mock
import (
"oh-my-posh/environment"
"github.com/distatus/battery"
mock "github.com/stretchr/testify/mock"
)
type MockedEnvironment struct {
mock.Mock
}
func (env *MockedEnvironment) Getenv(key string) string {
args := env.Called(key)
return args.String(0)
}
func (env *MockedEnvironment) Pwd() string {
args := env.Called()
return args.String(0)
}
func (env *MockedEnvironment) Home() string {
args := env.Called()
return args.String(0)
}
func (env *MockedEnvironment) HasFiles(pattern string) bool {
args := env.Called(pattern)
return args.Bool(0)
}
func (env *MockedEnvironment) HasFilesInDir(dir, pattern string) bool {
args := env.Called(dir, pattern)
return args.Bool(0)
}
func (env *MockedEnvironment) HasFolder(folder string) bool {
args := env.Called(folder)
return args.Bool(0)
}
func (env *MockedEnvironment) FileContent(file string) string {
args := env.Called(file)
return args.String(0)
}
func (env *MockedEnvironment) FolderList(path string) []string {
args := env.Called(path)
return args.Get(0).([]string)
}
func (env *MockedEnvironment) PathSeperator() string {
args := env.Called()
return args.String(0)
}
func (env *MockedEnvironment) User() string {
args := env.Called()
return args.String(0)
}
func (env *MockedEnvironment) Host() (string, error) {
args := env.Called()
return args.String(0), args.Error(1)
}
func (env *MockedEnvironment) GOOS() string {
args := env.Called()
return args.String(0)
}
func (env *MockedEnvironment) Platform() string {
args := env.Called()
return args.String(0)
}
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) {
arguments := env.Called(command, args)
return arguments.String(0), arguments.Error(1)
}
func (env *MockedEnvironment) RunShellCommand(shell, command string) string {
args := env.Called(shell, command)
return args.String(0)
}
func (env *MockedEnvironment) ErrorCode() int {
args := env.Called()
return args.Int(0)
}
func (env *MockedEnvironment) ExecutionTime() float64 {
args := env.Called()
return float64(args.Int(0))
}
func (env *MockedEnvironment) Root() bool {
args := env.Called()
return args.Bool(0)
}
func (env *MockedEnvironment) Args() *environment.Args {
arguments := env.Called()
return arguments.Get(0).(*environment.Args)
}
func (env *MockedEnvironment) BatteryInfo() ([]*battery.Battery, error) {
args := env.Called()
return args.Get(0).([]*battery.Battery), args.Error(1)
}
func (env *MockedEnvironment) Shell() string {
args := env.Called()
return args.String(0)
}
func (env *MockedEnvironment) WindowTitle(imageName, windowTitleRegex string) (string, error) {
args := env.Called(imageName)
return args.String(0), args.Error(1)
}
func (env *MockedEnvironment) WindowsRegistryKeyValue(path string) (*environment.WindowsRegistryValue, error) {
args := env.Called(path)
return args.Get(0).(*environment.WindowsRegistryValue), args.Error(1)
}
func (env *MockedEnvironment) HTTPRequest(url string, timeout int, requestModifiers ...environment.HTTPRequestModifier) ([]byte, error) {
args := env.Called(url)
return args.Get(0).([]byte), args.Error(1)
}
func (env *MockedEnvironment) HasParentFilePath(path string) (*environment.FileInfo, error) {
args := env.Called(path)
return args.Get(0).(*environment.FileInfo), args.Error(1)
}
func (env *MockedEnvironment) StackCount() int {
args := env.Called()
return args.Int(0)
}
func (env *MockedEnvironment) IsWsl() bool {
args := env.Called()
return args.Bool(0)
}
func (env *MockedEnvironment) IsWsl2() bool {
args := env.Called()
return args.Bool(0)
}
func (env *MockedEnvironment) TerminalWidth() (int, error) {
args := env.Called()
return args.Int(0), args.Error(1)
}
func (env *MockedEnvironment) CachePath() string {
args := env.Called()
return args.String(0)
}
func (env *MockedEnvironment) Cache() environment.Cache {
args := env.Called()
return args.Get(0).(environment.Cache)
}
func (env *MockedEnvironment) Close() {
_ = env.Called()
}
func (env *MockedEnvironment) Logs() string {
args := env.Called()
return args.String(0)
}
func (env *MockedEnvironment) InWSLSharedDrive() bool {
args := env.Called()
return args.Bool(0)
}
func (env *MockedEnvironment) ConvertToWindowsPath(path string) string {
args := env.Called()
return args.String(0)
}
func (env *MockedEnvironment) ConvertToLinuxPath(path string) string {
args := env.Called()
return args.String(0)
}
func (env *MockedEnvironment) WifiNetwork() (*environment.WifiInfo, error) {
args := env.Called()
return args.Get(0).(*environment.WifiInfo), args.Error(1)
}
func (env *MockedEnvironment) TemplateCache() *environment.TemplateCache {
args := env.Called()
return args.Get(0).(*environment.TemplateCache)
}
func (env *MockedEnvironment) MockGitCommand(dir, returnValue string, args ...string) {
args = append([]string{"-C", dir, "--no-optional-locks", "-c", "core.quotepath=false", "-c", "color.status=false"}, args...)
env.On("RunCommand", "git", args).Return(returnValue, nil)
}

View file

@ -2,6 +2,7 @@ package main
import (
"fmt"
"oh-my-posh/regex"
)
// Property defines one property of a segment for context
@ -66,7 +67,7 @@ func (p properties) getColor(property Property, defaultValue string) string {
if IsAnsiColorName(colorString) {
return colorString
}
values := findNamedRegexMatch(`(?P<color>#[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}|p:.*)`, colorString)
values := regex.FindNamedRegexMatch(`(?P<color>#[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}|p:.*)`, colorString)
if values != nil && values["color"] != "" {
return values["color"]
}

View file

@ -1,9 +1,7 @@
package main
package regex
import (
"fmt"
"regexp"
"strings"
"sync"
)
@ -12,7 +10,7 @@ var (
regexCacheLock = sync.RWMutex{}
)
func getCompiledRegex(pattern string) *regexp.Regexp {
func GetCompiledRegex(pattern string) *regexp.Regexp {
// try in cache first
regexCacheLock.RLock()
re := regexCache[pattern]
@ -32,9 +30,9 @@ func getCompiledRegex(pattern string) *regexp.Regexp {
return re
}
func findNamedRegexMatch(pattern, text string) map[string]string {
func FindNamedRegexMatch(pattern, text string) map[string]string {
// error ignored because mustCompile will cause a panic
re := getCompiledRegex(pattern)
re := GetCompiledRegex(pattern)
match := re.FindStringSubmatch(text)
result := make(map[string]string)
if len(match) == 0 {
@ -49,8 +47,8 @@ func findNamedRegexMatch(pattern, text string) map[string]string {
return result
}
func findAllNamedRegexMatch(pattern, text string) []map[string]string {
re := getCompiledRegex(pattern)
func FindAllNamedRegexMatch(pattern, text string) []map[string]string {
re := GetCompiledRegex(pattern)
match := re.FindAllStringSubmatch(text, -1)
var results []map[string]string
if len(match) == 0 {
@ -70,34 +68,12 @@ func findAllNamedRegexMatch(pattern, text string) []map[string]string {
return results
}
func replaceAllString(pattern, text, replaceText string) string {
re := getCompiledRegex(pattern)
func ReplaceAllString(pattern, text, replaceText string) string {
re := GetCompiledRegex(pattern)
return re.ReplaceAllString(text, replaceText)
}
func matchString(pattern, text string) bool {
re := getCompiledRegex(pattern)
func MatchString(pattern, text string) bool {
re := GetCompiledRegex(pattern)
return re.MatchString(text)
}
func dirMatchesOneOf(env Environment, dir string, regexes []string) bool {
normalizedCwd := strings.ReplaceAll(dir, "\\", "/")
normalizedHomeDir := strings.ReplaceAll(env.Home(), "\\", "/")
for _, element := range regexes {
normalizedElement := strings.ReplaceAll(element, "\\\\", "/")
if strings.HasPrefix(normalizedElement, "~") {
normalizedElement = strings.Replace(normalizedElement, "~", normalizedHomeDir, 1)
}
pattern := fmt.Sprintf("^%s$", normalizedElement)
goos := env.GOOS()
if goos == windowsPlatform || goos == darwinPlatform {
pattern = "(?i)" + pattern
}
matched := matchString(pattern, normalizedCwd)
if matched {
return true
}
}
return false
}

View file

@ -1,40 +0,0 @@
package main
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestDirMatchesOneOf(t *testing.T) {
cases := []struct {
GOOS string
HomeDir string
Dir string
Pattern string
Expected bool
}{
{GOOS: linuxPlatform, HomeDir: "/home/bill", Dir: "/home/bill", Pattern: "/home/bill", Expected: true},
{GOOS: linuxPlatform, HomeDir: "/home/bill", Dir: "/home/bill/foo", Pattern: "~/foo", Expected: true},
{GOOS: linuxPlatform, HomeDir: "/home/bill", Dir: "/home/bill/foo", Pattern: "~/Foo", Expected: false},
{GOOS: linuxPlatform, HomeDir: "/home/bill", Dir: "/home/bill/foo", Pattern: "~\\\\foo", Expected: true},
{GOOS: linuxPlatform, HomeDir: "/home/bill", Dir: "/home/bill/foo/bar", Pattern: "~/fo.*", Expected: true},
{GOOS: linuxPlatform, HomeDir: "/home/bill", Dir: "/home/bill/foo", Pattern: "~/fo\\w", Expected: true},
{GOOS: windowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill", Pattern: "C:\\\\Users\\\\Bill", Expected: true},
{GOOS: windowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill", Pattern: "C:/Users/Bill", Expected: true},
{GOOS: windowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill", Pattern: "c:/users/bill", Expected: true},
{GOOS: windowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill", Pattern: "~", Expected: true},
{GOOS: windowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill\\Foo", Pattern: "~/Foo", Expected: true},
{GOOS: windowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill\\Foo", Pattern: "~/foo", Expected: true},
{GOOS: windowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill\\Foo\\Bar", Pattern: "~/fo.*", Expected: true},
{GOOS: windowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill\\Foo", Pattern: "~/fo\\w", Expected: true},
}
for _, tc := range cases {
env := new(MockedEnvironment)
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

@ -2,6 +2,7 @@ package main
import (
"fmt"
"oh-my-posh/environment"
"strings"
)
@ -36,7 +37,7 @@ func (s *ScmStatus) String() string {
type scm struct {
props Properties
env Environment
env environment.Environment
}
const (
@ -48,7 +49,7 @@ const (
FullBranchPath Property = "full_branch_path"
)
func (s *scm) init(props Properties, env Environment) {
func (s *scm) init(props Properties, env environment.Environment) {
s.props = props
s.env = env
}
@ -72,7 +73,7 @@ func (s *scm) shouldIgnoreRootRepository(rootDir string) bool {
if len(excludedFolders) == 0 {
return false
}
return dirMatchesOneOf(s.env, rootDir, excludedFolders)
return environment.DirMatchesOneOf(s.env, rootDir, excludedFolders)
}
func (s *scm) FileContents(folder, file string) string {

View file

@ -1,6 +1,8 @@
package main
import (
"oh-my-posh/environment"
"oh-my-posh/mock"
"testing"
"github.com/stretchr/testify/assert"
@ -167,15 +169,16 @@ func TestScmShouldIgnoreRootRepository(t *testing.T) {
}
for _, tc := range cases {
props := properties{
ExcludeFolders: []string{
"/home/bill",
"/home/gates.*",
},
excludeFolders := []string{
"/home/bill",
"/home/gates.*",
}
env := new(MockedEnvironment)
props := properties{
ExcludeFolders: excludeFolders,
}
env := new(mock.MockedEnvironment)
env.On("Home").Return("/home/bill")
env.On("GOOS").Return(windowsPlatform)
env.On("GOOS").Return(environment.WindowsPlatform)
s := &scm{
props: props,
env: env,

View file

@ -3,6 +3,7 @@ package main
import (
"errors"
"fmt"
"oh-my-posh/environment"
"runtime/debug"
"time"
)
@ -24,7 +25,7 @@ type Segment struct {
writer SegmentWriter
stringValue string
active bool
env Environment
env environment.Environment
}
// SegmentTiming holds the timing context for a segment
@ -51,7 +52,7 @@ type Properties interface {
type SegmentWriter interface {
enabled() bool
template() string
init(props Properties, env Environment)
init(props Properties, env environment.Environment)
}
// SegmentStyle the syle of segment, for more information, see the constants
@ -200,7 +201,7 @@ func (segment *Segment) cwdIncluded() bool {
return true
}
return dirMatchesOneOf(segment.env, segment.env.Pwd(), list)
return environment.DirMatchesOneOf(segment.env, segment.env.Pwd(), list)
}
func (segment *Segment) cwdExcluded() bool {
@ -209,7 +210,7 @@ func (segment *Segment) cwdExcluded() bool {
value = segment.Properties[IgnoreFolders]
}
list := parseStringArray(value)
return dirMatchesOneOf(segment.env, segment.env.Pwd(), list)
return environment.DirMatchesOneOf(segment.env, segment.env.Pwd(), list)
}
func (segment *Segment) getColor(templates []string, defaultColor string) string {
@ -248,7 +249,7 @@ func (segment *Segment) background() string {
return segment.getColor(segment.BackgroundTemplates, segment.Background)
}
func (segment *Segment) mapSegmentWithWriter(env Environment) error {
func (segment *Segment) mapSegmentWithWriter(env environment.Environment) error {
segment.env = env
functions := map[SegmentType]SegmentWriter{
OWM: &owm{},
@ -306,7 +307,7 @@ func (segment *Segment) mapSegmentWithWriter(env Environment) error {
return errors.New("unable to map writer")
}
func (segment *Segment) setStringValue(env Environment) {
func (segment *Segment) setStringValue(env environment.Environment) {
defer func() {
err := recover()
if err == nil {

View file

@ -3,6 +3,7 @@ package main
import (
"encoding/json"
"fmt"
"oh-my-posh/environment"
)
type angular struct {
@ -13,7 +14,7 @@ func (a *angular) template() string {
return languageTemplate
}
func (a *angular) init(props Properties, env Environment) {
func (a *angular) init(props Properties, env environment.Environment) {
a.language = language{
env: env,
props: props,

View file

@ -2,6 +2,8 @@ package main
import (
"fmt"
"oh-my-posh/environment"
"oh-my-posh/mock"
"testing"
"github.com/stretchr/testify/assert"
@ -22,14 +24,14 @@ func TestAngularCliVersionDisplayed(t *testing.T) {
extension: "angular.json",
}
var env = new(MockedEnvironment)
var env = new(mock.MockedEnvironment)
// mock getVersion methods
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.On("TemplateCache").Return(&environment.TemplateCache{
Env: make(map[string]string),
})
props := properties{}

View file

@ -2,12 +2,14 @@ package main
import (
"fmt"
"oh-my-posh/environment"
"strings"
)
type aws struct {
props Properties
env Environment
props Properties
env environment.Environment
Profile string
Region string
}
@ -20,7 +22,7 @@ func (a *aws) template() string {
return "{{ .Profile }}{{ if .Region }}@{{ .Region }}{{ end }}"
}
func (a *aws) init(props Properties, env Environment) {
func (a *aws) init(props Properties, env environment.Environment) {
a.props = props
a.env = env
}

View file

@ -1,6 +1,7 @@
package main
import (
"oh-my-posh/mock"
"testing"
"github.com/stretchr/testify/assert"
@ -46,7 +47,7 @@ func TestAWSSegment(t *testing.T) {
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.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)

View file

@ -2,13 +2,14 @@ package main
import (
"encoding/json"
"oh-my-posh/environment"
"path/filepath"
"strings"
)
type az struct {
props Properties
env Environment
env environment.Environment
AzureSubscription
Origin string
@ -82,7 +83,7 @@ func (a *az) template() string {
return "{{ .Name }}"
}
func (a *az) init(props Properties, env Environment) {
func (a *az) init(props Properties, env environment.Environment) {
a.props = props
a.env = env
}

View file

@ -1,5 +1,7 @@
package main
import "oh-my-posh/environment"
type azfunc struct {
language
}
@ -8,7 +10,7 @@ func (az *azfunc) template() string {
return languageTemplate
}
func (az *azfunc) init(props Properties, env Environment) {
func (az *azfunc) init(props Properties, env environment.Environment) {
az.language = language{
env: env,
props: props,

View file

@ -2,6 +2,8 @@ package main
import (
"io/ioutil"
"oh-my-posh/environment"
"oh-my-posh/mock"
"path/filepath"
"testing"
@ -67,7 +69,7 @@ func TestAzSegment(t *testing.T) {
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
home := "/Users/posh"
env.On("Home").Return(home)
var azureProfile, azureRmContext, azureRMContext string
@ -83,7 +85,7 @@ func TestAzSegment(t *testing.T) {
content, _ := ioutil.ReadFile("./test/AzureRmContext.json")
azureRMContext = string(content)
}
env.On("GOOS").Return(linuxPlatform)
env.On("GOOS").Return(environment.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)

View file

@ -2,13 +2,14 @@ package main
import (
"math"
"oh-my-posh/environment"
"github.com/distatus/battery"
)
type batt struct {
props Properties
env Environment
env environment.Environment
battery.Battery
Percentage int
@ -66,7 +67,7 @@ func (b *batt) enabledWhileError(err error) bool {
if err == nil {
return true
}
if _, ok := err.(*noBatteryError); ok {
if _, ok := err.(*environment.NoBatteryError); ok {
return false
}
displayError := b.props.getBool(DisplayError, false)
@ -103,7 +104,7 @@ func (b *batt) mapMostLogicalState(currentState, newState battery.State) battery
return newState
}
func (b *batt) init(props Properties, env Environment) {
func (b *batt) init(props Properties, env environment.Environment) {
b.props = props
b.env = env
}

View file

@ -7,6 +7,7 @@ import (
"fmt"
"math"
"net/http"
"oh-my-posh/environment"
"sort"
"time"
)
@ -14,7 +15,7 @@ import (
// segment struct, makes templating easier
type brewfather struct {
props Properties
env Environment
env environment.Environment
Batch
TemperatureTrendIcon string
@ -324,7 +325,7 @@ func (bf *brewfather) SGToPlato(sg float64) float64 {
return math.Round(100*((135.997*sg*sg*sg)-(630.272*sg*sg)+(1111.14*sg)-616.868)) / 100 // 2 decimal places
}
func (bf *brewfather) init(props Properties, env Environment) {
func (bf *brewfather) init(props Properties, env environment.Environment) {
bf.props = props
bf.env = env
}

View file

@ -2,6 +2,7 @@ package main
import (
"fmt"
"oh-my-posh/mock"
"testing"
"time"
@ -136,7 +137,7 @@ func TestBrewfatherSegment(t *testing.T) {
}
for _, tc := range cases {
env := &MockedEnvironment{}
env := &mock.MockedEnvironment{}
props := properties{
CacheTimeout: tc.CacheTimeout,
BFBatchID: BFFakeBatchID,
@ -144,7 +145,7 @@ func TestBrewfatherSegment(t *testing.T) {
BFUserID: "FAKE",
}
cache := &MockedCache{}
cache := &mock.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()

View file

@ -1,10 +1,13 @@
package main
import "strings"
import (
"oh-my-posh/environment"
"strings"
)
type command struct {
props Properties
env Environment
env environment.Environment
Output string
}
@ -49,7 +52,7 @@ func (c *command) enabled() bool {
return c.Output != ""
}
func (c *command) init(props Properties, env Environment) {
func (c *command) init(props Properties, env environment.Environment) {
c.props = props
c.env = env
}

View file

@ -1,13 +1,14 @@
package main
import (
"oh-my-posh/mock"
"testing"
"github.com/stretchr/testify/assert"
)
func TestExecuteCommand(t *testing.T) {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("HasCommand", "bash").Return(true)
env.On("RunShellCommand", "bash", "echo hello").Return("hello")
props := properties{
@ -23,7 +24,7 @@ func TestExecuteCommand(t *testing.T) {
}
func TestExecuteMultipleCommandsOrFirst(t *testing.T) {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("HasCommand", "bash").Return(true)
env.On("RunShellCommand", "bash", "exit 1").Return("")
env.On("RunShellCommand", "bash", "echo hello").Return("hello")
@ -41,7 +42,7 @@ func TestExecuteMultipleCommandsOrFirst(t *testing.T) {
}
func TestExecuteMultipleCommandsOrSecond(t *testing.T) {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("HasCommand", "bash").Return(true)
env.On("RunShellCommand", "bash", "echo hello").Return("hello")
env.On("RunShellCommand", "bash", "echo world").Return("world")
@ -58,7 +59,7 @@ func TestExecuteMultipleCommandsOrSecond(t *testing.T) {
}
func TestExecuteMultipleCommandsAnd(t *testing.T) {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("HasCommand", "bash").Return(true)
env.On("RunShellCommand", "bash", "echo hello").Return("hello")
env.On("RunShellCommand", "bash", "echo world").Return("world")
@ -75,7 +76,7 @@ func TestExecuteMultipleCommandsAnd(t *testing.T) {
}
func TestExecuteSingleCommandEmpty(t *testing.T) {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("HasCommand", "bash").Return(true)
env.On("RunShellCommand", "bash", "").Return("")
props := properties{
@ -90,7 +91,7 @@ func TestExecuteSingleCommandEmpty(t *testing.T) {
}
func TestExecuteSingleCommandNoCommandProperty(t *testing.T) {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("HasCommand", "bash").Return(true)
env.On("RunShellCommand", "bash", "echo no command specified").Return("no command specified")
var props properties
@ -104,7 +105,7 @@ func TestExecuteSingleCommandNoCommandProperty(t *testing.T) {
}
func TestExecuteMultipleCommandsAndDisabled(t *testing.T) {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("HasCommand", "bash").Return(true)
env.On("RunShellCommand", "bash", "echo").Return("")
props := properties{
@ -119,7 +120,7 @@ func TestExecuteMultipleCommandsAndDisabled(t *testing.T) {
}
func TestExecuteMultipleCommandsOrDisabled(t *testing.T) {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("HasCommand", "bash").Return(true)
env.On("RunShellCommand", "bash", "echo").Return("")
env.On("RunShellCommand", "bash", "echo|| echo").Return("")

View file

@ -1,5 +1,7 @@
package main
import "oh-my-posh/environment"
type crystal struct {
language
}
@ -8,7 +10,7 @@ func (c *crystal) template() string {
return languageTemplate
}
func (c *crystal) init(props Properties, env Environment) {
func (c *crystal) init(props Properties, env environment.Environment) {
c.language = language{
env: env,
props: props,

View file

@ -1,5 +1,7 @@
package main
import "oh-my-posh/environment"
type dart struct {
language
}
@ -8,7 +10,7 @@ func (d *dart) template() string {
return languageTemplate
}
func (d *dart) init(props Properties, env Environment) {
func (d *dart) init(props Properties, env environment.Environment) {
d.language = language{
env: env,
props: props,

View file

@ -1,5 +1,7 @@
package main
import "oh-my-posh/environment"
type dotnet struct {
language
@ -10,7 +12,7 @@ func (d *dotnet) template() string {
return "{{ if .Unsupported }}\uf071{{ else }}{{ .Full }}{{ end }}"
}
func (d *dotnet) init(props Properties, env Environment) {
func (d *dotnet) init(props Properties, env environment.Environment) {
d.language = language{
env: env,
props: props,

View file

@ -1,6 +1,8 @@
package main
import (
"oh-my-posh/environment"
"oh-my-posh/mock"
"testing"
"github.com/stretchr/testify/assert"
@ -22,10 +24,10 @@ func TestDotnetSegment(t *testing.T) {
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("HasCommand", "dotnet").Return(tc.HasCommand)
if tc.ExitCode != 0 {
err := &commandError{exitCode: tc.ExitCode}
err := &environment.CommandError{ExitCode: tc.ExitCode}
env.On("RunCommand", "dotnet", []string{"--version"}).Return("", err)
} else {
env.On("RunCommand", "dotnet", []string{"--version"}).Return(tc.Version, nil)
@ -35,7 +37,7 @@ func TestDotnetSegment(t *testing.T) {
env.On("PathSeperator").Return("")
env.On("Pwd").Return("/usr/home/project")
env.On("Home").Return("/usr/home")
env.On("TemplateCache").Return(&TemplateCache{
env.On("TemplateCache").Return(&environment.TemplateCache{
Env: make(map[string]string),
})
props := properties{

View file

@ -2,6 +2,7 @@ package main
import (
"fmt"
"oh-my-posh/environment"
"strconv"
lang "golang.org/x/text/language"
@ -10,7 +11,7 @@ import (
type executiontime struct {
props Properties
env Environment
env environment.Environment
FormattedMs string
Ms int64
@ -63,7 +64,7 @@ func (t *executiontime) template() string {
return "{{ .FormattedMs }}"
}
func (t *executiontime) init(props Properties, env Environment) {
func (t *executiontime) init(props Properties, env environment.Environment) {
t.props = props
t.env = env
}

View file

@ -1,6 +1,7 @@
package main
import (
"oh-my-posh/mock"
"testing"
"time"
@ -8,7 +9,7 @@ import (
)
func TestExecutionTimeWriterDefaultThresholdEnabled(t *testing.T) {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("ExecutionTime").Return(1337)
executionTime := &executiontime{
env: env,
@ -18,7 +19,7 @@ func TestExecutionTimeWriterDefaultThresholdEnabled(t *testing.T) {
}
func TestExecutionTimeWriterDefaultThresholdDisabled(t *testing.T) {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("ExecutionTime").Return(1)
executionTime := &executiontime{
env: env,
@ -28,7 +29,7 @@ func TestExecutionTimeWriterDefaultThresholdDisabled(t *testing.T) {
}
func TestExecutionTimeWriterCustomThresholdEnabled(t *testing.T) {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("ExecutionTime").Return(99)
props := properties{
ThresholdProperty: float64(10),
@ -41,7 +42,7 @@ func TestExecutionTimeWriterCustomThresholdEnabled(t *testing.T) {
}
func TestExecutionTimeWriterCustomThresholdDisabled(t *testing.T) {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("ExecutionTime").Return(99)
props := properties{
ThresholdProperty: float64(100),
@ -56,7 +57,7 @@ func TestExecutionTimeWriterCustomThresholdDisabled(t *testing.T) {
func TestExecutionTimeWriterDuration(t *testing.T) {
input := 1337
expected := "1.337s"
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("ExecutionTime").Return(input)
executionTime := &executiontime{
env: env,
@ -69,7 +70,7 @@ func TestExecutionTimeWriterDuration(t *testing.T) {
func TestExecutionTimeWriterDuration2(t *testing.T) {
input := 13371337
expected := "3h 42m 51.337s"
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("ExecutionTime").Return(input)
executionTime := &executiontime{
env: env,

View file

@ -1,10 +1,13 @@
package main
import "strconv"
import (
"oh-my-posh/environment"
"strconv"
)
type exit struct {
props Properties
env Environment
env environment.Environment
Text string
}
@ -21,7 +24,7 @@ func (e *exit) enabled() bool {
return e.env.ErrorCode() != 0
}
func (e *exit) init(props Properties, env Environment) {
func (e *exit) init(props Properties, env environment.Environment) {
e.props = props
e.env = env
}

View file

@ -1,6 +1,8 @@
package main
import (
"oh-my-posh/environment"
"oh-my-posh/mock"
"testing"
"github.com/stretchr/testify/assert"
@ -17,7 +19,7 @@ func TestExitWriterEnabled(t *testing.T) {
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("ErrorCode").Return(tc.ExitCode)
e := &exit{
env: env,
@ -74,9 +76,9 @@ func TestExitWriterTemplateString(t *testing.T) {
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("ErrorCode").Return(tc.ExitCode)
env.On("TemplateCache").Return(&TemplateCache{
env.On("TemplateCache").Return(&environment.TemplateCache{
Code: tc.ExitCode,
})
e := &exit{

View file

@ -2,6 +2,8 @@ package main
import (
"fmt"
"oh-my-posh/environment"
"oh-my-posh/regex"
"strconv"
"strings"
@ -160,7 +162,7 @@ func (g *git) shouldDisplay() bool {
// handle worktree
g.gitRootFolder = gitdir.Path
dirPointer := strings.Trim(g.env.FileContent(gitdir.Path), " \r\n")
matches := findNamedRegexMatch(`^gitdir: (?P<dir>.*)$`, dirPointer)
matches := regex.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
// to the mounted path
@ -214,7 +216,7 @@ func (g *git) setBranchStatus() {
}
func (g *git) getUpstreamIcon() string {
upstream := replaceAllString("/.*", g.Upstream, "")
upstream := regex.ReplaceAllString("/.*", g.Upstream, "")
g.UpstreamURL = g.getOriginURL(upstream)
if strings.Contains(g.UpstreamURL, "github") {
return g.props.getString(GithubIcon, "\uF408 ")
@ -287,7 +289,7 @@ func (g *git) getGitCommand() string {
return g.gitCommand
}
g.gitCommand = "git"
if g.env.GOOS() == windowsPlatform || g.IsWslSharedPath {
if g.env.GOOS() == environment.WindowsPlatform || g.IsWslSharedPath {
g.gitCommand = "git.exe"
}
return g.gitCommand
@ -353,7 +355,7 @@ func (g *git) setGitHEADContext() {
if g.hasGitFile("MERGE_MSG") {
icon := g.props.getString(MergeIcon, "\uE727 ")
mergeContext := g.FileContents(g.gitWorkingFolder, "MERGE_MSG")
matches := findNamedRegexMatch(`Merge (remote-tracking )?(?P<type>branch|commit|tag) '(?P<theirs>.*)'`, mergeContext)
matches := regex.FindNamedRegexMatch(`Merge (remote-tracking )?(?P<type>branch|commit|tag) '(?P<theirs>.*)'`, mergeContext)
// head := g.getGitRefFileSymbolicName("ORIG_HEAD")
if matches != nil && matches["theirs"] != "" {
var headIcon, theirs string
@ -391,7 +393,7 @@ func (g *git) setGitHEADContext() {
}
if g.hasGitFile("sequencer/todo") {
todo := g.FileContents(g.gitWorkingFolder, "sequencer/todo")
matches := findNamedRegexMatch(`^(?P<action>p|pick|revert)\s+(?P<sha>\S+)`, todo)
matches := regex.FindNamedRegexMatch(`^(?P<action>p|pick|revert)\s+(?P<sha>\S+)`, todo)
if matches != nil && matches["sha"] != "" {
action := matches["action"]
sha := matches["sha"]

View file

@ -2,6 +2,8 @@ package main
import (
"fmt"
"oh-my-posh/environment"
"oh-my-posh/mock"
"strings"
"testing"
@ -13,7 +15,7 @@ const (
)
func TestEnabledGitNotFound(t *testing.T) {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("InWSLSharedDrive").Return(false)
env.On("HasCommand", "git").Return(false)
env.On("GOOS").Return("")
@ -28,17 +30,17 @@ func TestEnabledGitNotFound(t *testing.T) {
}
func TestEnabledInWorkingDirectory(t *testing.T) {
fileInfo := &FileInfo{
fileInfo := &environment.FileInfo{
Path: "/dir/hello",
ParentFolder: "/dir",
IsDir: true,
}
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
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.MockGitCommand(fileInfo.Path, "", "describe", "--tags", "--exact-match")
env.On("IsWsl").Return(false)
env.On("HasParentFilePath", ".git").Return(fileInfo, nil)
g := &git{
@ -52,18 +54,18 @@ func TestEnabledInWorkingDirectory(t *testing.T) {
}
func TestEnabledInWorkingTree(t *testing.T) {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("InWSLSharedDrive").Return(false)
env.On("HasCommand", "git").Return(true)
env.On("GOOS").Return("")
env.On("IsWsl").Return(false)
fileInfo := &FileInfo{
fileInfo := &environment.FileInfo{
Path: "/dev/folder_worktree/.git",
ParentFolder: "/dev/folder_worktree",
IsDir: false,
}
env.On("FileContent", "/dev/real_folder/.git/worktrees/folder_worktree/HEAD").Return("")
env.mockGitCommand(fileInfo.ParentFolder, "", "describe", "--tags", "--exact-match")
env.MockGitCommand(fileInfo.ParentFolder, "", "describe", "--tags", "--exact-match")
env.On("HasParentFilePath", ".git").Return(fileInfo, nil)
env.On("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")
@ -79,18 +81,18 @@ func TestEnabledInWorkingTree(t *testing.T) {
}
func TestEnabledInSubmodule(t *testing.T) {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("InWSLSharedDrive").Return(false)
env.On("HasCommand", "git").Return(true)
env.On("GOOS").Return("")
env.On("IsWsl").Return(false)
fileInfo := &FileInfo{
fileInfo := &environment.FileInfo{
Path: "/dev/parent/test-submodule/.git",
ParentFolder: "/dev/parent/test-submodule",
IsDir: false,
}
env.On("FileContent", "/dev/parent/test-submodule/../.git/modules/test-submodule/HEAD").Return("")
env.mockGitCommand("/dev/parent/test-submodule/../.git/modules/test-submodule", "", "describe", "--tags", "--exact-match")
env.MockGitCommand("/dev/parent/test-submodule/../.git/modules/test-submodule", "", "describe", "--tags", "--exact-match")
env.On("HasParentFilePath", ".git").Return(fileInfo, nil)
env.On("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")
@ -110,7 +112,7 @@ func TestGetGitOutputForCommand(t *testing.T) {
args := []string{"-C", "", "--no-optional-locks", "-c", "core.quotepath=false", "-c", "color.status=false"}
commandArgs := []string{"symbolic-ref", "--short", "HEAD"}
want := "je suis le output"
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("IsWsl").Return(false)
env.On("RunCommand", "git", append(args, commandArgs...)).Return(want, nil)
env.On("GOOS").Return("unix")
@ -124,11 +126,6 @@ func TestGetGitOutputForCommand(t *testing.T) {
assert.Equal(t, want, got)
}
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)
}
func TestSetGitHEADContextClean(t *testing.T) {
cases := []struct {
Case string
@ -232,13 +229,13 @@ func TestSetGitHEADContextClean(t *testing.T) {
},
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
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)
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("FileContent", "/rebase-merge/head-name").Return(tc.Ours)
@ -300,11 +297,11 @@ func TestSetPrettyHEADName(t *testing.T) {
{Case: "no hash on commit", Expected: "commit 1234567", HEAD: "12345678910"},
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
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")
env.MockGitCommand("", tc.Tag, "describe", "--tags", "--exact-match")
g := &git{
scm: scm{
env: env,
@ -418,10 +415,10 @@ func TestSetGitStatus(t *testing.T) {
},
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("GOOS").Return("unix")
env.On("IsWsl").Return(false)
env.mockGitCommand("", strings.ReplaceAll(tc.Output, "\t", ""), "status", "-unormal", "--branch", "--porcelain=2")
env.MockGitCommand("", strings.ReplaceAll(tc.Output, "\t", ""), "status", "-unormal", "--branch", "--porcelain=2")
g := &git{
scm: scm{
env: env,
@ -454,7 +451,7 @@ func TestGetStashContextZeroEntries(t *testing.T) {
{Expected: 4, StashContent: "1\n2\n3\n4\n\n"},
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("FileContent", "/logs/refs/stash").Return(tc.StashContent)
g := &git{
scm: scm{
@ -481,7 +478,7 @@ func TestGitUpstream(t *testing.T) {
{Case: "Gitstash", Expected: "G", Upstream: "gitstash.com/test"},
}
for _, tc := range cases {
env := &MockedEnvironment{}
env := &mock.MockedEnvironment{}
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)
@ -541,39 +538,6 @@ func TestGetBranchStatus(t *testing.T) {
}
}
func TestShouldIgnoreRootRepository(t *testing.T) {
cases := []struct {
Case string
Dir string
Expected bool
}{
{Case: "inside excluded", Dir: "/home/bill/repo"},
{Case: "oustide excluded", Dir: "/home/melinda"},
{Case: "excluded exact match", Dir: "/home/gates", Expected: true},
{Case: "excluded inside match", Dir: "/home/gates/bill", Expected: true},
}
for _, tc := range cases {
props := properties{
ExcludeFolders: []string{
"/home/bill",
"/home/gates.*",
},
}
env := new(MockedEnvironment)
env.On("Home").Return("/home/bill")
env.On("GOOS").Return(windowsPlatform)
git := &git{
scm: scm{
props: props,
env: env,
},
}
got := git.shouldIgnoreRootRepository(tc.Dir)
assert.Equal(t, tc.Expected, got, tc.Case)
}
}
func TestGetGitCommand(t *testing.T) {
cases := []struct {
Case string
@ -584,7 +548,7 @@ func TestGetGitCommand(t *testing.T) {
CWD string
IsWslSharedPath bool
}{
{Case: "On Windows", Expected: "git.exe", GOOS: windowsPlatform},
{Case: "On Windows", Expected: "git.exe", GOOS: environment.WindowsPlatform},
{Case: "Non Windows", Expected: "git"},
{Case: "Iside WSL2, non shared", IsWSL: true, Expected: "git"},
{Case: "Iside WSL2, shared", Expected: "git.exe", IsWSL: true, IsWslSharedPath: true, CWD: "/mnt/bill"},
@ -592,7 +556,7 @@ func TestGetGitCommand(t *testing.T) {
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("IsWsl").Return(tc.IsWSL)
env.On("GOOS").Return(tc.GOOS)
env.On("Pwd").Return(tc.CWD)
@ -743,7 +707,7 @@ func TestGitTemplateString(t *testing.T) {
props := properties{
FetchStatus: true,
}
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
tc.Git.env = env
tc.Git.props = props
assert.Equal(t, tc.Expected, renderTemplate(env, tc.Template, tc.Git), tc.Case)

View file

@ -1,6 +1,8 @@
package main
import (
"oh-my-posh/environment"
"golang.org/x/mod/modfile"
)
@ -16,7 +18,7 @@ func (g *golang) template() string {
return languageTemplate
}
func (g *golang) init(props Properties, env Environment) {
func (g *golang) init(props Properties, env environment.Environment) {
g.language = language{
env: env,
props: props,

View file

@ -4,6 +4,8 @@ import (
"errors"
"fmt"
"io/ioutil"
"oh-my-posh/environment"
"oh-my-posh/mock"
"testing"
"github.com/stretchr/testify/assert"
@ -16,14 +18,14 @@ type mockedLanguageParams struct {
extension string
}
func getMockedLanguageEnv(params *mockedLanguageParams) (*MockedEnvironment, properties) {
env := new(MockedEnvironment)
func getMockedLanguageEnv(params *mockedLanguageParams) (*mock.MockedEnvironment, properties) {
env := new(mock.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("Home").Return("/usr/home")
env.On("TemplateCache").Return(&TemplateCache{
env.On("TemplateCache").Return(&environment.TemplateCache{
Env: make(map[string]string),
})
props := properties{
@ -64,7 +66,7 @@ func TestGolang(t *testing.T) {
env, props := getMockedLanguageEnv(params)
if tc.ParseModFile {
props[ParseModFile] = tc.ParseModFile
fileInfo := &FileInfo{
fileInfo := &environment.FileInfo{
Path: "./go.mod",
ParentFolder: "./",
IsDir: false,

View file

@ -1,8 +1,10 @@
package main
import "oh-my-posh/environment"
type ipify struct {
props Properties
env Environment
env environment.Environment
IP string
}
@ -55,7 +57,7 @@ func (i *ipify) getResult() (string, error) {
return response, nil
}
func (i *ipify) init(props Properties, env Environment) {
func (i *ipify) init(props Properties, env environment.Environment) {
i.props = props
i.env = env
}

View file

@ -2,6 +2,7 @@ package main
import (
"errors"
"oh-my-posh/mock"
"testing"
"github.com/stretchr/testify/assert"
@ -42,7 +43,7 @@ func TestIpifySegment(t *testing.T) {
}
for _, tc := range cases {
env := &MockedEnvironment{}
env := &mock.MockedEnvironment{}
props := properties{
CacheTimeout: 0,
}

View file

@ -1,6 +1,9 @@
package main
import "fmt"
import (
"fmt"
"oh-my-posh/environment"
)
type java struct {
language
@ -10,7 +13,7 @@ func (j *java) template() string {
return languageTemplate
}
func (j *java) init(props Properties, env Environment) {
func (j *java) init(props Properties, env environment.Environment) {
javaRegex := `(?: JRE)(?: \(.*\))? \((?P<version>(?P<major>[0-9]+)(?:\.(?P<minor>[0-9]+))?(?:\.(?P<patch>[0-9]+))?).*\),`
javaCmd := &cmd{
executable: "java",

View file

@ -2,6 +2,7 @@ package main
import (
"fmt"
"oh-my-posh/mock"
"testing"
"github.com/stretchr/testify/assert"
@ -53,7 +54,7 @@ func TestJava(t *testing.T) {
},
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("HasCommand", "java").Return(true)
env.On("RunCommand", "java", []string{"-Xinternalversion"}).Return(tc.Version, nil)
env.On("HasFiles", "pom.xml").Return(true)

View file

@ -1,5 +1,7 @@
package main
import "oh-my-posh/environment"
type julia struct {
language
}
@ -8,7 +10,7 @@ func (j *julia) template() string {
return languageTemplate
}
func (j *julia) init(props Properties, env Environment) {
func (j *julia) init(props Properties, env environment.Environment) {
j.language = language{
env: env,
props: props,

View file

@ -1,6 +1,7 @@
package main
import (
"oh-my-posh/environment"
"path/filepath"
"gopkg.in/yaml.v3"
@ -10,9 +11,11 @@ import (
const ParseKubeConfig Property = "parse_kubeconfig"
type kubectl struct {
props Properties
env Environment
props Properties
env environment.Environment
Context string
KubeContext
}
@ -34,7 +37,7 @@ func (k *kubectl) template() string {
return "{{ .Context }}{{ if .Namespace }} :: {{ .Namespace }}{{ end }}"
}
func (k *kubectl) init(props Properties, env Environment) {
func (k *kubectl) init(props Properties, env environment.Environment) {
k.props = props
k.env = env
}

View file

@ -3,6 +3,8 @@ package main
import (
"fmt"
"io/ioutil"
"oh-my-posh/environment"
"oh-my-posh/mock"
"path/filepath"
"testing"
@ -105,7 +107,7 @@ func TestKubectlSegment(t *testing.T) {
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("HasCommand", "kubectl").Return(tc.KubectlExists)
var kubeconfig string
content, err := ioutil.ReadFile("./test/kubectl.yml")
@ -114,9 +116,9 @@ func TestKubectlSegment(t *testing.T) {
}
var kubectlErr error
if tc.KubectlErr {
kubectlErr = &commandError{
err: "oops",
exitCode: 1,
kubectlErr = &environment.CommandError{
Err: "oops",
ExitCode: 1,
}
}
env.On("RunCommand", "kubectl", []string{"config", "view", "--output", "yaml", "--minify"}).Return(kubeconfig, kubectlErr)

View file

@ -3,6 +3,8 @@ package main
import (
"errors"
"fmt"
"oh-my-posh/environment"
"oh-my-posh/regex"
)
const (
@ -34,7 +36,7 @@ type cmd struct {
}
func (c *cmd) parse(versionInfo string) (*version, error) {
values := findNamedRegexMatch(c.regex, versionInfo)
values := regex.FindNamedRegexMatch(c.regex, versionInfo)
if len(values) == 0 {
return nil, errors.New("cannot parse version string")
}
@ -52,7 +54,7 @@ func (c *cmd) parse(versionInfo string) (*version, error) {
type language struct {
props Properties
env Environment
env environment.Environment
extensions []string
commands []*cmd
versionURLTemplate string
@ -150,8 +152,8 @@ func (l *language) setVersion() error {
continue
}
versionStr, err = l.env.RunCommand(command.executable, command.args...)
if exitErr, ok := err.(*commandError); ok {
l.exitCode = exitErr.exitCode
if exitErr, ok := err.(*environment.CommandError); ok {
l.exitCode = exitErr.ExitCode
return fmt.Errorf("err executing %s with %s", command.executable, command.args)
}
} else {

View file

@ -1,6 +1,8 @@
package main
import (
"oh-my-posh/environment"
"oh-my-posh/mock"
"testing"
"github.com/stretchr/testify/assert"
@ -35,7 +37,7 @@ func (l *languageArgs) hasvalue(value string, list []string) bool {
}
func bootStrapLanguageTest(args *languageArgs) *language {
env := new(MockedEnvironment)
env := new(mock.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)
@ -50,7 +52,7 @@ func bootStrapLanguageTest(args *languageArgs) *language {
}
env.On("Pwd").Return(cwd)
env.On("Home").Return(home)
env.On("TemplateCache").Return(&TemplateCache{
env.On("TemplateCache").Return(&environment.TemplateCache{
Env: make(map[string]string),
})
if args.properties == nil {
@ -346,7 +348,7 @@ func TestLanguageEnabledCommandExitCode(t *testing.T) {
enabledExtensions: []string{uni, corn},
enabledCommands: []string{"uni"},
version: universion,
expectedError: &commandError{exitCode: expected},
expectedError: &environment.CommandError{ExitCode: expected},
}
lang := bootStrapLanguageTest(args)
assert.True(t, lang.enabled())

View file

@ -2,11 +2,12 @@ package main
import (
"encoding/json"
"oh-my-posh/environment"
)
type nbgv struct {
props Properties
env Environment
env environment.Environment
VersionInfo
}
@ -43,7 +44,7 @@ func (n *nbgv) enabled() bool {
return n.VersionInfo.VersionFileFound
}
func (n *nbgv) init(props Properties, env Environment) {
func (n *nbgv) init(props Properties, env environment.Environment) {
n.props = props
n.env = env
}

View file

@ -2,6 +2,7 @@ package main
import (
"errors"
"oh-my-posh/mock"
"testing"
"github.com/alecthomas/assert"
@ -57,7 +58,7 @@ func TestNbgv(t *testing.T) {
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("HasCommand", "nbgv").Return(tc.HasNbgv)
env.On("RunCommand", "nbgv", []string{"get-version", "--format=json"}).Return(tc.Response, tc.Error)
nbgv := &nbgv{

View file

@ -3,13 +3,14 @@ package main
import (
"encoding/json"
"errors"
"oh-my-posh/environment"
"time"
)
// segment struct, makes templating easier
type nightscout struct {
props Properties
env Environment
env environment.Environment
NightscoutData
TrendIcon string
@ -137,7 +138,7 @@ func (ns *nightscout) getResult() (*NightscoutData, error) {
return data, nil
}
func (ns *nightscout) init(props Properties, env Environment) {
func (ns *nightscout) init(props Properties, env environment.Environment) {
ns.props = props
ns.env = env
}

View file

@ -2,6 +2,7 @@ package main
import (
"errors"
"oh-my-posh/mock"
"testing"
"github.com/stretchr/testify/assert"
@ -129,13 +130,13 @@ func TestNSSegment(t *testing.T) {
}
for _, tc := range cases {
env := &MockedEnvironment{}
env := &mock.MockedEnvironment{}
props := properties{
CacheTimeout: tc.CacheTimeout,
URL: "FAKE",
}
cache := &MockedCache{}
cache := &mock.MockedCache{}
cache.On("Get", FAKEAPIURL).Return(tc.JSONResponse, !tc.CacheFoundFail)
cache.On("Set", FAKEAPIURL, tc.JSONResponse, tc.CacheTimeout).Return()

View file

@ -1,6 +1,10 @@
package main
import "fmt"
import (
"fmt"
"oh-my-posh/environment"
"oh-my-posh/regex"
)
type node struct {
language
@ -21,7 +25,7 @@ func (n *node) template() string {
return "{{ if .PackageManagerIcon }}{{ .PackageManagerIcon }} {{ end }}{{ .Full }}"
}
func (n *node) init(props Properties, env Environment) {
func (n *node) init(props Properties, env environment.Environment) {
n.language = language{
env: env,
props: props,
@ -62,12 +66,12 @@ func (n *node) matchesVersionFile() bool {
return true
}
regex := fmt.Sprintf(
re := fmt.Sprintf(
`(?im)^v?%s(\.?%s)?(\.?%s)?$`,
n.language.version.Major,
n.language.version.Minor,
n.language.version.Patch,
)
return matchString(regex, fileVersion)
return regex.MatchString(re, fileVersion)
}

View file

@ -1,6 +1,7 @@
package main
import (
"oh-my-posh/mock"
"testing"
"github.com/alecthomas/assert"
@ -29,7 +30,7 @@ func TestNodeMatchesVersionFile(t *testing.T) {
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("FileContent", ".nvmrc").Return(tc.RCVersion)
node := &node{
@ -60,7 +61,7 @@ func TestNodeInContext(t *testing.T) {
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.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)

View file

@ -1,8 +1,10 @@
package main
import "oh-my-posh/environment"
type osInfo struct {
props Properties
env Environment
env environment.Environment
Icon string
}
@ -63,11 +65,11 @@ func (oi *osInfo) template() string {
func (oi *osInfo) enabled() bool {
goos := oi.env.GOOS()
switch goos {
case windowsPlatform:
case environment.WindowsPlatform:
oi.Icon = oi.props.getString(Windows, "\uE62A")
case darwinPlatform:
case environment.DarwinPlatform:
oi.Icon = oi.props.getString(MacOS, "\uF179")
case linuxPlatform:
case environment.LinuxPlatform:
platform := oi.env.Platform()
displayDistroName := oi.props.getBool(DisplayDistroName, false)
if displayDistroName {
@ -125,7 +127,7 @@ func (oi *osInfo) getDistroIcon(distro string) string {
return oi.props.getString(Linux, "\uF17C")
}
func (oi *osInfo) init(props Properties, env Environment) {
func (oi *osInfo) init(props Properties, env environment.Environment) {
oi.props = props
oi.env = env
}

View file

@ -1,6 +1,8 @@
package main
import (
"oh-my-posh/environment"
"oh-my-posh/mock"
"testing"
"github.com/stretchr/testify/assert"
@ -60,10 +62,10 @@ func TestOSInfo(t *testing.T) {
},
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("GOOS").Return(tc.GOOS)
env.On("Platform").Return(tc.Platform)
env.On("TemplateCache").Return(&TemplateCache{
env.On("TemplateCache").Return(&environment.TemplateCache{
Env: make(map[string]string),
WSL: tc.IsWSL,
})

View file

@ -4,11 +4,13 @@ import (
"encoding/json"
"errors"
"fmt"
"oh-my-posh/environment"
)
type owm struct {
props Properties
env Environment
props Properties
env environment.Environment
Temperature float64
Weather string
URL string
@ -161,7 +163,7 @@ func (d *owm) setStatus() error {
return nil
}
func (d *owm) init(props Properties, env Environment) {
func (d *owm) init(props Properties, env environment.Environment) {
d.props = props
d.env = env
}

View file

@ -3,6 +3,7 @@ package main
import (
"errors"
"fmt"
"oh-my-posh/mock"
"testing"
"github.com/stretchr/testify/assert"
@ -50,7 +51,7 @@ func TestOWMSegmentSingle(t *testing.T) {
}
for _, tc := range cases {
env := &MockedEnvironment{}
env := &mock.MockedEnvironment{}
props := properties{
APIKey: "key",
Location: "AMSTERDAM,NL",
@ -178,7 +179,7 @@ func TestOWMSegmentIcons(t *testing.T) {
}
for _, tc := range cases {
env := &MockedEnvironment{}
env := &mock.MockedEnvironment{}
response := fmt.Sprintf(`{"weather":[{"icon":"%s"}],"main":{"temp":20}}`, tc.IconID)
expectedString := fmt.Sprintf("%s (20°C)", tc.ExpectedIconString)
@ -201,7 +202,7 @@ func TestOWMSegmentIcons(t *testing.T) {
// test with hyperlink enabled
for _, tc := range cases {
env := &MockedEnvironment{}
env := &mock.MockedEnvironment{}
response := fmt.Sprintf(`{"weather":[{"icon":"%s"}],"main":{"temp":20}}`, tc.IconID)
expectedString := fmt.Sprintf("[%s (20°C)](http://api.openweathermap.org/data/2.5/weather?q=AMSTERDAM,NL&units=metric&appid=key)", tc.ExpectedIconString)
@ -226,8 +227,8 @@ func TestOWMSegmentFromCache(t *testing.T) {
response := fmt.Sprintf(`{"weather":[{"icon":"%s"}],"main":{"temp":20}}`, "01d")
expectedString := fmt.Sprintf("%s (20°C)", "\ufa98")
env := &MockedEnvironment{}
cache := &MockedCache{}
env := &mock.MockedEnvironment{}
cache := &mock.MockedCache{}
o := &owm{
props: properties{
APIKey: "key",
@ -249,8 +250,8 @@ func TestOWMSegmentFromCacheWithHyperlink(t *testing.T) {
response := fmt.Sprintf(`{"weather":[{"icon":"%s"}],"main":{"temp":20}}`, "01d")
expectedString := fmt.Sprintf("[%s (20°C)](http://api.openweathermap.org/data/2.5/weather?q=AMSTERDAM,NL&units=metric&appid=key)", "\ufa98")
env := &MockedEnvironment{}
cache := &MockedCache{}
env := &mock.MockedEnvironment{}
cache := &mock.MockedCache{}
o := &owm{
props: properties{

View file

@ -2,14 +2,15 @@ package main
import (
"fmt"
"path/filepath"
"oh-my-posh/environment"
"oh-my-posh/regex"
"sort"
"strings"
)
type path struct {
props Properties
env Environment
env environment.Environment
pwd string
Path string
@ -95,13 +96,13 @@ func (pt *path) enabled() bool {
}
func (pt *path) formatWindowsDrive(pwd string) string {
if pt.env.GOOS() != windowsPlatform || !strings.HasSuffix(pwd, ":") {
if pt.env.GOOS() != environment.WindowsPlatform || !strings.HasSuffix(pwd, ":") {
return pwd
}
return pwd + "\\"
}
func (pt *path) init(props Properties, env Environment) {
func (pt *path) init(props Properties, env environment.Environment) {
pt.props = props
pt.env = env
}
@ -141,7 +142,7 @@ func (pt *path) getAgnosterPath() string {
buffer.WriteString(fmt.Sprintf("%s%s", separator, folderIcon))
}
if pathDepth > 0 {
buffer.WriteString(fmt.Sprintf("%s%s", separator, base(pwd, pt.env)))
buffer.WriteString(fmt.Sprintf("%s%s", separator, environment.Base(pt.env, pwd)))
}
return buffer.String()
}
@ -181,7 +182,7 @@ func (pt *path) getLetterPath() string {
}
// check if there is at least a letter we can use
matches := findNamedRegexMatch(`(?P<letter>[\p{L}0-9]).*`, folder)
matches := regex.FindNamedRegexMatch(`(?P<letter>[\p{L}0-9]).*`, folder)
if matches == nil || matches["letter"] == "" {
// no letter found, keep the folder unchanged
@ -241,7 +242,7 @@ func (pt *path) getFullPath() string {
func (pt *path) getFolderPath() string {
pwd := pt.getPwd()
pwd = base(pwd, pt.env)
pwd = environment.Base(pt.env, pwd)
return pt.replaceFolderSeparators(pwd)
}
@ -261,7 +262,7 @@ func (pt *path) normalize(inputPath string) string {
}
normalized = strings.ReplaceAll(normalized, "\\", "/")
goos := pt.env.GOOS()
if goos == windowsPlatform || goos == darwinPlatform {
if goos == environment.WindowsPlatform || goos == environment.DarwinPlatform {
normalized = strings.ToLower(normalized)
}
return normalized
@ -343,35 +344,3 @@ func (pt *path) pathDepth(pwd string) int {
}
return depth - 1
}
// Base returns the last element of path.
// Trailing path separators are removed before extracting the last element.
// If the path consists entirely of separators, Base returns a single separator.
func base(path string, env Environment) string {
if path == "/" {
return path
}
volumeName := filepath.VolumeName(path)
// Strip trailing slashes.
for len(path) > 0 && string(path[len(path)-1]) == env.PathSeperator() {
path = path[0 : len(path)-1]
}
if volumeName == path {
return path
}
// Throw away volume name
path = path[len(filepath.VolumeName(path)):]
// Find the last element
i := len(path) - 1
for i >= 0 && string(path[i]) != env.PathSeperator() {
i--
}
if i >= 0 {
path = path[i+1:]
}
// If empty now, it had only slashes.
if path == "" {
return env.PathSeperator()
}
return path
}

View file

@ -1,214 +1,16 @@
package main
import (
"oh-my-posh/environment"
"oh-my-posh/mock"
"testing"
"github.com/distatus/battery"
"github.com/gookit/config/v2"
"github.com/mitchellh/mapstructure"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
type MockedEnvironment struct {
mock.Mock
}
func (env *MockedEnvironment) Getenv(key string) string {
args := env.Called(key)
return args.String(0)
}
func (env *MockedEnvironment) Pwd() string {
args := env.Called()
return args.String(0)
}
func (env *MockedEnvironment) Home() string {
args := env.Called()
return args.String(0)
}
func (env *MockedEnvironment) HasFiles(pattern string) bool {
args := env.Called(pattern)
return args.Bool(0)
}
func (env *MockedEnvironment) HasFilesInDir(dir, pattern string) bool {
args := env.Called(dir, pattern)
return args.Bool(0)
}
func (env *MockedEnvironment) HasFolder(folder string) bool {
args := env.Called(folder)
return args.Bool(0)
}
func (env *MockedEnvironment) FileContent(file string) string {
args := env.Called(file)
return args.String(0)
}
func (env *MockedEnvironment) FolderList(path string) []string {
args := env.Called(path)
return args.Get(0).([]string)
}
func (env *MockedEnvironment) PathSeperator() string {
args := env.Called()
return args.String(0)
}
func (env *MockedEnvironment) User() string {
args := env.Called()
return args.String(0)
}
func (env *MockedEnvironment) Host() (string, error) {
args := env.Called()
return args.String(0), args.Error(1)
}
func (env *MockedEnvironment) GOOS() string {
args := env.Called()
return args.String(0)
}
func (env *MockedEnvironment) Platform() string {
args := env.Called()
return args.String(0)
}
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) {
arguments := env.Called(command, args)
return arguments.String(0), arguments.Error(1)
}
func (env *MockedEnvironment) RunShellCommand(shell, command string) string {
args := env.Called(shell, command)
return args.String(0)
}
func (env *MockedEnvironment) ErrorCode() int {
args := env.Called()
return args.Int(0)
}
func (env *MockedEnvironment) ExecutionTime() float64 {
args := env.Called()
return float64(args.Int(0))
}
func (env *MockedEnvironment) Root() bool {
args := env.Called()
return args.Bool(0)
}
func (env *MockedEnvironment) Args() *Args {
arguments := env.Called()
return arguments.Get(0).(*Args)
}
func (env *MockedEnvironment) BatteryInfo() ([]*battery.Battery, error) {
args := env.Called()
return args.Get(0).([]*battery.Battery), args.Error(1)
}
func (env *MockedEnvironment) Shell() string {
args := env.Called()
return args.String(0)
}
func (env *MockedEnvironment) WindowTitle(imageName, windowTitleRegex string) (string, error) {
args := env.Called(imageName)
return args.String(0), args.Error(1)
}
func (env *MockedEnvironment) WindowsRegistryKeyValue(path string) (*WindowsRegistryValue, error) {
args := env.Called(path)
return args.Get(0).(*WindowsRegistryValue), args.Error(1)
}
func (env *MockedEnvironment) HTTPRequest(url string, timeout int, requestModifiers ...HTTPRequestModifier) ([]byte, error) {
args := env.Called(url)
return args.Get(0).([]byte), args.Error(1)
}
func (env *MockedEnvironment) HasParentFilePath(path string) (*FileInfo, error) {
args := env.Called(path)
return args.Get(0).(*FileInfo), args.Error(1)
}
func (env *MockedEnvironment) StackCount() int {
args := env.Called()
return args.Int(0)
}
func (env *MockedEnvironment) IsWsl() bool {
args := env.Called()
return args.Bool(0)
}
func (env *MockedEnvironment) IsWsl2() bool {
args := env.Called()
return args.Bool(0)
}
func (env *MockedEnvironment) TerminalWidth() (int, error) {
args := env.Called()
return args.Int(0), args.Error(1)
}
func (env *MockedEnvironment) CachePath() string {
args := env.Called()
return args.String(0)
}
func (env *MockedEnvironment) Cache() Cache {
args := env.Called()
return args.Get(0).(Cache)
}
func (env *MockedEnvironment) Close() {
_ = env.Called()
}
func (env *MockedEnvironment) Logs() string {
args := env.Called()
return args.String(0)
}
func (env *MockedEnvironment) InWSLSharedDrive() bool {
args := env.Called()
return args.Bool(0)
}
func (env *MockedEnvironment) ConvertToWindowsPath(path string) string {
args := env.Called()
return args.String(0)
}
func (env *MockedEnvironment) ConvertToLinuxPath(path string) string {
args := env.Called()
return args.String(0)
}
func (env *MockedEnvironment) WifiNetwork() (*WifiInfo, error) {
args := env.Called()
return args.Get(0).(*WifiInfo), args.Error(1)
}
func (env *MockedEnvironment) TemplateCache() *TemplateCache {
args := env.Called()
return args.Get(0).(*TemplateCache)
}
func renderTemplate(env *MockedEnvironment, segmentTemplate string, context interface{}) string {
func renderTemplate(env *mock.MockedEnvironment, segmentTemplate string, context interface{}) string {
found := false
for _, call := range env.Mock.ExpectedCalls {
if call.Method == "TemplateCache" {
@ -217,7 +19,7 @@ func renderTemplate(env *MockedEnvironment, segmentTemplate string, context inte
}
}
if !found {
env.On("TemplateCache").Return(&TemplateCache{
env.On("TemplateCache").Return(&environment.TemplateCache{
Env: make(map[string]string),
})
}
@ -242,7 +44,7 @@ const (
func TestIsInHomeDirTrue(t *testing.T) {
home := homeBill
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("Home").Return(home)
path := &path{
env: env,
@ -257,7 +59,7 @@ func TestIsInHomeDirLevelTrue(t *testing.T) {
for i := 0; i < 99; i++ {
pwd += levelDir
}
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("Home").Return(home)
path := &path{
env: env,
@ -286,10 +88,10 @@ func TestRootLocationHome(t *testing.T) {
{Expected: "DRIVE:", HomePath: "/home/bill/", Pwd: "/usr/error/what", Pswd: "DRIVE:", PathSeperator: "/"},
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("Home").Return(tc.HomePath)
env.On("Pwd").Return(tc.Pwd)
args := &Args{
args := &environment.Args{
PSWD: &tc.Pswd,
}
env.On("Args").Return(args)
@ -309,7 +111,7 @@ func TestRootLocationHome(t *testing.T) {
func TestIsInHomeDirFalse(t *testing.T) {
home := homeBill
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("Home").Return(home)
path := &path{
env: env,
@ -323,7 +125,7 @@ func TestPathDepthMultipleLevelsDeep(t *testing.T) {
for i := 0; i < 99; i++ {
pwd += levelDir
}
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("PathSeperator").Return("/")
env.On("getRunteGOOS").Return("")
path := &path{
@ -335,7 +137,7 @@ func TestPathDepthMultipleLevelsDeep(t *testing.T) {
func TestPathDepthZeroLevelsDeep(t *testing.T) {
pwd := "/usr/"
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("PathSeperator").Return("/")
path := &path{
env: env,
@ -346,7 +148,7 @@ func TestPathDepthZeroLevelsDeep(t *testing.T) {
func TestPathDepthOneLevelDeep(t *testing.T) {
pwd := "/usr/location"
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("PathSeperator").Return("/")
path := &path{
env: env,
@ -437,14 +239,14 @@ func TestAgnosterPathStyles(t *testing.T) {
{Style: Letter, Expected: "➼ s > .w > man", HomePath: "/usr/home", Pwd: "➼ something/.whatever/man", PathSeperator: "/", FolderSeparatorIcon: " > "},
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
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{
args := &environment.Args{
PSWD: &tc.Pswd,
}
env.On("Args").Return(args)
@ -505,8 +307,8 @@ func TestGetFullPath(t *testing.T) {
{Style: Folder, FolderSeparatorIcon: "|", Pwd: "/usr/home/abc", Expected: "abc"},
{Style: Folder, FolderSeparatorIcon: "|", Pwd: "/a/b/c/d", Expected: "d"},
{Style: Folder, FolderSeparatorIcon: "\\", Pwd: "C:\\", Expected: "C:\\", PathSeparator: "\\", GOOS: windowsPlatform},
{Style: Full, FolderSeparatorIcon: "\\", Pwd: "C:\\Users\\Jan", Expected: "C:\\Users\\Jan", PathSeparator: "\\", GOOS: windowsPlatform},
{Style: Folder, FolderSeparatorIcon: "\\", Pwd: "C:\\", Expected: "C:\\", PathSeparator: "\\", GOOS: environment.WindowsPlatform},
{Style: Full, FolderSeparatorIcon: "\\", Pwd: "C:\\Users\\Jan", Expected: "C:\\Users\\Jan", PathSeparator: "\\", GOOS: environment.WindowsPlatform},
// StackCountEnabled=true and StackCount=2
{Style: Full, FolderSeparatorIcon: "|", Pwd: "/", StackCount: 2, Expected: "2 /"},
@ -555,7 +357,7 @@ func TestGetFullPath(t *testing.T) {
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
if len(tc.PathSeparator) == 0 {
tc.PathSeparator = "/"
}
@ -565,7 +367,7 @@ func TestGetFullPath(t *testing.T) {
env.On("GOOS").Return(tc.GOOS)
env.On("StackCount").Return(tc.StackCount)
env.On("IsWsl").Return(false)
args := &Args{
args := &environment.Args{
PSWD: &tc.Pswd,
}
env.On("Args").Return(args)
@ -609,12 +411,12 @@ func TestGetFullPathCustomMappedLocations(t *testing.T) {
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("PathSeperator").Return("/")
env.On("Home").Return("/usr/home")
env.On("Pwd").Return(tc.Pwd)
env.On("GOOS").Return("")
args := &Args{
args := &environment.Args{
PSWD: &tc.Pwd,
}
env.On("Args").Return(args)
@ -636,18 +438,18 @@ func TestNormalizePath(t *testing.T) {
GOOS string
Expected string
}{
{Input: "C:\\Users\\Bob\\Foo", GOOS: linuxPlatform, Expected: "C:/Users/Bob/Foo"},
{Input: "C:\\Users\\Bob\\Foo", GOOS: windowsPlatform, Expected: "c:/users/bob/foo"},
{Input: "~\\Bob\\Foo", GOOS: linuxPlatform, Expected: "/usr/home/Bob/Foo"},
{Input: "~\\Bob\\Foo", GOOS: windowsPlatform, Expected: "/usr/home/bob/foo"},
{Input: "/foo/~/bar", GOOS: linuxPlatform, Expected: "/foo/~/bar"},
{Input: "/foo/~/bar", GOOS: windowsPlatform, Expected: "/foo/~/bar"},
{Input: "~/baz", GOOS: linuxPlatform, Expected: "/usr/home/baz"},
{Input: "~/baz", GOOS: windowsPlatform, Expected: "/usr/home/baz"},
{Input: "C:\\Users\\Bob\\Foo", GOOS: environment.LinuxPlatform, Expected: "C:/Users/Bob/Foo"},
{Input: "C:\\Users\\Bob\\Foo", GOOS: environment.WindowsPlatform, Expected: "c:/users/bob/foo"},
{Input: "~\\Bob\\Foo", GOOS: environment.LinuxPlatform, Expected: "/usr/home/Bob/Foo"},
{Input: "~\\Bob\\Foo", GOOS: environment.WindowsPlatform, Expected: "/usr/home/bob/foo"},
{Input: "/foo/~/bar", GOOS: environment.LinuxPlatform, Expected: "/foo/~/bar"},
{Input: "/foo/~/bar", GOOS: environment.WindowsPlatform, Expected: "/foo/~/bar"},
{Input: "~/baz", GOOS: environment.LinuxPlatform, Expected: "/usr/home/baz"},
{Input: "~/baz", GOOS: environment.WindowsPlatform, Expected: "/usr/home/baz"},
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("Home").Return("/usr/home")
env.On("GOOS").Return(tc.GOOS)
pt := &path{
@ -660,12 +462,12 @@ func TestNormalizePath(t *testing.T) {
func TestGetFolderPathCustomMappedLocations(t *testing.T) {
pwd := "/a/b/c/d"
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("PathSeperator").Return("/")
env.On("Home").Return("/usr/home")
env.On("Pwd").Return(pwd)
env.On("GOOS").Return("")
args := &Args{
args := &environment.Args{
PSWD: &pwd,
}
env.On("Args").Return(args)
@ -707,12 +509,12 @@ func TestAgnosterPath(t *testing.T) { // nolint:dupl
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("Home").Return(tc.Home)
env.On("PathSeperator").Return(tc.PathSeparator)
env.On("Pwd").Return(tc.PWD)
env.On("GOOS").Return("")
args := &Args{
args := &environment.Args{
PSWD: &tc.PWD,
}
env.On("Args").Return(args)
@ -755,12 +557,12 @@ func TestAgnosterLeftPath(t *testing.T) { // nolint:dupl
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("Home").Return(tc.Home)
env.On("PathSeperator").Return(tc.PathSeparator)
env.On("Pwd").Return(tc.PWD)
env.On("GOOS").Return("")
args := &Args{
args := &environment.Args{
PSWD: &tc.PWD,
}
env.On("Args").Return(args)
@ -803,12 +605,12 @@ func TestGetPwd(t *testing.T) {
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("PathSeperator").Return("/")
env.On("Home").Return("/usr/home")
env.On("Pwd").Return(tc.Pwd)
env.On("GOOS").Return("")
args := &Args{
args := &environment.Args{
PSWD: &tc.Pswd,
}
env.On("Args").Return(args)

View file

@ -1,5 +1,7 @@
package main
import "oh-my-posh/environment"
type php struct {
language
}
@ -8,7 +10,7 @@ func (p *php) template() string {
return languageTemplate
}
func (p *php) init(props Properties, env Environment) {
func (p *php) init(props Properties, env environment.Environment) {
p.language = language{
env: env,
props: props,

View file

@ -2,6 +2,8 @@ package main
import (
"fmt"
"oh-my-posh/environment"
"oh-my-posh/regex"
"strconv"
"strings"
)
@ -34,7 +36,7 @@ type plastic struct {
plasticWorkspaceFolder string // root folder of workspace
}
func (p *plastic) init(props Properties, env Environment) {
func (p *plastic) init(props Properties, env environment.Environment) {
p.props = props
p.env = env
}
@ -94,7 +96,7 @@ func (p *plastic) parseFilesStatus(output []string) {
continue
}
p.MergePending = p.MergePending || matchString(`(?i)\smerge\s+from\s+[0-9]+\s*$`, line)
p.MergePending = p.MergePending || regex.MatchString(`(?i)\smerge\s+from\s+[0-9]+\s*$`, line)
code := line[:2]
p.Status.add(code)
@ -102,7 +104,7 @@ func (p *plastic) parseFilesStatus(output []string) {
}
func (p *plastic) parseStringPattern(output, pattern, name string) string {
match := findNamedRegexMatch(pattern, output)
match := regex.FindNamedRegexMatch(pattern, output)
if sValue, ok := match[name]; ok {
return sValue
}

View file

@ -1,13 +1,15 @@
package main
import (
"oh-my-posh/environment"
"oh-my-posh/mock"
"testing"
"github.com/stretchr/testify/assert"
)
func TestPlasticEnabledNotFound(t *testing.T) {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("HasCommand", "cm").Return(false)
env.On("GOOS").Return("")
env.On("IsWsl").Return(false)
@ -21,12 +23,12 @@ func TestPlasticEnabledNotFound(t *testing.T) {
}
func TestPlasticEnabledInWorkspaceDirectory(t *testing.T) {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
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{
fileInfo := &environment.FileInfo{
Path: "/dir/hello",
ParentFolder: "/dir",
IsDir: true,
@ -43,7 +45,7 @@ func TestPlasticEnabledInWorkspaceDirectory(t *testing.T) {
}
func setupCmStatusEnv(status, headStatus string) *plastic {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("RunCommand", "cm", []string{"status", "--all", "--machinereadable"}).Return(status, nil)
env.On("RunCommand", "cm", []string{"status", "--head", "--machinereadable"}).Return(headStatus, nil)
p := &plastic{
@ -329,7 +331,7 @@ func TestPlasticTemplateString(t *testing.T) {
FetchStatus: true,
}
tc.Plastic.props = props
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
tc.Plastic.env = env
assert.Equal(t, tc.Expected, renderTemplate(env, tc.Template, tc.Plastic), tc.Case)
}

View file

@ -1,10 +1,13 @@
package main
import "strings"
import (
"oh-my-posh/environment"
"strings"
)
type poshgit struct {
props Properties
env Environment
env environment.Environment
Status string
}
@ -23,7 +26,7 @@ func (p *poshgit) enabled() bool {
return p.Status != ""
}
func (p *poshgit) init(props Properties, env Environment) {
func (p *poshgit) init(props Properties, env environment.Environment) {
p.props = props
p.env = env
}

View file

@ -1,6 +1,7 @@
package main
import (
"oh-my-posh/mock"
"testing"
"github.com/stretchr/testify/assert"
@ -19,7 +20,7 @@ func TestPoshGitSegment(t *testing.T) {
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("Getenv", poshGitEnv).Return(tc.PoshGitPrompt)
p := &poshgit{
env: env,

View file

@ -1,5 +1,7 @@
package main
import "oh-my-posh/environment"
type python struct {
language
@ -15,7 +17,7 @@ func (p *python) template() string {
return languageTemplate
}
func (p *python) init(props Properties, env Environment) {
func (p *python) init(props Properties, env environment.Environment) {
p.language = language{
env: env,
props: props,
@ -57,7 +59,7 @@ func (p *python) loadContext() {
var venv string
for _, venvVar := range venvVars {
venv = p.language.env.Getenv(venvVar)
name := base(venv, p.language.env)
name := environment.Base(p.language.env, venv)
if p.canUseVenvName(name) {
p.Venv = name
break

View file

@ -1,6 +1,8 @@
package main
import (
"oh-my-posh/environment"
"oh-my-posh/mock"
"testing"
"github.com/alecthomas/assert"
@ -41,7 +43,7 @@ func TestPythonTemplate(t *testing.T) {
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.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)
@ -56,7 +58,7 @@ func TestPythonTemplate(t *testing.T) {
FetchVersion: tc.FetchVersion,
DisplayMode: DisplayModeAlways,
}
env.On("TemplateCache").Return(&TemplateCache{
env.On("TemplateCache").Return(&environment.TemplateCache{
Env: make(map[string]string),
})
python := &python{}
@ -76,7 +78,7 @@ func TestPythonPythonInContext(t *testing.T) {
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("PathSeperator").Return("")
env.On("Getenv", "VIRTUAL_ENV").Return(tc.VirtualEnvName)
env.On("Getenv", "CONDA_ENV_PATH").Return("")

View file

@ -1,8 +1,10 @@
package main
import "oh-my-posh/environment"
type root struct {
props Properties
env Environment
env environment.Environment
}
func (rt *root) template() string {
@ -13,7 +15,7 @@ func (rt *root) enabled() bool {
return rt.env.Root()
}
func (rt *root) init(props Properties, env Environment) {
func (rt *root) init(props Properties, env environment.Environment) {
rt.props = props
rt.env = env
}

View file

@ -1,5 +1,7 @@
package main
import "oh-my-posh/environment"
type ruby struct {
language
}
@ -8,7 +10,7 @@ func (r *ruby) template() string {
return languageTemplate
}
func (r *ruby) init(props Properties, env Environment) {
func (r *ruby) init(props Properties, env environment.Environment) {
r.language = language{
env: env,
props: props,

View file

@ -2,6 +2,7 @@ package main
import (
"fmt"
"oh-my-posh/mock"
"testing"
"github.com/stretchr/testify/assert"
@ -82,7 +83,7 @@ func TestRuby(t *testing.T) {
},
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.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)

View file

@ -1,5 +1,7 @@
package main
import "oh-my-posh/environment"
type rust struct {
language
}
@ -8,7 +10,7 @@ func (r *rust) template() string {
return languageTemplate
}
func (r *rust) init(props Properties, env Environment) {
func (r *rust) init(props Properties, env environment.Environment) {
r.language = language{
env: env,
props: props,

View file

@ -1,8 +1,10 @@
package main
import "oh-my-posh/environment"
type session struct {
props Properties
env Environment
env environment.Environment
// text string
SSHSession bool
@ -20,7 +22,7 @@ func (s *session) template() string {
return "{{ .UserName }}@{{ .HostName }}"
}
func (s *session) init(props Properties, env Environment) {
func (s *session) init(props Properties, env environment.Environment) {
s.props = props
s.env = env
}

View file

@ -1,6 +1,8 @@
package main
import (
"oh-my-posh/environment"
"oh-my-posh/mock"
"testing"
"github.com/stretchr/testify/assert"
@ -86,7 +88,7 @@ func TestSessionSegmentTemplate(t *testing.T) {
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("User").Return(tc.UserName)
env.On("GOOS").Return("burp")
env.On("Host").Return(tc.ComputerName, nil)
@ -96,7 +98,7 @@ func TestSessionSegmentTemplate(t *testing.T) {
}
env.On("Getenv", "SSH_CONNECTION").Return(SSHSession)
env.On("Getenv", "SSH_CLIENT").Return(SSHSession)
env.On("TemplateCache").Return(&TemplateCache{
env.On("TemplateCache").Return(&environment.TemplateCache{
UserName: tc.UserName,
HostName: tc.ComputerName,
Env: map[string]string{

View file

@ -1,10 +1,13 @@
package main
import "strings"
import (
"oh-my-posh/environment"
"strings"
)
type shell struct {
props Properties
env Environment
env environment.Environment
Name string
}
@ -30,7 +33,7 @@ func (s *shell) enabled() bool {
return true
}
func (s *shell) init(props Properties, env Environment) {
func (s *shell) init(props Properties, env environment.Environment) {
s.props = props
s.env = env
}

View file

@ -1,6 +1,7 @@
package main
import (
"oh-my-posh/mock"
"testing"
"github.com/stretchr/testify/assert"
@ -8,7 +9,7 @@ import (
func TestWriteCurrentShell(t *testing.T) {
expected := "zsh"
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("Shell").Return(expected, nil)
s := &shell{
env: env,
@ -28,7 +29,7 @@ func TestUseMappedShellNames(t *testing.T) {
{Shell: "PWSH", Expected: "PS"},
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("Shell").Return(tc.Expected, nil)
s := &shell{
env: env,

View file

@ -1,8 +1,10 @@
package main
import "oh-my-posh/environment"
type spotify struct {
props Properties
env Environment
env environment.Environment
MusicPlayer
}
@ -43,7 +45,7 @@ func (s *spotify) resolveIcon() {
}
}
func (s *spotify) init(props Properties, env Environment) {
func (s *spotify) init(props Properties, env environment.Environment) {
s.props = props
s.env = env
}

View file

@ -4,6 +4,7 @@ package main
import (
"errors"
"oh-my-posh/mock"
"testing"
"github.com/stretchr/testify/assert"
@ -24,7 +25,7 @@ func TestSpotifyDarwinEnabledAndSpotifyPlaying(t *testing.T) {
{Running: "true", Expected: "\uF8E3 Candlemass - Spellbreaker", Status: "paused", Artist: "Candlemass", Track: "Spellbreaker"},
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.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)

View file

@ -1,6 +1,7 @@
package main
import (
"oh-my-posh/mock"
"testing"
"github.com/stretchr/testify/assert"
@ -8,7 +9,7 @@ import (
func TestSpotifyStringPlayingSong(t *testing.T) {
expected := "\ue602 Candlemass - Spellbreaker"
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
s := &spotify{
MusicPlayer: MusicPlayer{
Artist: "Candlemass",
@ -24,7 +25,7 @@ func TestSpotifyStringPlayingSong(t *testing.T) {
func TestSpotifyStringStoppedSong(t *testing.T) {
expected := "\uf04d "
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
s := &spotify{
MusicPlayer: MusicPlayer{
Artist: "Candlemass",

View file

@ -4,6 +4,7 @@ package main
import (
"errors"
"oh-my-posh/mock"
"testing"
"github.com/stretchr/testify/assert"
@ -15,9 +16,8 @@ type spotifyArgs struct {
}
func bootStrapSpotifyWindowsTest(args *spotifyArgs) *spotify {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("WindowTitle", "spotify.exe").Return(args.title, args.runError)
env.onTemplate()
s := &spotify{
env: env,
props: properties{},
@ -37,9 +37,14 @@ func TestSpotifyWindowsEnabledAndSpotifyPlaying(t *testing.T) {
args := &spotifyArgs{
title: "Candlemass - Spellbreaker",
}
s := bootStrapSpotifyWindowsTest(args)
env := new(mock.MockedEnvironment)
env.On("WindowTitle", "spotify.exe").Return(args.title, args.runError)
s := &spotify{
env: env,
props: properties{},
}
assert.Equal(t, true, s.enabled())
assert.Equal(t, "\ue602 Candlemass - Spellbreaker", s.string())
assert.Equal(t, "\ue602 Candlemass - Spellbreaker", renderTemplate(env, s.template(), s))
}
func TestSpotifyWindowsEnabledAndSpotifyStopped(t *testing.T) {

View file

@ -6,6 +6,8 @@ import (
"fmt"
"testing"
"oh-my-posh/mock"
"github.com/stretchr/testify/assert"
)
@ -51,15 +53,14 @@ func TestSpotifyWsl(t *testing.T) {
ExecOutput: ""},
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.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.onTemplate()
s := &spotify{
env: env,
props: properties{},
}
assert.Equal(t, tc.ExpectedEnabled, s.enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
assert.Equal(t, tc.ExpectedString, s.string(), fmt.Sprintf("Failed in case: %s", tc.Case))
assert.Equal(t, tc.ExpectedString, renderTemplate(env, s.template(), s), fmt.Sprintf("Failed in case: %s", tc.Case))
}
}

View file

@ -6,13 +6,14 @@ import (
"fmt"
"math"
"net/http"
"oh-my-posh/environment"
"time"
)
// segment struct, makes templating easier
type strava struct {
props Properties
env Environment
env environment.Environment
StravaData
Icon string
@ -229,7 +230,7 @@ func (s *strava) getResult() (*StravaData, error) {
return data, nil
}
func (s *strava) init(props Properties, env Environment) {
func (s *strava) init(props Properties, env environment.Environment) {
s.props = props
s.env = env
}

View file

@ -3,6 +3,7 @@ package main
import (
"errors"
"fmt"
"oh-my-posh/mock"
"testing"
"time"
@ -135,13 +136,13 @@ func TestStravaSegment(t *testing.T) {
}
for _, tc := range cases {
env := &MockedEnvironment{}
env := &mock.MockedEnvironment{}
url := "https://www.strava.com/api/v3/athlete/activities?page=1&per_page=1"
tokenURL := fmt.Sprintf("https://ohmyposh.dev/api/refresh?segment=strava&token=%s", tc.TokenRefreshToken)
var props properties = map[Property]interface{}{
CacheTimeout: tc.CacheTimeout,
}
cache := &MockedCache{}
cache := &mock.MockedCache{}
cache.On("Get", url).Return(tc.JSONResponse, !tc.CacheFoundFail)
cache.On("Set", url, tc.JSONResponse, tc.CacheTimeout).Return()

View file

@ -1,6 +1,8 @@
package main
import (
"oh-my-posh/environment"
cpu "github.com/shirou/gopsutil/v3/cpu"
load "github.com/shirou/gopsutil/v3/load"
mem "github.com/shirou/gopsutil/v3/mem"
@ -8,7 +10,7 @@ import (
type sysinfo struct {
props Properties
env Environment
env environment.Environment
Precision int
// mem
PhysicalTotalMemory uint64
@ -42,7 +44,7 @@ func (s *sysinfo) enabled() bool {
return true
}
func (s *sysinfo) init(props Properties, env Environment) {
func (s *sysinfo) init(props Properties, env environment.Environment) {
s.props = props
s.env = env
s.Precision = s.props.getInt(Precision, 2)

View file

@ -1,6 +1,7 @@
package main
import (
"oh-my-posh/mock"
"testing"
"github.com/shirou/gopsutil/v3/cpu"
@ -49,7 +50,7 @@ func TestSysInfo(t *testing.T) {
}
for _, tc := range cases {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
tc.SysInfo.env = env
tc.SysInfo.props = properties{
Precision: tc.Precision,

View file

@ -1,8 +1,13 @@
package main
import (
"oh-my-posh/environment"
)
type terraform struct {
props Properties
env Environment
props Properties
env environment.Environment
WorkspaceName string
}
@ -10,7 +15,7 @@ func (tf *terraform) template() string {
return "{{ .WorkspaceName }}"
}
func (tf *terraform) init(props Properties, env Environment) {
func (tf *terraform) init(props Properties, env environment.Environment) {
tf.props = props
tf.env = env
}

View file

@ -1,6 +1,7 @@
package main
import (
"oh-my-posh/mock"
"testing"
"github.com/stretchr/testify/assert"
@ -13,7 +14,7 @@ type terraformArgs struct {
}
func bootStrapTerraformTest(args *terraformArgs) *terraform {
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
env.On("HasCommand", "terraform").Return(args.hasTfCommand)
env.On("HasFolder", "/.terraform").Return(args.hasTfFolder)
env.On("Pwd").Return("")

View file

@ -2,6 +2,8 @@ package main
import (
"encoding/json"
"oh-my-posh/environment"
"oh-my-posh/mock"
"testing"
"github.com/stretchr/testify/assert"
@ -15,7 +17,7 @@ func TestMapSegmentWriterCanMap(t *testing.T) {
sc := &Segment{
Type: Session,
}
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
err := sc.mapSegmentWithWriter(env)
assert.NoError(t, err)
assert.NotNil(t, sc.writer)
@ -25,7 +27,7 @@ func TestMapSegmentWriterCannotMap(t *testing.T) {
sc := &Segment{
Type: "nilwriter",
}
env := new(MockedEnvironment)
env := new(mock.MockedEnvironment)
err := sc.mapSegmentWithWriter(env)
assert.Error(t, err)
}
@ -79,8 +81,8 @@ func TestShouldIncludeFolder(t *testing.T) {
{Case: "Include Mismatch / Exclude Mismatch", IncludeFolders: []string{"zProjects.*"}, ExcludeFolders: []string{"Projects/nope"}, Expected: false},
}
for _, tc := range cases {
env := new(MockedEnvironment)
env.On("GOOS").Return(linuxPlatform)
env := new(mock.MockedEnvironment)
env.On("GOOS").Return(environment.LinuxPlatform)
env.On("Home").Return("")
env.On("Pwd").Return(cwd)
segment := &Segment{
@ -96,8 +98,8 @@ func TestShouldIncludeFolder(t *testing.T) {
}
func TestShouldIncludeFolderRegexInverted(t *testing.T) {
env := new(MockedEnvironment)
env.On("GOOS").Return(linuxPlatform)
env := new(mock.MockedEnvironment)
env.On("GOOS").Return(environment.LinuxPlatform)
env.On("Home").Return("")
env.On("Pwd").Return(cwd)
segment := &Segment{
@ -117,8 +119,8 @@ func TestShouldIncludeFolderRegexInverted(t *testing.T) {
}
func TestShouldIncludeFolderRegexInvertedNonEscaped(t *testing.T) {
env := new(MockedEnvironment)
env.On("GOOS").Return(linuxPlatform)
env := new(mock.MockedEnvironment)
env.On("GOOS").Return(environment.LinuxPlatform)
env.On("Home").Return("")
env.On("Pwd").Return(cwd)
segment := &Segment{
@ -190,8 +192,8 @@ func TestGetColors(t *testing.T) {
},
}
for _, tc := range cases {
env := new(MockedEnvironment)
env.On("TemplateCache").Return(&TemplateCache{
env := new(mock.MockedEnvironment)
env.On("TemplateCache").Return(&environment.TemplateCache{
Env: make(map[string]string),
})
segment := &Segment{

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