refactor: linting checks for all platforms

This commit is contained in:
Jan De Dobbeleer 2020-11-12 09:43:32 +01:00 committed by Jan De Dobbeleer
parent 3c812f916e
commit 8fb190e074
49 changed files with 537 additions and 443 deletions

View file

@ -9,6 +9,7 @@ root = true
indent_style = space indent_style = space
trim_trailing_whitespace = true trim_trailing_whitespace = true
insert_final_newline = true insert_final_newline = true
end_of_line = lf
; Go Code - match go fmt ; Go Code - match go fmt
[*.go] [*.go]

1
.gitattributes vendored Normal file
View file

@ -0,0 +1 @@
* text=auto eol=lf

View file

@ -27,7 +27,6 @@ jobs:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Golang CI - name: Golang CI
if: matrix.os == 'ubuntu-latest'
uses: golangci/golangci-lint-action@v2 uses: golangci/golangci-lint-action@v2
with: with:
version: v1.31 version: v1.31

0
.gitignore vendored Executable file → Normal file
View file

50
.golangci.yml Normal file
View file

@ -0,0 +1,50 @@
linters:
disable-all: true
enable:
- bodyclose
- deadcode
- depguard
- dupl
- errcheck
- exhaustive
- gochecknoinits
- goconst
- gocritic
- gocyclo
- gofmt
- goimports
- golint
- goprintffuncname
- gosimple
- govet
- ineffassign
- interfacer
- misspell
- nakedret
- noctx
- nolintlint
- rowserrcheck
- scopelint
- staticcheck
- structcheck
- typecheck
- unconvert
- unparam
- unused
- varcheck
- whitespace
- lll
linters-settings:
gocritic:
enabled-tags:
- diagnostic
- experimental
- opinionated
- performance
- style
disabled-tags:
- experimental
disabled-checks:
- ifElseChain
lll:
line-length: 180

View file

@ -1,49 +1,49 @@
<?xml version="1.0" encoding="iso-8859-1"?> <?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" <svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 30.851 30.851" style="enable-background:new 0 0 30.851 30.851;" xml:space="preserve"> viewBox="0 0 30.851 30.851" style="enable-background:new 0 0 30.851 30.851;" xml:space="preserve">
<g> <g>
<g id="c43_terminal"> <g id="c43_terminal">
<path d="M28.645,2.203H2.204C0.987,2.203,0,3.188,0,4.405v22.038c0,1.216,0.987,2.204,2.204,2.204h26.441 <path d="M28.645,2.203H2.204C0.987,2.203,0,3.188,0,4.405v22.038c0,1.216,0.987,2.204,2.204,2.204h26.441
c1.215,0,2.206-0.988,2.206-2.204V4.405C30.851,3.188,29.859,2.203,28.645,2.203z M7.162,3.857c0.607,0,1.102,0.491,1.102,1.103 c1.215,0,2.206-0.988,2.206-2.204V4.405C30.851,3.188,29.859,2.203,28.645,2.203z M7.162,3.857c0.607,0,1.102,0.491,1.102,1.103
c0,0.607-0.494,1.098-1.102,1.098c-0.611,0-1.104-0.49-1.104-1.098C6.059,4.349,6.551,3.857,7.162,3.857z M3.855,3.857 c0,0.607-0.494,1.098-1.102,1.098c-0.611,0-1.104-0.49-1.104-1.098C6.059,4.349,6.551,3.857,7.162,3.857z M3.855,3.857
c0.608,0,1.102,0.491,1.102,1.103c0,0.607-0.493,1.098-1.102,1.098S2.752,5.568,2.752,4.96C2.753,4.349,3.246,3.857,3.855,3.857z c0.608,0,1.102,0.491,1.102,1.103c0,0.607-0.493,1.098-1.102,1.098S2.752,5.568,2.752,4.96C2.753,4.349,3.246,3.857,3.855,3.857z
M28.645,26.444H2.204V7.735h26.441V26.444z"/> M28.645,26.444H2.204V7.735h26.441V26.444z"/>
<polygon points="12.351,12.264 5.275,9.028 5.275,10.589 10.746,12.929 10.746,12.958 5.275,15.294 5.275,16.854 12.351,13.618 <polygon points="12.351,12.264 5.275,9.028 5.275,10.589 10.746,12.929 10.746,12.958 5.275,15.294 5.275,16.854 12.351,13.618
"/> "/>
<rect x="15.682" y="12.199" width="3.855" height="1.486"/> <rect x="15.682" y="12.199" width="3.855" height="1.486"/>
</g> </g>
<g id="Capa_1_86_"> <g id="Capa_1_86_">
</g> </g>
</g> </g>
<g> <g>
</g> </g>
<g> <g>
</g> </g>
<g> <g>
</g> </g>
<g> <g>
</g> </g>
<g> <g>
</g> </g>
<g> <g>
</g> </g>
<g> <g>
</g> </g>
<g> <g>
</g> </g>
<g> <g>
</g> </g>
<g> <g>
</g> </g>
<g> <g>
</g> </g>
<g> <g>
</g> </g>
<g> <g>
</g> </g>
<g> <g>
</g> </g>
<g> <g>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -27,7 +27,7 @@ func (e *engine) getPowerlineColor(foreground bool) string {
return e.previousActiveSegment.Background return e.previousActiveSegment.Background
} }
func (e *engine) writePowerLineSeparator(background string, foreground string, end bool) { func (e *engine) writePowerLineSeparator(background, foreground string, end bool) {
symbol := e.activeSegment.PowerlineSymbol symbol := e.activeSegment.PowerlineSymbol
if end { if end {
symbol = e.previousActiveSegment.PowerlineSymbol symbol = e.previousActiveSegment.PowerlineSymbol
@ -75,7 +75,7 @@ func (e *engine) renderSegmentText(text string) {
e.renderPlainSegment(text) e.renderPlainSegment(text)
case Diamond: case Diamond:
e.renderDiamondSegment(text) e.renderDiamondSegment(text)
default: case Powerline:
e.renderPowerLineSegment(text) e.renderPowerLineSegment(text)
} }
e.previousActiveSegment = e.activeSegment e.previousActiveSegment = e.activeSegment
@ -135,7 +135,7 @@ func (e *engine) render() {
cursorMove := e.renderer.setCursorForRightWrite(blockText, block.HorizontalOffset) cursorMove := e.renderer.setCursorForRightWrite(blockText, block.HorizontalOffset)
e.renderer.print(cursorMove) e.renderer.print(cursorMove)
e.renderer.print(blockText) e.renderer.print(blockText)
default: case Left:
e.renderer.print(e.renderBlockSegments(block)) e.renderer.print(e.renderBlockSegments(block))
} }
} }

View file

@ -16,6 +16,11 @@ import (
"github.com/shirou/gopsutil/process" "github.com/shirou/gopsutil/process"
) )
const (
unknown = "unknown"
windowsPlatform = "windows"
)
type environmentInfo interface { type environmentInfo interface {
getenv(key string) string getenv(key string) string
getcwd() string getcwd() string
@ -31,12 +36,12 @@ type environmentInfo interface {
getPlatform() string getPlatform() string
hasCommand(command string) bool hasCommand(command string) bool
runCommand(command string, args ...string) (string, error) runCommand(command string, args ...string) (string, error)
runShellCommand(shell string, command string) string runShellCommand(shell, command string) string
lastErrorCode() int lastErrorCode() int
getArgs() *args getArgs() *args
getBatteryInfo() (*battery.Battery, error) getBatteryInfo() (*battery.Battery, error)
getShellName() string getShellName() string
getWindowTitle(imageName string, windowTitleRegex string) (string, error) getWindowTitle(imageName, windowTitleRegex string) (string, error)
} }
type environment struct { type environment struct {
@ -124,8 +129,8 @@ func (env *environment) getRuntimeGOOS() string {
} }
func (env *environment) getPlatform() string { func (env *environment) getPlatform() string {
if runtime.GOOS == "windows" { if runtime.GOOS == windowsPlatform {
return "windows" return windowsPlatform
} }
p, _, _, _ := host.PlatformInformation() p, _, _, _ := host.PlatformInformation()
@ -146,7 +151,7 @@ func (env *environment) runCommand(command string, args ...string) (string, erro
return strings.TrimSpace(string(out)), nil return strings.TrimSpace(string(out)), nil
} }
func (env *environment) runShellCommand(shell string, command string) string { func (env *environment) runShellCommand(shell, command string) string {
out, err := exec.Command(shell, "-c", command).Output() out, err := exec.Command(shell, "-c", command).Output()
if err != nil { if err != nil {
log.Println(err) log.Println(err)
@ -177,14 +182,14 @@ func (env *environment) getShellName() string {
p, _ := process.NewProcess(int32(pid)) p, _ := process.NewProcess(int32(pid))
name, err := p.Name() name, err := p.Name()
if err != nil { if err != nil {
return "unknown" return unknown
} }
if name == "cmd.exe" { if name == "cmd.exe" {
p, _ = p.Parent() p, _ = p.Parent()
name, err = p.Name() name, err = p.Name()
} }
if err != nil { if err != nil {
return "unknown" return unknown
} }
shell := strings.Replace(name, ".exe", "", 1) shell := strings.Replace(name, ".exe", "", 1)
return strings.Trim(shell, " ") return strings.Trim(shell, " ")

2
environment_unix.go Executable file → Normal file
View file

@ -15,6 +15,6 @@ func (env *environment) homeDir() string {
return os.Getenv("HOME") return os.Getenv("HOME")
} }
func (env *environment) getWindowTitle(imageName string, windowTitleRegex string) (string, error) { func (env *environment) getWindowTitle(imageName, windowTitleRegex string) (string, error) {
return "", errors.New("not implemented") return "", errors.New("not implemented")
} }

6
environment_windows.go Executable file → Normal file
View file

@ -25,7 +25,9 @@ func (env *environment) isRunningAsRoot() bool {
if err != nil { if err != nil {
return false return false
} }
defer windows.FreeSid(sid) defer func() {
_ = windows.FreeSid(sid)
}()
// This appears to cast a null pointer so I'm not sure why this // This appears to cast a null pointer so I'm not sure why this
// works, but this guy says it does and it Works for Me™: // works, but this guy says it does and it Works for Me™:
@ -48,6 +50,6 @@ func (env *environment) homeDir() string {
return home return home
} }
func (env *environment) getWindowTitle(imageName string, windowTitleRegex string) (string, error) { func (env *environment) getWindowTitle(imageName, windowTitleRegex string) (string, error) {
return getWindowTitle(imageName, windowTitleRegex) return getWindowTitle(imageName, windowTitleRegex)
} }

View file

@ -35,7 +35,7 @@ func getImagePid(imageName string) ([]int, error) {
} }
// getWindowTitle returns the title of a window linked to a process name // getWindowTitle returns the title of a window linked to a process name
func getWindowTitle(imageName string, windowTitleRegex string) (string, error) { func getWindowTitle(imageName, windowTitleRegex string) (string, error) {
processPid, err := getImagePid(imageName) processPid, err := getImagePid(imageName)
if err != nil { if err != nil {
return "", nil return "", nil
@ -73,7 +73,9 @@ func processes() ([]WindowsProcess, error) {
if err != nil { if err != nil {
return nil, syscall.GetLastError() return nil, syscall.GetLastError()
} }
defer windows.CloseHandle(handle) defer func() {
_ = windows.CloseHandle(handle)
}()
// get process infor by looping through the snapshot // get process infor by looping through the snapshot
var entry windows.ProcessEntry32 var entry windows.ProcessEntry32
@ -109,8 +111,8 @@ var (
) )
// EnumWindows call EnumWindows from user32 and returns all active windows // EnumWindows call EnumWindows from user32 and returns all active windows
func EnumWindows(enumFunc uintptr, lparam uintptr) (err error) { func EnumWindows(enumFunc, lparam uintptr) (err error) {
r1, _, e1 := syscall.Syscall(procEnumWindows.Addr(), 2, uintptr(enumFunc), uintptr(lparam), 0) r1, _, e1 := syscall.Syscall(procEnumWindows.Addr(), 2, enumFunc, lparam, 0)
if r1 == 0 { if r1 == 0 {
if e1 != 0 { if e1 != 0 {
err = error(e1) err = error(e1)
@ -122,10 +124,10 @@ func EnumWindows(enumFunc uintptr, lparam uintptr) (err error) {
} }
// GetWindowText returns the title and text of a window from a window handle // GetWindowText returns the title and text of a window from a window handle
func GetWindowText(hwnd syscall.Handle, str *uint16, maxCount int32) (len int32, err error) { func GetWindowText(hwnd syscall.Handle, str *uint16, maxCount int32) (length int32, err error) {
r0, _, e1 := syscall.Syscall(procGetWindowTextW.Addr(), 3, uintptr(hwnd), uintptr(unsafe.Pointer(str)), uintptr(maxCount)) r0, _, e1 := syscall.Syscall(procGetWindowTextW.Addr(), 3, uintptr(hwnd), uintptr(unsafe.Pointer(str)), uintptr(maxCount))
len = int32(r0) length = int32(r0)
if len == 0 { if length == 0 {
if e1 != 0 { if e1 != 0 {
err = error(e1) err = error(e1)
} else { } else {
@ -135,7 +137,7 @@ func GetWindowText(hwnd syscall.Handle, str *uint16, maxCount int32) (len int32,
return return
} }
// GetWindowTitle searchs for a window attached to the pid // GetWindowTitle searches for a window attached to the pid
func GetWindowTitle(pid int, windowTitleRegex string) (syscall.Handle, string, error) { func GetWindowTitle(pid int, windowTitleRegex string) (syscall.Handle, string, error) {
var hwnd syscall.Handle var hwnd syscall.Handle
var title string var title string
@ -166,8 +168,8 @@ func GetWindowTitle(pid int, windowTitleRegex string) (syscall.Handle, string, e
return 1 // continue enumeration return 1 // continue enumeration
}) })
// Enumerates all top-level windows on the screen // Enumerates all top-level windows on the screen
EnumWindows(cb, 0) err = EnumWindows(cb, 0)
if hwnd == 0 { if err != nil || hwnd == 0 {
return 0, "", fmt.Errorf("No window with title '%b' found", pid) return 0, "", fmt.Errorf("No window with title '%b' found", pid)
} }
return hwnd, title, nil return hwnd, title, nil

0
main.go Executable file → Normal file
View file

View file

@ -1,110 +1,110 @@
# #
# Module manifest for module 'oh-my-posh3' # Module manifest for module 'oh-my-posh3'
# #
# Generated by: Jan De Dobbeleer # Generated by: Jan De Dobbeleer
# #
# Generated on: 11-Sep-20 # Generated on: 11-Sep-20
# #
@{ @{
# Version number of this module. # Version number of this module.
ModuleVersion = '0.0.0.1' ModuleVersion = '0.0.0.1'
# Script module or binary module file associated with this manifest. # Script module or binary module file associated with this manifest.
RootModule = 'oh-my-posh.psm1' RootModule = 'oh-my-posh.psm1'
# ID used to uniquely identify this module # ID used to uniquely identify this module
GUID = '7d7c4a78-e2fe-4e5f-9510-34ac893e4562' GUID = '7d7c4a78-e2fe-4e5f-9510-34ac893e4562'
# Company or vendor of this module # Company or vendor of this module
CompanyName = 'Unknown' CompanyName = 'Unknown'
# Author of this module # Author of this module
Author = 'Jan De Dobbeleer' Author = 'Jan De Dobbeleer'
# Copyright statement for this module # Copyright statement for this module
Copyright = '(c) 2020 Jan De Dobbeleer. All rights reserved.' Copyright = '(c) 2020 Jan De Dobbeleer. All rights reserved.'
# Description of the functionality provided by this module # Description of the functionality provided by this module
Description = 'A prompt theme engine for any shell' Description = 'A prompt theme engine for any shell'
# Minimum version of the Windows PowerShell engine required by this module # Minimum version of the Windows PowerShell engine required by this module
PowerShellVersion = '6.0' PowerShellVersion = '6.0'
# List of all files packaged with this module # List of all files packaged with this module
FileList = @() FileList = @()
# Cmdlets to export from this module # Cmdlets to export from this module
CmdletsToExport = @() CmdletsToExport = @()
# Variables to export from this module # Variables to export from this module
VariablesToExport = @() VariablesToExport = @()
# Aliases to export from this module # Aliases to export from this module
AliasesToExport = '*' AliasesToExport = '*'
# Functions to export from this module # Functions to export from this module
FunctionsToExport = @('Get-PoshThemes', 'Set-PoshPrompt', 'Write-PoshTheme', 'Set-PoshContext') FunctionsToExport = @('Get-PoshThemes', 'Set-PoshPrompt', 'Write-PoshTheme', 'Set-PoshContext')
# Private data to pass to the module specified in RootModule. This may also contain a PSData hashtable with additional module metadata used by PowerShell. # Private data to pass to the module specified in RootModule. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
PrivateData = @{ PrivateData = @{
PSData = @{ PSData = @{
Prerelease = 'beta' Prerelease = 'beta'
# Tags applied to this module. These help with module discovery in online galleries. # Tags applied to this module. These help with module discovery in online galleries.
Tags = @('git', 'agnoster', 'theme', 'zsh', 'posh-git', 'prompt', 'paradox', 'robbyrussel', 'oh-my-posh') Tags = @('git', 'agnoster', 'theme', 'zsh', 'posh-git', 'prompt', 'paradox', 'robbyrussel', 'oh-my-posh')
# A URL to the license for this module. # A URL to the license for this module.
LicenseUri = 'https://github.com/JanDeDobbeleer/oh-my-posh3/blob/main/COPYING' LicenseUri = 'https://github.com/JanDeDobbeleer/oh-my-posh3/blob/main/COPYING'
# A URL to the main website for this project. # A URL to the main website for this project.
ProjectUri = 'https://github.com/JanDeDobbeleer/oh-my-posh3' ProjectUri = 'https://github.com/JanDeDobbeleer/oh-my-posh3'
} # End of PSData hashtable } # End of PSData hashtable
} # End of PrivateData hashtable } # End of PrivateData hashtable
} }

View file

@ -5,22 +5,22 @@ import (
"regexp" "regexp"
) )
//Property defines one property of a segment for context // Property defines one property of a segment for context
type Property string type Property string
//general Properties used across Segments // general Properties used across Segments
const ( const (
//Style indicates with style to use // Style indicates with style to use
Style Property = "style" Style Property = "style"
//Prefix adds a text prefix to the segment // Prefix adds a text prefix to the segment
Prefix Property = "prefix" Prefix Property = "prefix"
//Postfix adds a text postfix to the segment // Postfix adds a text postfix to the segment
Postfix Property = "postfix" Postfix Property = "postfix"
//ColorBackground color the background or foreground when a specific color is set // ColorBackground color the background or foreground when a specific color is set
ColorBackground Property = "color_background" ColorBackground Property = "color_background"
//IgnoreFolders folders to ignore and not run the segment logic // IgnoreFolders folders to ignore and not run the segment logic
IgnoreFolders Property = "ignore_folders" IgnoreFolders Property = "ignore_folders"
//DisplayVersion show the version number or not // DisplayVersion show the version number or not
DisplayVersion Property = "display_version" DisplayVersion Property = "display_version"
) )

View file

@ -6,8 +6,11 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
const (
expected = "expected"
)
func TestGetString(t *testing.T) { func TestGetString(t *testing.T) {
expected := "expected"
values := map[Property]interface{}{TextProperty: expected} values := map[Property]interface{}{TextProperty: expected}
properties := properties{ properties := properties{
values: values, values: values,
@ -17,7 +20,6 @@ func TestGetString(t *testing.T) {
} }
func TestGetStringNoEntry(t *testing.T) { func TestGetStringNoEntry(t *testing.T) {
expected := "expected"
values := map[Property]interface{}{} values := map[Property]interface{}{}
properties := properties{ properties := properties{
values: values, values: values,
@ -27,7 +29,6 @@ func TestGetStringNoEntry(t *testing.T) {
} }
func TestGetStringNoTextEntry(t *testing.T) { func TestGetStringNoTextEntry(t *testing.T) {
expected := "expected"
values := map[Property]interface{}{TextProperty: true} values := map[Property]interface{}{TextProperty: true}
properties := properties{ properties := properties{
values: values, values: values,
@ -37,7 +38,7 @@ func TestGetStringNoTextEntry(t *testing.T) {
} }
func TestGetColor(t *testing.T) { func TestGetColor(t *testing.T) {
expected := "#123456" expected := expectedColor
values := map[Property]interface{}{UserColor: expected} values := map[Property]interface{}{UserColor: expected}
properties := properties{ properties := properties{
values: values, values: values,
@ -47,7 +48,7 @@ func TestGetColor(t *testing.T) {
} }
func TestDefaultColorWithInvalidColorCode(t *testing.T) { func TestDefaultColorWithInvalidColorCode(t *testing.T) {
expected := "#123456" expected := expectedColor
values := map[Property]interface{}{UserColor: "invalid"} values := map[Property]interface{}{UserColor: "invalid"}
properties := properties{ properties := properties{
values: values, values: values,
@ -57,7 +58,7 @@ func TestDefaultColorWithInvalidColorCode(t *testing.T) {
} }
func TestDefaultColorWithUnavailableProperty(t *testing.T) { func TestDefaultColorWithUnavailableProperty(t *testing.T) {
expected := "#123456" expected := expectedColor
values := map[Property]interface{}{} values := map[Property]interface{}{}
properties := properties{ properties := properties{
values: values, values: values,

30
renderer.go Executable file → Normal file
View file

@ -59,7 +59,7 @@ func getColorFromName(colorName string, isBackground bool) (string, error) {
return "", errors.New("color name does not exist") return "", errors.New("color name does not exist")
} }
//Renderer writes colorized strings // Renderer writes colorized strings
type Renderer struct { type Renderer struct {
Buffer *bytes.Buffer Buffer *bytes.Buffer
formats *formats formats *formats
@ -67,8 +67,10 @@ type Renderer struct {
} }
const ( const (
//Transparent implies a transparent color // Transparent implies a transparent color
Transparent string = "transparent" Transparent = "transparent"
zsh = "zsh"
bash = "bash"
) )
func (r *Renderer) init(shell string) { func (r *Renderer) init(shell string) {
@ -77,7 +79,7 @@ func (r *Renderer) init(shell string) {
rANSI: "[\u001B\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[a-zA-Z\\d]*)*)?\u0007)|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PRZcf-ntqry=><~]))", rANSI: "[\u001B\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[a-zA-Z\\d]*)*)?\u0007)|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PRZcf-ntqry=><~]))",
} }
switch shell { switch shell {
case "zsh": case zsh:
r.formats.single = "%%{\x1b[%sm%%}%s%%{\x1b[0m%%}" r.formats.single = "%%{\x1b[%sm%%}%s%%{\x1b[0m%%}"
r.formats.full = "%%{\x1b[%sm\x1b[%sm%%}%s%%{\x1b[0m%%}" r.formats.full = "%%{\x1b[%sm\x1b[%sm%%}%s%%{\x1b[0m%%}"
r.formats.transparent = "%%{\x1b[%s;49m\x1b[7m%%}%s%%{\x1b[m\x1b[0m%%}" r.formats.transparent = "%%{\x1b[%s;49m\x1b[7m%%}%s%%{\x1b[m\x1b[0m%%}"
@ -87,7 +89,7 @@ func (r *Renderer) init(shell string) {
r.formats.title = "%%{\033]0;%s\007%%}" r.formats.title = "%%{\033]0;%s\007%%}"
r.formats.creset = "%{\x1b[0m%}" r.formats.creset = "%{\x1b[0m%}"
r.formats.clearOEL = "%{\x1b[K%}" r.formats.clearOEL = "%{\x1b[K%}"
case "bash": case bash:
r.formats.single = "\\[\x1b[%sm\\]%s\\[\x1b[0m\\]" r.formats.single = "\\[\x1b[%sm\\]%s\\[\x1b[0m\\]"
r.formats.full = "\\[\x1b[%sm\x1b[%sm\\]%s\\[\x1b[0m\\]" r.formats.full = "\\[\x1b[%sm\x1b[%sm\\]%s\\[\x1b[0m\\]"
r.formats.transparent = "\\[\x1b[%s;49m\x1b[7m\\]%s\\[\x1b[m\x1b[0m\\]" r.formats.transparent = "\\[\x1b[%s;49m\x1b[7m\\]%s\\[\x1b[m\x1b[0m\\]"
@ -122,7 +124,7 @@ func (r *Renderer) getAnsiFromColorString(colorString string, isBackground bool)
return style.Code() return style.Code()
} }
func (r *Renderer) writeColoredText(background string, foreground string, text string) { func (r *Renderer) writeColoredText(background, foreground, text string) {
var coloredText string var coloredText string
if foreground == Transparent && background != "" { if foreground == Transparent && background != "" {
ansiColor := r.getAnsiFromColorString(background, false) ansiColor := r.getAnsiFromColorString(background, false)
@ -138,12 +140,12 @@ func (r *Renderer) writeColoredText(background string, foreground string, text s
r.Buffer.WriteString(coloredText) r.Buffer.WriteString(coloredText)
} }
func (r *Renderer) writeAndRemoveText(background string, foreground string, text string, textToRemove string, parentText string) string { func (r *Renderer) writeAndRemoveText(background, foreground, text, textToRemove, parentText string) string {
r.writeColoredText(background, foreground, text) r.writeColoredText(background, foreground, text)
return strings.Replace(parentText, textToRemove, "", 1) return strings.Replace(parentText, textToRemove, "", 1)
} }
func (r *Renderer) write(background string, foreground string, text string) { func (r *Renderer) write(background, foreground, text string) {
// first we match for any potentially valid color enclosed in <> // first we match for any potentially valid color enclosed in <>
rex := regexp.MustCompile(`<([#A-Za-z0-9]+)>(.*?)<\/>`) rex := regexp.MustCompile(`<([#A-Za-z0-9]+)>(.*?)<\/>`)
match := rex.FindAllStringSubmatch(text, -1) match := rex.FindAllStringSubmatch(text, -1)
@ -166,12 +168,12 @@ func (r *Renderer) lenWithoutANSI(str string) int {
re := regexp.MustCompile(r.formats.rANSI) re := regexp.MustCompile(r.formats.rANSI)
stripped := re.ReplaceAllString(str, "") stripped := re.ReplaceAllString(str, "")
switch r.shell { switch r.shell {
case "zsh": case zsh:
stripped = strings.Replace(stripped, "%{", "", -1) stripped = strings.ReplaceAll(stripped, "%{", "")
stripped = strings.Replace(stripped, "%}", "", -1) stripped = strings.ReplaceAll(stripped, "%}", "")
case "bash": case bash:
stripped = strings.Replace(stripped, "\\[", "", -1) stripped = strings.ReplaceAll(stripped, "\\[", "")
stripped = strings.Replace(stripped, "\\]", "", -1) stripped = strings.ReplaceAll(stripped, "\\]", "")
} }
var i norm.Iter var i norm.Iter
i.InitString(norm.NFD, stripped) i.InitString(norm.NFD, stripped)

11
renderer_test.go Executable file → Normal file
View file

@ -4,8 +4,12 @@ import (
"bytes" "bytes"
"testing" "testing"
"github.com/stretchr/testify/assert"
"github.com/gookit/color" "github.com/gookit/color"
"github.com/stretchr/testify/assert"
)
const (
inputText = "This is white, <#ff5733>this is orange</>, white again"
) )
func TestWriteAndRemoveText(t *testing.T) { func TestWriteAndRemoveText(t *testing.T) {
@ -13,7 +17,6 @@ func TestWriteAndRemoveText(t *testing.T) {
Buffer: new(bytes.Buffer), Buffer: new(bytes.Buffer),
} }
renderer.init("pwsh") renderer.init("pwsh")
inputText := "This is white, <#ff5733>this is orange</>, white again"
text := renderer.writeAndRemoveText("#193549", "#fff", "This is white, ", "This is white, ", inputText) text := renderer.writeAndRemoveText("#193549", "#fff", "This is white, ", "This is white, ", inputText)
assert.Equal(t, "<#ff5733>this is orange</>, white again", text) assert.Equal(t, "<#ff5733>this is orange</>, white again", text)
assert.NotContains(t, renderer.string(), "<#ff5733>") assert.NotContains(t, renderer.string(), "<#ff5733>")
@ -24,7 +27,6 @@ func TestWriteAndRemoveTextColored(t *testing.T) {
Buffer: new(bytes.Buffer), Buffer: new(bytes.Buffer),
} }
renderer.init("pwsh") renderer.init("pwsh")
inputText := "This is white, <#ff5733>this is orange</>, white again"
text := renderer.writeAndRemoveText("#193549", "#ff5733", "this is orange", "<#ff5733>this is orange</>", inputText) text := renderer.writeAndRemoveText("#193549", "#ff5733", "this is orange", "<#ff5733>this is orange</>", inputText)
assert.Equal(t, "This is white, , white again", text) assert.Equal(t, "This is white, , white again", text)
assert.NotContains(t, renderer.string(), "<#ff5733>") assert.NotContains(t, renderer.string(), "<#ff5733>")
@ -35,8 +37,7 @@ func TestWriteColorOverride(t *testing.T) {
Buffer: new(bytes.Buffer), Buffer: new(bytes.Buffer),
} }
renderer.init("pwsh") renderer.init("pwsh")
text := "This is white, <#ff5733>this is orange</>, white again" renderer.write("#193549", "#ff5733", inputText)
renderer.write("#193549", "#ff5733", text)
assert.NotContains(t, renderer.string(), "<#ff5733>") assert.NotContains(t, renderer.string(), "<#ff5733>")
} }

View file

@ -2,7 +2,7 @@ package main
import "errors" import "errors"
//Segment represent a single segment and it's configuration // Segment represent a single segment and it's configuration
type Segment struct { type Segment struct {
Type SegmentType `json:"type"` Type SegmentType `json:"type"`
Style SegmentStyle `json:"style"` Style SegmentStyle `json:"style"`
@ -19,65 +19,65 @@ type Segment struct {
active bool active bool
} }
//SegmentWriter is the interface used to define what and if to write to the prompt // SegmentWriter is the interface used to define what and if to write to the prompt
type SegmentWriter interface { type SegmentWriter interface {
enabled() bool enabled() bool
string() string string() string
init(props *properties, env environmentInfo) init(props *properties, env environmentInfo)
} }
//SegmentStyle the syle of segment, for more information, see the constants // SegmentStyle the syle of segment, for more information, see the constants
type SegmentStyle string type SegmentStyle string
//SegmentType the type of segment, for more information, see the constants // SegmentType the type of segment, for more information, see the constants
type SegmentType string type SegmentType string
const ( const (
//Session represents the user info segment // Session represents the user info segment
Session SegmentType = "session" Session SegmentType = "session"
//Path represents the current path segment // Path represents the current path segment
Path SegmentType = "path" Path SegmentType = "path"
//Git represents the git status and information // Git represents the git status and information
Git SegmentType = "git" Git SegmentType = "git"
//Exit writes the last exit code // Exit writes the last exit code
Exit SegmentType = "exit" Exit SegmentType = "exit"
//Python writes the virtual env name // Python writes the virtual env name
Python SegmentType = "python" Python SegmentType = "python"
//Root writes root symbol // Root writes root symbol
Root SegmentType = "root" Root SegmentType = "root"
//Time writes the current timestamp // Time writes the current timestamp
Time SegmentType = "time" Time SegmentType = "time"
//Text writes a text // Text writes a text
Text SegmentType = "text" Text SegmentType = "text"
//Cmd writes the output of a shell command // Cmd writes the output of a shell command
Cmd SegmentType = "command" Cmd SegmentType = "command"
//Battery writes the battery percentage // Battery writes the battery percentage
Battery SegmentType = "battery" Battery SegmentType = "battery"
//Spotify writes the Spotify status for Mac // Spotify writes the Spotify status for Mac
Spotify SegmentType = "spotify" Spotify SegmentType = "spotify"
//ShellInfo writes which shell we're currently in // ShellInfo writes which shell we're currently in
ShellInfo SegmentType = "shell" ShellInfo SegmentType = "shell"
//Node writes which node version is currently active // Node writes which node version is currently active
Node SegmentType = "node" Node SegmentType = "node"
//Os write os specific icon // Os write os specific icon
Os SegmentType = "os" Os SegmentType = "os"
//EnvVar writes the content of an environment variable // EnvVar writes the content of an environment variable
EnvVar SegmentType = "envvar" EnvVar SegmentType = "envvar"
//Az writes the Azure subscription info we're currently in // Az writes the Azure subscription info we're currently in
Az SegmentType = "az" Az SegmentType = "az"
//Kubectl writes the Kubernetes context we're currently in // Kubectl writes the Kubernetes context we're currently in
Kubectl SegmentType = "kubectl" Kubectl SegmentType = "kubectl"
//Dotnet writes which dotnet version is currently active // Dotnet writes which dotnet version is currently active
Dotnet SegmentType = "dotnet" Dotnet SegmentType = "dotnet"
//Terraform writes the terraform workspace we're currently in // Terraform writes the terraform workspace we're currently in
Terraform SegmentType = "terraform" Terraform SegmentType = "terraform"
//Golang writes which go version is currently active // Golang writes which go version is currently active
Golang SegmentType = "go" Golang SegmentType = "go"
//Powerline writes it Powerline style // Powerline writes it Powerline style
Powerline SegmentStyle = "powerline" Powerline SegmentStyle = "powerline"
//Plain writes it without ornaments // Plain writes it without ornaments
Plain SegmentStyle = "plain" Plain SegmentStyle = "plain"
//Diamond writes the prompt shaped with a leading and trailing symbol // Diamond writes the prompt shaped with a leading and trailing symbol
Diamond SegmentStyle = "diamond" Diamond SegmentStyle = "diamond"
) )
@ -144,5 +144,5 @@ func (segment *Segment) mapSegmentWithWriter(env environmentInfo) error {
segment.props = props segment.props = props
return nil return nil
} }
return errors.New("Unable to map writer") return errors.New("unable to map writer")
} }

View file

@ -13,11 +13,11 @@ type az struct {
} }
const ( const (
//SubscriptionInfoSeparator is put between the name and ID // SubscriptionInfoSeparator is put between the name and ID
SubscriptionInfoSeparator Property = "info_separator" SubscriptionInfoSeparator Property = "info_separator"
//DisplaySubscriptionID hides or show the subscription GUID // DisplaySubscriptionID hides or show the subscription GUID
DisplaySubscriptionID Property = "display_id" DisplaySubscriptionID Property = "display_id"
//DisplaySubscriptionName hides or shows the subscription display name // DisplaySubscriptionName hides or shows the subscription display name
DisplaySubscriptionName Property = "display_name" DisplaySubscriptionName Property = "display_name"
) )

View file

@ -14,21 +14,21 @@ type batt struct {
} }
const ( const (
//BatteryIcon to display in front of the battery // BatteryIcon to display in front of the battery
BatteryIcon Property = "battery_icon" BatteryIcon Property = "battery_icon"
//DisplayError to display when an error occurs or not // DisplayError to display when an error occurs or not
DisplayError Property = "display_error" DisplayError Property = "display_error"
//ChargingIcon to display when charging // ChargingIcon to display when charging
ChargingIcon Property = "charging_icon" ChargingIcon Property = "charging_icon"
//DischargingIcon o display when discharging // DischargingIcon o display when discharging
DischargingIcon Property = "discharging_icon" DischargingIcon Property = "discharging_icon"
//ChargedIcon to display when fully charged // ChargedIcon to display when fully charged
ChargedIcon Property = "charged_icon" ChargedIcon Property = "charged_icon"
//ChargedColor to display when fully charged // ChargedColor to display when fully charged
ChargedColor Property = "charged_color" ChargedColor Property = "charged_color"
//ChargingColor to display when charging // ChargingColor to display when charging
ChargingColor Property = "charging_color" ChargingColor Property = "charging_color"
//DischargingColor to display when discharging // DischargingColor to display when discharging
DischargingColor Property = "discharging_color" DischargingColor Property = "discharging_color"
) )
@ -58,7 +58,7 @@ func (b *batt) enabled() bool {
case battery.Full: case battery.Full:
colorPorperty = ChargedColor colorPorperty = ChargedColor
icon = b.props.getString(ChargedIcon, "") icon = b.props.getString(ChargedIcon, "")
default: case battery.Empty, battery.Unknown:
b.percentageText = percentageText b.percentageText = percentageText
return true return true
} }

View file

@ -8,6 +8,10 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
const (
expectedColor = "#768954"
)
func setupBatteryTests(state battery.State, batteryLevel float64, props *properties) *batt { func setupBatteryTests(state battery.State, batteryLevel float64, props *properties) *batt {
env := &MockedEnvironment{} env := &MockedEnvironment{}
bt := &battery.Battery{ bt := &battery.Battery{
@ -55,7 +59,7 @@ func TestBatteryDischarging(t *testing.T) {
} }
func TestBatteryBackgroundColor(t *testing.T) { func TestBatteryBackgroundColor(t *testing.T) {
expected := "#768954" expected := expectedColor
props := &properties{ props := &properties{
background: "#111111", background: "#111111",
values: map[Property]interface{}{ values: map[Property]interface{}{
@ -70,7 +74,7 @@ func TestBatteryBackgroundColor(t *testing.T) {
} }
func TestBatteryBackgroundColorInvalid(t *testing.T) { func TestBatteryBackgroundColorInvalid(t *testing.T) {
expected := "#768954" expected := expectedColor
props := &properties{ props := &properties{
background: expected, background: expected,
values: map[Property]interface{}{ values: map[Property]interface{}{
@ -85,7 +89,7 @@ func TestBatteryBackgroundColorInvalid(t *testing.T) {
} }
func TestBatteryForegroundColor(t *testing.T) { func TestBatteryForegroundColor(t *testing.T) {
expected := "#768954" expected := expectedColor
props := &properties{ props := &properties{
foreground: "#111111", foreground: "#111111",
values: map[Property]interface{}{ values: map[Property]interface{}{
@ -100,7 +104,7 @@ func TestBatteryForegroundColor(t *testing.T) {
} }
func TestBatteryForegroundColorInvalid(t *testing.T) { func TestBatteryForegroundColorInvalid(t *testing.T) {
expected := "#768954" expected := expectedColor
props := &properties{ props := &properties{
foreground: expected, foreground: expected,
values: map[Property]interface{}{ values: map[Property]interface{}{

View file

@ -9,9 +9,9 @@ type command struct {
} }
const ( const (
//ExecutableShell to execute command in // ExecutableShell to execute command in
ExecutableShell Property = "shell" ExecutableShell Property = "shell"
//Command to execute // Command to execute
Command Property = "command" Command Property = "command"
) )

View file

@ -12,8 +12,8 @@ type dotnet struct {
} }
const ( const (
//UnsupportedDotnetVersionIcon is displayed when the dotnet version in // UnsupportedDotnetVersionIcon is displayed when the dotnet version in
//the current folder isn't supported by the installed dotnet SDK set. // the current folder isn't supported by the installed dotnet SDK set.
UnsupportedDotnetVersionIcon Property = "unsupported_version_icon" UnsupportedDotnetVersionIcon Property = "unsupported_version_icon"
) )

View file

@ -7,7 +7,7 @@ type envvar struct {
} }
const ( const (
//VarName name of the variable // VarName name of the variable
VarName Property = "var_name" VarName Property = "var_name"
) )

View file

@ -8,11 +8,11 @@ type exit struct {
} }
const ( const (
//DisplayExitCode shows or hides the error code // DisplayExitCode shows or hides the error code
DisplayExitCode Property = "display_exit_code" DisplayExitCode Property = "display_exit_code"
//AlwaysEnabled decides whether or not to always display the exitcode info // AlwaysEnabled decides whether or not to always display the exitcode info
AlwaysEnabled Property = "always_enabled" AlwaysEnabled Property = "always_enabled"
//ErrorColor specify a different foreground color for the error text when using always_show = true // ErrorColor specify a different foreground color for the error text when using always_show = true
ErrorColor Property = "error_color" ErrorColor Property = "error_color"
) )

62
segment_git.go Executable file → Normal file
View file

@ -28,7 +28,7 @@ type gitStatus struct {
changed bool changed bool
} }
func (s *gitStatus) string(prefix string, color string) string { func (s *gitStatus) string(prefix, color string) string {
var status string var status string
stringIfValue := func(value int, prefix string) string { stringIfValue := func(value int, prefix string) string {
if value > 0 { if value > 0 {
@ -54,63 +54,63 @@ type git struct {
} }
const ( const (
//BranchIcon the icon to use as branch indicator // BranchIcon the icon to use as branch indicator
BranchIcon Property = "branch_icon" BranchIcon Property = "branch_icon"
//BranchIdenticalIcon the icon to display when the remote and local branch are identical // BranchIdenticalIcon the icon to display when the remote and local branch are identical
BranchIdenticalIcon Property = "branch_identical_icon" BranchIdenticalIcon Property = "branch_identical_icon"
//BranchAheadIcon the icon to display when the local branch is ahead of the remote // BranchAheadIcon the icon to display when the local branch is ahead of the remote
BranchAheadIcon Property = "branch_ahead_icon" BranchAheadIcon Property = "branch_ahead_icon"
//BranchBehindIcon the icon to display when the local branch is behind the remote // BranchBehindIcon the icon to display when the local branch is behind the remote
BranchBehindIcon Property = "branch_behind_icon" BranchBehindIcon Property = "branch_behind_icon"
//BranchGoneIcon the icon to use when ther's no remote // BranchGoneIcon the icon to use when ther's no remote
BranchGoneIcon Property = "branch_gone_icon" BranchGoneIcon Property = "branch_gone_icon"
//LocalWorkingIcon the icon to use as the local working area changes indicator // LocalWorkingIcon the icon to use as the local working area changes indicator
LocalWorkingIcon Property = "local_working_icon" LocalWorkingIcon Property = "local_working_icon"
//LocalStagingIcon the icon to use as the local staging area changes indicator // LocalStagingIcon the icon to use as the local staging area changes indicator
LocalStagingIcon Property = "local_staged_icon" LocalStagingIcon Property = "local_staged_icon"
//DisplayStatus shows the status of the repository // DisplayStatus shows the status of the repository
DisplayStatus Property = "display_status" DisplayStatus Property = "display_status"
//DisplayStatusDetail shows the detailed status of the repository // DisplayStatusDetail shows the detailed status of the repository
DisplayStatusDetail Property = "display_status_detail" DisplayStatusDetail Property = "display_status_detail"
//RebaseIcon shows before the rebase context // RebaseIcon shows before the rebase context
RebaseIcon Property = "rebase_icon" RebaseIcon Property = "rebase_icon"
//CherryPickIcon shows before the cherry-pick context // CherryPickIcon shows before the cherry-pick context
CherryPickIcon Property = "cherry_pick_icon" CherryPickIcon Property = "cherry_pick_icon"
//CommitIcon shows before the detached context // CommitIcon shows before the detached context
CommitIcon Property = "commit_icon" CommitIcon Property = "commit_icon"
//TagIcon shows before the tag context // TagIcon shows before the tag context
TagIcon Property = "tag_icon" TagIcon Property = "tag_icon"
//DisplayStashCount show stash count or not // DisplayStashCount show stash count or not
DisplayStashCount Property = "display_stash_count" DisplayStashCount Property = "display_stash_count"
//StashCountIcon shows before the stash context // StashCountIcon shows before the stash context
StashCountIcon Property = "stash_count_icon" StashCountIcon Property = "stash_count_icon"
//StatusSeparatorIcon shows between staging and working area // StatusSeparatorIcon shows between staging and working area
StatusSeparatorIcon Property = "status_separator_icon" StatusSeparatorIcon Property = "status_separator_icon"
//MergeIcon shows before the merge context // MergeIcon shows before the merge context
MergeIcon Property = "merge_icon" MergeIcon Property = "merge_icon"
//DisplayUpstreamIcon show or hide the upstream icon // DisplayUpstreamIcon show or hide the upstream icon
DisplayUpstreamIcon Property = "display_upstream_icon" DisplayUpstreamIcon Property = "display_upstream_icon"
//GithubIcon shows√ when upstream is github // GithubIcon shows√ when upstream is github
GithubIcon Property = "github_icon" GithubIcon Property = "github_icon"
//BitbucketIcon shows when upstream is bitbucket // BitbucketIcon shows when upstream is bitbucket
BitbucketIcon Property = "bitbucket_icon" BitbucketIcon Property = "bitbucket_icon"
//GitlabIcon shows when upstream is gitlab // GitlabIcon shows when upstream is gitlab
GitlabIcon Property = "gitlab_icon" GitlabIcon Property = "gitlab_icon"
//GitIcon shows when the upstream can't be identified // GitIcon shows when the upstream can't be identified
GitIcon Property = "git_icon" GitIcon Property = "git_icon"
//WorkingColor if set, the color to use on the working area // WorkingColor if set, the color to use on the working area
WorkingColor Property = "working_color" WorkingColor Property = "working_color"
//StagingColor if set, the color to use on the staging area // StagingColor if set, the color to use on the staging area
StagingColor Property = "staging_color" StagingColor Property = "staging_color"
//StatusColorsEnabled enables status colors // StatusColorsEnabled enables status colors
StatusColorsEnabled Property = "status_colors_enabled" StatusColorsEnabled Property = "status_colors_enabled"
//LocalChangesColor if set, the color to use when there are local changes // LocalChangesColor if set, the color to use when there are local changes
LocalChangesColor Property = "local_changes_color" LocalChangesColor Property = "local_changes_color"
//AheadAndBehindColor if set, the color to use when the branch is ahead and behind the remote // AheadAndBehindColor if set, the color to use when the branch is ahead and behind the remote
AheadAndBehindColor Property = "ahead_and_behind_color" AheadAndBehindColor Property = "ahead_and_behind_color"
//BehindColor if set, the color to use when the branch is ahead and behind the remote // BehindColor if set, the color to use when the branch is ahead and behind the remote
BehindColor Property = "behind_color" BehindColor Property = "behind_color"
//AheadColor if set, the color to use when the branch is ahead and behind the remote // AheadColor if set, the color to use when the branch is ahead and behind the remote
AheadColor Property = "ahead_color" AheadColor Property = "ahead_color"
) )
@ -170,7 +170,7 @@ func (g *git) init(props *properties, env environmentInfo) {
g.env = env g.env = env
} }
func (g *git) getStatusDetailString(status *gitStatus, color Property, icon Property, defaultIcon string) string { func (g *git) getStatusDetailString(status *gitStatus, color, icon Property, defaultIcon string) string {
prefix := g.props.getString(icon, defaultIcon) prefix := g.props.getString(icon, defaultIcon)
foregroundColor := g.props.getColor(color, g.props.foreground) foregroundColor := g.props.getColor(color, g.props.foreground)
if !g.props.getBool(DisplayStatusDetail, true) { if !g.props.getBool(DisplayStatusDetail, true) {

43
segment_git_test.go Executable file → Normal file
View file

@ -6,6 +6,10 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
const (
changesColor = "#BD8BDE"
)
func TestEnabledGitNotFound(t *testing.T) { func TestEnabledGitNotFound(t *testing.T) {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("hasCommand", "git").Return(false) env.On("hasCommand", "git").Return(false)
@ -70,12 +74,12 @@ func setupHEADContextEnv(context *detachedContext) *git {
env.On("getFileContent", "/.git/MERGE_HEAD").Return(context.mergeHEAD) env.On("getFileContent", "/.git/MERGE_HEAD").Return(context.mergeHEAD)
env.On("hasFiles", "/.git/CHERRY_PICK_HEAD").Return(context.cherryPick) env.On("hasFiles", "/.git/CHERRY_PICK_HEAD").Return(context.cherryPick)
env.On("hasFiles", "/.git/MERGE_HEAD").Return(context.merge) env.On("hasFiles", "/.git/MERGE_HEAD").Return(context.merge)
env.On("runCommand", "git", []string{"-c", "core.quotepath=false", "-c", "color.status=false", "rev-parse", "--short", "HEAD"}).Return(context.currentCommit, nil) env.mockGitCommand(context.currentCommit, "rev-parse", "--short", "HEAD")
env.On("runCommand", "git", []string{"-c", "core.quotepath=false", "-c", "color.status=false", "describe", "--tags", "--exact-match"}).Return(context.tagName, nil) env.mockGitCommand(context.tagName, "describe", "--tags", "--exact-match")
env.On("runCommand", "git", []string{"-c", "core.quotepath=false", "-c", "color.status=false", "name-rev", "--name-only", "--exclude=tags/*", context.origin}).Return(context.origin, nil) env.mockGitCommand(context.origin, "name-rev", "--name-only", "--exclude=tags/*", context.origin)
env.On("runCommand", "git", []string{"-c", "core.quotepath=false", "-c", "color.status=false", "name-rev", "--name-only", "--exclude=tags/*", context.onto}).Return(context.onto, nil) env.mockGitCommand(context.onto, "name-rev", "--name-only", "--exclude=tags/*", context.onto)
env.On("runCommand", "git", []string{"-c", "core.quotepath=false", "-c", "color.status=false", "name-rev", "--name-only", "--exclude=tags/*", context.cherryPickSHA}).Return(context.cherryPickSHA, nil) env.mockGitCommand(context.cherryPickSHA, "name-rev", "--name-only", "--exclude=tags/*", context.cherryPickSHA)
env.On("runCommand", "git", []string{"-c", "core.quotepath=false", "-c", "color.status=false", "name-rev", "--name-only", "--exclude=tags/*", context.mergeHEAD}).Return(context.mergeHEAD, nil) env.mockGitCommand(context.mergeHEAD, "name-rev", "--name-only", "--exclude=tags/*", context.mergeHEAD)
g := &git{ g := &git{
env: env, env: env,
repo: &gitRepo{ repo: &gitRepo{
@ -85,6 +89,11 @@ func setupHEADContextEnv(context *detachedContext) *git {
return g return g
} }
func (m *MockedEnvironment) mockGitCommand(returnValue string, args ...string) {
args = append([]string{"-c", "core.quotepath=false", "-c", "color.status=false"}, args...)
m.On("runCommand", "git", args).Return(returnValue, nil)
}
func TestGetGitDetachedCommitHash(t *testing.T) { func TestGetGitDetachedCommitHash(t *testing.T) {
want := "\uf417lalasha1" want := "\uf417lalasha1"
context := &detachedContext{ context := &detachedContext{
@ -411,7 +420,7 @@ func TestGetUpstreamSymbolGit(t *testing.T) {
} }
func TestGetStatusColorLocalChangesStaging(t *testing.T) { func TestGetStatusColorLocalChangesStaging(t *testing.T) {
expected := "#BD8BDE" expected := changesColor
repo := &gitRepo{ repo := &gitRepo{
staging: &gitStatus{ staging: &gitStatus{
changed: true, changed: true,
@ -429,7 +438,7 @@ func TestGetStatusColorLocalChangesStaging(t *testing.T) {
} }
func TestGetStatusColorLocalChangesWorking(t *testing.T) { func TestGetStatusColorLocalChangesWorking(t *testing.T) {
expected := "#BD8BDE" expected := changesColor
repo := &gitRepo{ repo := &gitRepo{
staging: &gitStatus{}, staging: &gitStatus{},
working: &gitStatus{ working: &gitStatus{
@ -448,7 +457,7 @@ func TestGetStatusColorLocalChangesWorking(t *testing.T) {
} }
func TestGetStatusColorAheadAndBehind(t *testing.T) { func TestGetStatusColorAheadAndBehind(t *testing.T) {
expected := "#BD8BDE" expected := changesColor
repo := &gitRepo{ repo := &gitRepo{
staging: &gitStatus{}, staging: &gitStatus{},
working: &gitStatus{}, working: &gitStatus{},
@ -467,7 +476,7 @@ func TestGetStatusColorAheadAndBehind(t *testing.T) {
} }
func TestGetStatusColorAhead(t *testing.T) { func TestGetStatusColorAhead(t *testing.T) {
expected := "#BD8BDE" expected := changesColor
repo := &gitRepo{ repo := &gitRepo{
staging: &gitStatus{}, staging: &gitStatus{},
working: &gitStatus{}, working: &gitStatus{},
@ -486,7 +495,7 @@ func TestGetStatusColorAhead(t *testing.T) {
} }
func TestGetStatusColorBehind(t *testing.T) { func TestGetStatusColorBehind(t *testing.T) {
expected := "#BD8BDE" expected := changesColor
repo := &gitRepo{ repo := &gitRepo{
staging: &gitStatus{}, staging: &gitStatus{},
working: &gitStatus{}, working: &gitStatus{},
@ -505,7 +514,7 @@ func TestGetStatusColorBehind(t *testing.T) {
} }
func TestGetStatusColorDefault(t *testing.T) { func TestGetStatusColorDefault(t *testing.T) {
expected := "#BD8BDE" expected := changesColor
repo := &gitRepo{ repo := &gitRepo{
staging: &gitStatus{}, staging: &gitStatus{},
working: &gitStatus{}, working: &gitStatus{},
@ -516,7 +525,7 @@ func TestGetStatusColorDefault(t *testing.T) {
repo: repo, repo: repo,
props: &properties{ props: &properties{
values: map[Property]interface{}{ values: map[Property]interface{}{
BehindColor: "#BD8BDE", BehindColor: changesColor,
}, },
}, },
} }
@ -524,7 +533,7 @@ func TestGetStatusColorDefault(t *testing.T) {
} }
func TestSetStatusColorBackground(t *testing.T) { func TestSetStatusColorBackground(t *testing.T) {
expected := "#BD8BDE" expected := changesColor
repo := &gitRepo{ repo := &gitRepo{
staging: &gitStatus{ staging: &gitStatus{
changed: true, changed: true,
@ -534,7 +543,7 @@ func TestSetStatusColorBackground(t *testing.T) {
repo: repo, repo: repo,
props: &properties{ props: &properties{
values: map[Property]interface{}{ values: map[Property]interface{}{
LocalChangesColor: "#BD8BDE", LocalChangesColor: changesColor,
ColorBackground: false, ColorBackground: false,
}, },
foreground: "#ffffff", foreground: "#ffffff",
@ -546,7 +555,7 @@ func TestSetStatusColorBackground(t *testing.T) {
} }
func TestSetStatusColorForeground(t *testing.T) { func TestSetStatusColorForeground(t *testing.T) {
expected := "#BD8BDE" expected := changesColor
repo := &gitRepo{ repo := &gitRepo{
staging: &gitStatus{ staging: &gitStatus{
changed: true, changed: true,
@ -556,7 +565,7 @@ func TestSetStatusColorForeground(t *testing.T) {
repo: repo, repo: repo,
props: &properties{ props: &properties{
values: map[Property]interface{}{ values: map[Property]interface{}{
LocalChangesColor: "#BD8BDE", LocalChangesColor: changesColor,
ColorBackground: true, ColorBackground: true,
}, },
foreground: "#ffffff", foreground: "#ffffff",

0
segment_golang_test.go Executable file → Normal file
View file

0
segment_kubectl_test.go Executable file → Normal file
View file

14
segment_node_test.go Executable file → Normal file
View file

@ -6,6 +6,10 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
const (
node114 = "1.14"
)
type nodeArgs struct { type nodeArgs struct {
enabled bool enabled bool
nodeVersion string nodeVersion string
@ -49,7 +53,7 @@ func TestNodeWriterDisabledNoJSorTSFiles(t *testing.T) {
} }
func TestNodeEnabledJSFiles(t *testing.T) { func TestNodeEnabledJSFiles(t *testing.T) {
expected := "1.14" expected := node114
args := &nodeArgs{ args := &nodeArgs{
enabled: true, enabled: true,
nodeVersion: expected, nodeVersion: expected,
@ -62,7 +66,7 @@ func TestNodeEnabledJSFiles(t *testing.T) {
} }
func TestNodeEnabledTsFiles(t *testing.T) { func TestNodeEnabledTsFiles(t *testing.T) {
expected := "1.14" expected := node114
args := &nodeArgs{ args := &nodeArgs{
enabled: true, enabled: true,
nodeVersion: expected, nodeVersion: expected,
@ -75,7 +79,7 @@ func TestNodeEnabledTsFiles(t *testing.T) {
} }
func TestNodeEnabledJsAndTsFiles(t *testing.T) { func TestNodeEnabledJsAndTsFiles(t *testing.T) {
expected := "1.14" expected := node114
args := &nodeArgs{ args := &nodeArgs{
enabled: true, enabled: true,
nodeVersion: expected, nodeVersion: expected,
@ -92,7 +96,7 @@ func TestNodeEnabledNoVersion(t *testing.T) {
expected := "" expected := ""
args := &nodeArgs{ args := &nodeArgs{
enabled: true, enabled: true,
nodeVersion: "1.14", nodeVersion: node114,
hasJS: true, hasJS: true,
displayVersion: false, displayVersion: false,
} }
@ -102,7 +106,7 @@ func TestNodeEnabledNoVersion(t *testing.T) {
} }
func TestNodeEnabledNodeVersion(t *testing.T) { func TestNodeEnabledNodeVersion(t *testing.T) {
expected := "1.14" expected := node114
args := &nodeArgs{ args := &nodeArgs{
enabled: true, enabled: true,
nodeVersion: expected, nodeVersion: expected,

View file

@ -10,53 +10,53 @@ type osInfo struct {
} }
const ( const (
//MacOS the string/icon to use for MacOS // MacOS the string/icon to use for MacOS
MacOS Property = "macos" MacOS Property = "macos"
//Linux the string/icon to use for linux // Linux the string/icon to use for linux
Linux Property = "linux" Linux Property = "linux"
//Windows the string/icon to use for windows // Windows the string/icon to use for windows
Windows Property = "windows" Windows Property = "windows"
//WSL the string/icon to use for WSL // WSL the string/icon to use for WSL
WSL Property = "wsl" WSL Property = "wsl"
//WSLSeparator shows between WSL and Linux properties when WSL is detected // WSLSeparator shows between WSL and Linux properties when WSL is detected
WSLSeparator Property = "wsl_separator" WSLSeparator Property = "wsl_separator"
//Alpine the string/icon to use for Alpine // Alpine the string/icon to use for Alpine
Alpine Property = "alpine" Alpine Property = "alpine"
//Aosc the string/icon to use for Aosc // Aosc the string/icon to use for Aosc
Aosc Property = "aosc" Aosc Property = "aosc"
//Arch the string/icon to use for Arch // Arch the string/icon to use for Arch
Arch Property = "arch" Arch Property = "arch"
//Centos the string/icon to use for Centos // Centos the string/icon to use for Centos
Centos Property = "centos" Centos Property = "centos"
//Coreos the string/icon to use for Coreos // Coreos the string/icon to use for Coreos
Coreos Property = "coreos" Coreos Property = "coreos"
//Debian the string/icon to use for Debian // Debian the string/icon to use for Debian
Debian Property = "debian" Debian Property = "debian"
//Devuan the string/icon to use for Devuan // Devuan the string/icon to use for Devuan
Devuan Property = "devuan" Devuan Property = "devuan"
//Raspbian the string/icon to use for Raspbian // Raspbian the string/icon to use for Raspbian
Raspbian Property = "raspbian" Raspbian Property = "raspbian"
//Elementary the string/icon to use for Elementary // Elementary the string/icon to use for Elementary
Elementary Property = "elementary" Elementary Property = "elementary"
//Fedora the string/icon to use for Fedora // Fedora the string/icon to use for Fedora
Fedora Property = "fedora" Fedora Property = "fedora"
//Gentoo the string/icon to use for Gentoo // Gentoo the string/icon to use for Gentoo
Gentoo Property = "gentoo" Gentoo Property = "gentoo"
//Mageia the string/icon to use for Mageia // Mageia the string/icon to use for Mageia
Mageia Property = "mageia" Mageia Property = "mageia"
//Manjaro the string/icon to use for Manjaro // Manjaro the string/icon to use for Manjaro
Manjaro Property = "manjaro" Manjaro Property = "manjaro"
//Mint the string/icon to use for Mint // Mint the string/icon to use for Mint
Mint Property = "mint" Mint Property = "mint"
//Nixos the string/icon to use for Nixos // Nixos the string/icon to use for Nixos
Nixos Property = "nixos" Nixos Property = "nixos"
//Opensuse the string/icon to use for Opensuse // Opensuse the string/icon to use for Opensuse
Opensuse Property = "opensuse" Opensuse Property = "opensuse"
//Sabayon the string/icon to use for Sabayon // Sabayon the string/icon to use for Sabayon
Sabayon Property = "sabayon" Sabayon Property = "sabayon"
//Slackware the string/icon to use for Slackware // Slackware the string/icon to use for Slackware
Slackware Property = "slackware" Slackware Property = "slackware"
//Ubuntu the string/icon to use for Ubuntu // Ubuntu the string/icon to use for Ubuntu
Ubuntu Property = "ubuntu" Ubuntu Property = "ubuntu"
) )
@ -67,7 +67,7 @@ func (n *osInfo) enabled() bool {
func (n *osInfo) string() string { func (n *osInfo) string() string {
goos := n.env.getRuntimeGOOS() goos := n.env.getRuntimeGOOS()
switch goos { switch goos {
case "windows": case windowsPlatform:
return n.props.getString(Windows, "\uE62A") return n.props.getString(Windows, "\uE62A")
case "darwin": case "darwin":
return n.props.getString(MacOS, "\uF179") return n.props.getString(MacOS, "\uF179")

View file

@ -15,7 +15,7 @@ func TestOsInfo(t *testing.T) {
background: "#000", background: "#000",
} }
osInfo := &osInfo{ osInfo := &osInfo{
env: env, env: env,
props: props, props: props,
} }
want := "win" want := "win"
@ -30,12 +30,12 @@ func TestWSL(t *testing.T) {
env.On("getPlatform", nil).Return("debian") env.On("getPlatform", nil).Return("debian")
props := &properties{ props := &properties{
values: map[Property]interface{}{ values: map[Property]interface{}{
WSL: "WSL TEST", WSL: "WSL TEST",
WSLSeparator: " @ ", WSLSeparator: " @ ",
}, },
} }
osInfo := &osInfo{ osInfo := &osInfo{
env: env, env: env,
props: props, props: props,
} }
want := "WSL TEST @ \uF306" want := "WSL TEST @ \uF306"

24
segment_path.go Executable file → Normal file
View file

@ -13,23 +13,23 @@ type path struct {
} }
const ( const (
//FolderSeparatorIcon the path which is split will be separated by this icon // FolderSeparatorIcon the path which is split will be separated by this icon
FolderSeparatorIcon Property = "folder_separator_icon" FolderSeparatorIcon Property = "folder_separator_icon"
//HomeIcon indicates the $HOME location // HomeIcon indicates the $HOME location
HomeIcon Property = "home_icon" HomeIcon Property = "home_icon"
//FolderIcon identifies one folder // FolderIcon identifies one folder
FolderIcon Property = "folder_icon" FolderIcon Property = "folder_icon"
//WindowsRegistryIcon indicates the registry location on Windows // WindowsRegistryIcon indicates the registry location on Windows
WindowsRegistryIcon Property = "windows_registry_icon" WindowsRegistryIcon Property = "windows_registry_icon"
//Agnoster displays a short path with separator icon, this the default style // Agnoster displays a short path with separator icon, this the default style
Agnoster string = "agnoster" Agnoster string = "agnoster"
//AgnosterFull displays all the folder names with the folder_separator_icon // AgnosterFull displays all the folder names with the folder_separator_icon
AgnosterFull string = "agnoster_full" AgnosterFull string = "agnoster_full"
//Short displays a shorter path // Short displays a shorter path
Short string = "short" Short string = "short"
//Full displays the full path // Full displays the full path
Full string = "full" Full string = "full"
//Folder displays the current folder // Folder displays the current folder
Folder string = "folder" Folder string = "folder"
) )
@ -96,7 +96,7 @@ func (pt *path) getAgnosterFullPath() string {
if string(pwd[0]) == pathSeparator { if string(pwd[0]) == pathSeparator {
pwd = pwd[1:] pwd = pwd[1:]
} }
return strings.Replace(pwd, pathSeparator, folderSeparator, -1) return strings.ReplaceAll(pwd, pathSeparator, folderSeparator)
} }
func (pt *path) inHomeDir(pwd string) bool { func (pt *path) inHomeDir(pwd string) bool {
@ -104,7 +104,7 @@ func (pt *path) inHomeDir(pwd string) bool {
} }
func (pt *path) rootLocation(pwd string) string { func (pt *path) rootLocation(pwd string) string {
//See https://community.idera.com/database-tools/powershell/powertips/b/tips/posts/correcting-powershell-paths // See https://community.idera.com/database-tools/powershell/powertips/b/tips/posts/correcting-powershell-paths
if strings.HasPrefix(pwd, "Microsoft.PowerShell.Core\\FileSystem::") { if strings.HasPrefix(pwd, "Microsoft.PowerShell.Core\\FileSystem::") {
pwd = strings.Replace(pwd, "Microsoft.PowerShell.Core\\FileSystem::", "", 1) pwd = strings.Replace(pwd, "Microsoft.PowerShell.Core\\FileSystem::", "", 1)
} }
@ -162,7 +162,7 @@ func base(path string, env environmentInfo) string {
} }
// If empty now, it had only slashes. // If empty now, it had only slashes.
if path == "" { if path == "" {
return string(env.getPathSeperator()) return env.getPathSeperator()
} }
return path return path
} }

52
segment_path_test.go Executable file → Normal file
View file

@ -78,7 +78,7 @@ func (env *MockedEnvironment) runCommand(command string, args ...string) (string
return arguments.String(0), arguments.Error(1) return arguments.String(0), arguments.Error(1)
} }
func (env *MockedEnvironment) runShellCommand(shell string, command string) string { func (env *MockedEnvironment) runShellCommand(shell, command string) string {
args := env.Called(shell, command) args := env.Called(shell, command)
return args.String(0) return args.String(0)
} }
@ -108,13 +108,21 @@ func (env *MockedEnvironment) getShellName() string {
return args.String(0) return args.String(0)
} }
func (env *MockedEnvironment) getWindowTitle(imageName string, windowTitleRegex string) (string, error) { func (env *MockedEnvironment) getWindowTitle(imageName, windowTitleRegex string) (string, error) {
args := env.Called(imageName) args := env.Called(imageName)
return args.String(0), args.Error(1) return args.String(0), args.Error(1)
} }
const (
homeGates = "/home/gates"
homeBill = "/home/bill"
homeJan = "/usr/home/jan"
homeBillWindows = "C:\\Users\\Bill"
levelDir = "/level"
)
func TestIsInHomeDirTrue(t *testing.T) { func TestIsInHomeDirTrue(t *testing.T) {
home := "/home/bill" home := homeBill
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("homeDir", nil).Return(home) env.On("homeDir", nil).Return(home)
path := &path{ path := &path{
@ -126,10 +134,10 @@ func TestIsInHomeDirTrue(t *testing.T) {
func TestIsInHomeDirLevelTrue(t *testing.T) { func TestIsInHomeDirLevelTrue(t *testing.T) {
level := rand.Intn(100) level := rand.Intn(100)
home := "/home/bill" home := homeBill
pwd := home pwd := home
for i := 0; i < level; i++ { for i := 0; i < level; i++ {
pwd += "/level" pwd += levelDir
} }
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("homeDir", nil).Return(home) env.On("homeDir", nil).Return(home)
@ -250,7 +258,7 @@ func TestRootLocationEmptyDir(t *testing.T) {
} }
func TestIsInHomeDirFalse(t *testing.T) { func TestIsInHomeDirFalse(t *testing.T) {
home := "/home/bill" home := homeBill
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("homeDir", nil).Return(home) env.On("homeDir", nil).Return(home)
path := &path{ path := &path{
@ -261,7 +269,7 @@ func TestIsInHomeDirFalse(t *testing.T) {
} }
func TestPathDepthInHome(t *testing.T) { func TestPathDepthInHome(t *testing.T) {
home := "/home/bill" home := homeBill
pwd := home pwd := home
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("homeDir", nil).Return(home) env.On("homeDir", nil).Return(home)
@ -288,10 +296,10 @@ func TestPathDepthInHomeTrailing(t *testing.T) {
func TestPathDepthInHomeMultipleLevelsDeep(t *testing.T) { func TestPathDepthInHomeMultipleLevelsDeep(t *testing.T) {
level := rand.Intn(100) level := rand.Intn(100)
home := "/home/bill" home := homeBill
pwd := home pwd := home
for i := 0; i < level; i++ { for i := 0; i < level; i++ {
pwd += "/level" pwd += levelDir
} }
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("homeDir", nil).Return(home) env.On("homeDir", nil).Return(home)
@ -305,10 +313,10 @@ func TestPathDepthInHomeMultipleLevelsDeep(t *testing.T) {
func TestPathDepthOutsideHomeMultipleLevelsDeep(t *testing.T) { func TestPathDepthOutsideHomeMultipleLevelsDeep(t *testing.T) {
level := rand.Intn(100) level := rand.Intn(100)
home := "/home/gates" home := homeGates
pwd := "/usr" pwd := "/usr"
for i := 0; i < level; i++ { for i := 0; i < level; i++ {
pwd += "/level" pwd += levelDir
} }
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("homeDir", nil).Return(home) env.On("homeDir", nil).Return(home)
@ -321,7 +329,7 @@ func TestPathDepthOutsideHomeMultipleLevelsDeep(t *testing.T) {
} }
func TestPathDepthOutsideHomeZeroLevelsDeep(t *testing.T) { func TestPathDepthOutsideHomeZeroLevelsDeep(t *testing.T) {
home := "/home/gates" home := homeGates
pwd := "/usr/" pwd := "/usr/"
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("homeDir", nil).Return(home) env.On("homeDir", nil).Return(home)
@ -334,7 +342,7 @@ func TestPathDepthOutsideHomeZeroLevelsDeep(t *testing.T) {
} }
func TestPathDepthOutsideHomeOneLevelDeep(t *testing.T) { func TestPathDepthOutsideHomeOneLevelDeep(t *testing.T) {
home := "/home/gates" home := homeGates
pwd := "/usr/location" pwd := "/usr/location"
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("homeDir", nil).Return(home) env.On("homeDir", nil).Return(home)
@ -363,7 +371,7 @@ func TestGetAgnosterFullPath(t *testing.T) {
assert.Equal(t, "usr > location > whatever", got) assert.Equal(t, "usr > location > whatever", got)
} }
func testWritePathInfo(home string, pwd string, pathSeparator string) string { func testWritePathInfo(home, pwd, pathSeparator string) string {
props := &properties{ props := &properties{
values: map[Property]interface{}{ values: map[Property]interface{}{
FolderSeparatorIcon: " > ", FolderSeparatorIcon: " > ",
@ -383,14 +391,14 @@ func testWritePathInfo(home string, pwd string, pathSeparator string) string {
} }
func TestWritePathInfoWindowsOutsideHome(t *testing.T) { func TestWritePathInfoWindowsOutsideHome(t *testing.T) {
home := "C:\\Users\\Bill" home := homeBillWindows
want := "C: > f > f > location" want := "C: > f > f > location"
got := testWritePathInfo(home, "C:\\Program Files\\Go\\location", "\\") got := testWritePathInfo(home, "C:\\Program Files\\Go\\location", "\\")
assert.Equal(t, want, got) assert.Equal(t, want, got)
} }
func TestWritePathInfoWindowsInsideHome(t *testing.T) { func TestWritePathInfoWindowsInsideHome(t *testing.T) {
home := "C:\\Users\\Bill" home := homeBillWindows
location := home + "\\Documents\\Bill\\location" location := home + "\\Documents\\Bill\\location"
want := "~ > f > f > location" want := "~ > f > f > location"
got := testWritePathInfo(home, location, "\\") got := testWritePathInfo(home, location, "\\")
@ -398,28 +406,28 @@ func TestWritePathInfoWindowsInsideHome(t *testing.T) {
} }
func TestWritePathInfoWindowsOutsideHomeZeroLevels(t *testing.T) { func TestWritePathInfoWindowsOutsideHomeZeroLevels(t *testing.T) {
home := "C:\\Users\\Bill" home := homeBillWindows
want := "C: > location" want := "C: > location"
got := testWritePathInfo(home, "C:\\location", "\\") got := testWritePathInfo(home, "C:\\location", "\\")
assert.Equal(t, want, got) assert.Equal(t, want, got)
} }
func TestWritePathInfoWindowsOutsideHomeOneLevels(t *testing.T) { func TestWritePathInfoWindowsOutsideHomeOneLevels(t *testing.T) {
home := "C:\\Users\\Bill" home := homeBillWindows
want := "C: > f > location" want := "C: > f > location"
got := testWritePathInfo(home, "C:\\Program Files\\location", "\\") got := testWritePathInfo(home, "C:\\Program Files\\location", "\\")
assert.Equal(t, want, got) assert.Equal(t, want, got)
} }
func TestWritePathInfoUnixOutsideHome(t *testing.T) { func TestWritePathInfoUnixOutsideHome(t *testing.T) {
home := "/usr/home/jan" home := homeJan
want := "mnt > f > f > location" want := "mnt > f > f > location"
got := testWritePathInfo(home, "/mnt/go/test/location", "/") got := testWritePathInfo(home, "/mnt/go/test/location", "/")
assert.Equal(t, want, got) assert.Equal(t, want, got)
} }
func TestWritePathInfoUnixInsideHome(t *testing.T) { func TestWritePathInfoUnixInsideHome(t *testing.T) {
home := "/usr/home/jan" home := homeJan
location := home + "/docs/jan/location" location := home + "/docs/jan/location"
want := "~ > f > f > location" want := "~ > f > f > location"
got := testWritePathInfo(home, location, "/") got := testWritePathInfo(home, location, "/")
@ -427,14 +435,14 @@ func TestWritePathInfoUnixInsideHome(t *testing.T) {
} }
func TestWritePathInfoUnixOutsideHomeZeroLevels(t *testing.T) { func TestWritePathInfoUnixOutsideHomeZeroLevels(t *testing.T) {
home := "/usr/home/jan" home := homeJan
want := "mnt > location" want := "mnt > location"
got := testWritePathInfo(home, "/mnt/location", "/") got := testWritePathInfo(home, "/mnt/location", "/")
assert.Equal(t, want, got) assert.Equal(t, want, got)
} }
func TestWritePathInfoUnixOutsideHomeOneLevels(t *testing.T) { func TestWritePathInfoUnixOutsideHomeOneLevels(t *testing.T) {
home := "/usr/home/jan" home := homeJan
want := "mnt > f > location" want := "mnt > f > location"
got := testWritePathInfo(home, "/mnt/folder/location", "/") got := testWritePathInfo(home, "/mnt/folder/location", "/")
assert.Equal(t, want, got) assert.Equal(t, want, got)

View file

@ -14,7 +14,7 @@ type python struct {
} }
const ( const (
//DisplayVirtualEnv shows or hides the virtual env // DisplayVirtualEnv shows or hides the virtual env
DisplayVirtualEnv Property = "display_virtual_env" DisplayVirtualEnv Property = "display_virtual_env"
) )
@ -46,7 +46,7 @@ func (p *python) enabled() bool {
p.pythonVersion = strings.Trim(values["version"], " ") p.pythonVersion = strings.Trim(values["version"], " ")
break break
} }
//last element, Python isn't installed on this machine // last element, Python isn't installed on this machine
if index == len(pythonVersions)-1 { if index == len(pythonVersions)-1 {
return false return false
} }

24
segment_python_test.go Executable file → Normal file
View file

@ -50,11 +50,15 @@ func bootStrapPythonTest(args *pythonArgs) *python {
return python return python
} }
const (
python345 = "Python 3.4.5"
)
func TestPythonWriterDisabledNoPythonFiles(t *testing.T) { func TestPythonWriterDisabledNoPythonFiles(t *testing.T) {
args := newPythonArgs() args := newPythonArgs()
args.hasPyFiles = false args.hasPyFiles = false
args.hasNotebookFiles = false args.hasNotebookFiles = false
args.python3Version = "Python 3.4.5" args.python3Version = python345
python := bootStrapPythonTest(args) python := bootStrapPythonTest(args)
assert.False(t, python.enabled(), "there are no Python files in the current folder") assert.False(t, python.enabled(), "there are no Python files in the current folder")
} }
@ -63,7 +67,7 @@ func TestPythonWriterDisabledHasPythonFiles(t *testing.T) {
args := newPythonArgs() args := newPythonArgs()
args.hasPyFiles = true args.hasPyFiles = true
args.hasNotebookFiles = false args.hasNotebookFiles = false
args.python3Version = "Python 3.4.5" args.python3Version = python345
python := bootStrapPythonTest(args) python := bootStrapPythonTest(args)
assert.True(t, python.enabled(), "there should be a Python file in the current folder") assert.True(t, python.enabled(), "there should be a Python file in the current folder")
} }
@ -72,7 +76,7 @@ func TestPythonWriterDisabledHasJupyterNotebookFiles(t *testing.T) {
args := newPythonArgs() args := newPythonArgs()
args.hasPyFiles = false args.hasPyFiles = false
args.hasNotebookFiles = true args.hasNotebookFiles = true
args.python3Version = "Python 3.4.5" args.python3Version = python345
python := bootStrapPythonTest(args) python := bootStrapPythonTest(args)
assert.True(t, python.enabled(), "there should be a Jupyter Notebook file in the current folder") assert.True(t, python.enabled(), "there should be a Jupyter Notebook file in the current folder")
} }
@ -81,7 +85,7 @@ func TestPythonWriterDisabledHasPyAndJupyterNotebookFiles(t *testing.T) {
args := newPythonArgs() args := newPythonArgs()
args.hasPyFiles = true args.hasPyFiles = true
args.hasNotebookFiles = true args.hasNotebookFiles = true
args.python3Version = "Python 3.4.5" args.python3Version = python345
python := bootStrapPythonTest(args) python := bootStrapPythonTest(args)
assert.True(t, python.enabled(), "there should be a Jupyter Notebook file in the current folder") assert.True(t, python.enabled(), "there should be a Jupyter Notebook file in the current folder")
} }
@ -102,7 +106,7 @@ func TestPythonWriterDisabledNoPythonInstalled(t *testing.T) {
func TestPythonWriterEnabledNoVirtualEnv(t *testing.T) { func TestPythonWriterEnabledNoVirtualEnv(t *testing.T) {
args := newPythonArgs() args := newPythonArgs()
args.python3Version = "Python 3.4.5" args.python3Version = python345
python := bootStrapPythonTest(args) python := bootStrapPythonTest(args)
assert.True(t, python.enabled()) assert.True(t, python.enabled())
assert.Equal(t, "3.4.5", python.string()) assert.Equal(t, "3.4.5", python.string())
@ -110,7 +114,7 @@ func TestPythonWriterEnabledNoVirtualEnv(t *testing.T) {
func TestPythonWriterEnabledVirtualEnvOverrule(t *testing.T) { func TestPythonWriterEnabledVirtualEnvOverrule(t *testing.T) {
args := newPythonArgs() args := newPythonArgs()
args.python3Version = "Python 3.4.5" args.python3Version = python345
args.condaEnvName = "myenv" args.condaEnvName = "myenv"
props := &properties{ props := &properties{
values: map[Property]interface{}{ values: map[Property]interface{}{
@ -125,7 +129,7 @@ func TestPythonWriterEnabledVirtualEnvOverrule(t *testing.T) {
func TestPythonWriterEnabledVirtualEnv(t *testing.T) { func TestPythonWriterEnabledVirtualEnv(t *testing.T) {
args := newPythonArgs() args := newPythonArgs()
args.python3Version = "Python 3.4.5" args.python3Version = python345
args.condaEnvName = "myenv" args.condaEnvName = "myenv"
expected := fmt.Sprintf("%s %s", args.condaEnvName, "3.4.5") expected := fmt.Sprintf("%s %s", args.condaEnvName, "3.4.5")
props := &properties{ props := &properties{
@ -142,7 +146,7 @@ func TestPythonWriterEnabledVirtualEnv(t *testing.T) {
func TestPythonWriterEnabledWithVirtualEnv(t *testing.T) { func TestPythonWriterEnabledWithVirtualEnv(t *testing.T) {
args := newPythonArgs() args := newPythonArgs()
args.virtualEnvName = "venv" args.virtualEnvName = "venv"
args.python3Version = "Python 3.4.5" args.python3Version = python345
expected := fmt.Sprintf("%s %s", args.virtualEnvName, "3.4.5") expected := fmt.Sprintf("%s %s", args.virtualEnvName, "3.4.5")
python := bootStrapPythonTest(args) python := bootStrapPythonTest(args)
assert.True(t, python.enabled()) assert.True(t, python.enabled())
@ -162,7 +166,7 @@ func TestPythonWriterEnabledWithCondaEnvPath(t *testing.T) {
func TestPythonWriterEnabledWithCondaDefaultEnv(t *testing.T) { func TestPythonWriterEnabledWithCondaDefaultEnv(t *testing.T) {
args := newPythonArgs() args := newPythonArgs()
args.condaDefaultName = "conda2" args.condaDefaultName = "conda2"
args.python3Version = "Python 3.4.5" args.python3Version = python345
expected := fmt.Sprintf("%s %s", args.condaDefaultName, "3.4.5") expected := fmt.Sprintf("%s %s", args.condaDefaultName, "3.4.5")
python := bootStrapPythonTest(args) python := bootStrapPythonTest(args)
assert.True(t, python.enabled()) assert.True(t, python.enabled())
@ -183,7 +187,7 @@ func TestPythonWriterEnabledWithTwoValidEnvs(t *testing.T) {
args := newPythonArgs() args := newPythonArgs()
args.condaEnvName = "conda" args.condaEnvName = "conda"
args.condaDefaultName = "conda2" args.condaDefaultName = "conda2"
args.python3Version = "Python 3.4.5" args.python3Version = python345
expected := fmt.Sprintf("%s %s", args.condaEnvName, "3.4.5") expected := fmt.Sprintf("%s %s", args.condaEnvName, "3.4.5")
python := bootStrapPythonTest(args) python := bootStrapPythonTest(args)
assert.True(t, python.enabled()) assert.True(t, python.enabled())

View file

@ -6,7 +6,7 @@ type root struct {
} }
const ( const (
//RootIcon indicates the root user // RootIcon indicates the root user
RootIcon Property = "root_icon" RootIcon Property = "root_icon"
) )

16
segment_session.go Executable file → Normal file
View file

@ -11,17 +11,17 @@ type session struct {
} }
const ( const (
//UserInfoSeparator is put between the user and computer name // UserInfoSeparator is put between the user and computer name
UserInfoSeparator Property = "user_info_separator" UserInfoSeparator Property = "user_info_separator"
//UserColor if set, is used to color the user name // UserColor if set, is used to color the user name
UserColor Property = "user_color" UserColor Property = "user_color"
//HostColor if set, is used to color the computer name // HostColor if set, is used to color the computer name
HostColor Property = "host_color" HostColor Property = "host_color"
//DisplayHost hides or show the computer name // DisplayHost hides or show the computer name
DisplayHost Property = "display_host" DisplayHost Property = "display_host"
//DisplayUser hides or shows the user name // DisplayUser hides or shows the user name
DisplayUser Property = "display_user" DisplayUser Property = "display_user"
//SSHIcon shows when in an SSH session // SSHIcon shows when in an SSH session
SSHIcon Property = "ssh_icon" SSHIcon Property = "ssh_icon"
) )
@ -49,7 +49,9 @@ func (s *session) getFormattedText() string {
if s.activeSSHSession() { if s.activeSSHSession() {
ssh = s.props.getString(SSHIcon, "\uF817 ") ssh = s.props.getString(SSHIcon, "\uF817 ")
} }
return fmt.Sprintf("%s<%s>%s</>%s<%s>%s</>", ssh, s.props.getColor(UserColor, s.props.foreground), username, separator, s.props.getColor(HostColor, s.props.foreground), computername) userColor := s.props.getColor(UserColor, s.props.foreground)
hostColor := s.props.getColor(HostColor, s.props.foreground)
return fmt.Sprintf("%s<%s>%s</>%s<%s>%s</>", ssh, userColor, username, separator, hostColor, computername)
} }
func (s *session) getComputerName() string { func (s *session) getComputerName() string {

0
segment_session_test.go Executable file → Normal file
View file

0
segment_shell_test.go Executable file → Normal file
View file

View file

@ -13,13 +13,13 @@ type spotify struct {
} }
const ( const (
//PlayingIcon indicates a song is playing // PlayingIcon indicates a song is playing
PlayingIcon Property = "playing_icon" PlayingIcon Property = "playing_icon"
//PausedIcon indicates a song is paused // PausedIcon indicates a song is paused
PausedIcon Property = "paused_icon" PausedIcon Property = "paused_icon"
//StoppedIcon indicates a song is stopped // StoppedIcon indicates a song is stopped
StoppedIcon Property = "stopped_icon" StoppedIcon Property = "stopped_icon"
//TrackSeparator is put between the artist and the track // TrackSeparator is put between the artist and the track
TrackSeparator Property = "track_separator" TrackSeparator Property = "track_separator"
) )

View file

@ -9,18 +9,19 @@ import (
) )
type spotifyArgs struct { type spotifyArgs struct {
spotifyDarwinRunning string running string
spotifyDarwinStatus string status string
spotifyDarwinArtist string artist string
spotifyDarwinTrack string track string
runError error
} }
func bootStrapSpotifyDarwinTest(args *spotifyArgs) *spotify { func bootStrapSpotifyDarwinTest(args *spotifyArgs) *spotify {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("runCommand", "osascript", []string{"-e", "application \"Spotify\" is running"}).Return(args.spotifyDarwinRunning, nil) env.On("runCommand", "osascript", []string{"-e", "application \"Spotify\" is running"}).Return(args.running, args.runError)
env.On("runCommand", "osascript", []string{"-e", "tell application \"Spotify\" to player state as string"}).Return(args.spotifyDarwinStatus, nil) env.On("runCommand", "osascript", []string{"-e", "tell application \"Spotify\" to player state as string"}).Return(args.status, nil)
env.On("runCommand", "osascript", []string{"-e", "tell application \"Spotify\" to artist of current track as string"}).Return(args.spotifyDarwinArtist, nil) env.On("runCommand", "osascript", []string{"-e", "tell application \"Spotify\" to artist of current track as string"}).Return(args.artist, nil)
env.On("runCommand", "osascript", []string{"-e", "tell application \"Spotify\" to name of current track as string"}).Return(args.spotifyDarwinTrack, nil) env.On("runCommand", "osascript", []string{"-e", "tell application \"Spotify\" to name of current track as string"}).Return(args.track, nil)
props := &properties{} props := &properties{}
s := &spotify{ s := &spotify{
env: env, env: env,
@ -31,7 +32,7 @@ func bootStrapSpotifyDarwinTest(args *spotifyArgs) *spotify {
func TestSpotifyDarwinEnabledAndSpotifyNotRunning(t *testing.T) { func TestSpotifyDarwinEnabledAndSpotifyNotRunning(t *testing.T) {
args := &spotifyArgs{ args := &spotifyArgs{
spotifyDarwinRunning: "false", running: "false",
} }
s := bootStrapSpotifyDarwinTest(args) s := bootStrapSpotifyDarwinTest(args)
assert.Equal(t, false, s.enabled()) assert.Equal(t, false, s.enabled())
@ -39,10 +40,10 @@ func TestSpotifyDarwinEnabledAndSpotifyNotRunning(t *testing.T) {
func TestSpotifyDarwinEnabledAndSpotifyPlaying(t *testing.T) { func TestSpotifyDarwinEnabledAndSpotifyPlaying(t *testing.T) {
args := &spotifyArgs{ args := &spotifyArgs{
spotifyDarwinRunning: "true", running: "true",
spotifyDarwinStatus: "playing", status: "playing",
spotifyDarwinArtist: "Candlemass", artist: "Candlemass",
spotifyDarwinTrack: "Spellbreaker", track: "Spellbreaker",
} }
s := bootStrapSpotifyDarwinTest(args) s := bootStrapSpotifyDarwinTest(args)
assert.Equal(t, true, s.enabled()) assert.Equal(t, true, s.enabled())
@ -51,10 +52,10 @@ func TestSpotifyDarwinEnabledAndSpotifyPlaying(t *testing.T) {
func TestSpotifyDarwinEnabledAndSpotifyPaused(t *testing.T) { func TestSpotifyDarwinEnabledAndSpotifyPaused(t *testing.T) {
args := &spotifyArgs{ args := &spotifyArgs{
spotifyDarwinRunning: "true", running: "true",
spotifyDarwinStatus: "paused", status: "paused",
spotifyDarwinArtist: "Candlemass", artist: "Candlemass",
spotifyDarwinTrack: "Spellbreaker", track: "Spellbreaker",
} }
s := bootStrapSpotifyDarwinTest(args) s := bootStrapSpotifyDarwinTest(args)
assert.Equal(t, true, s.enabled()) assert.Equal(t, true, s.enabled())

2
segment_spotify_test.go Executable file → Normal file
View file

@ -1,5 +1,3 @@
// +build windows
package main package main
import ( import (

View file

@ -10,13 +10,13 @@ import (
) )
type spotifyArgs struct { type spotifyArgs struct {
spotifyWindowsTitle string title string
spotifyNotRunningError error runError error
} }
func bootStrapSpotifyWindowsTest(args *spotifyArgs) *spotify { func bootStrapSpotifyWindowsTest(args *spotifyArgs) *spotify {
env := new(MockedEnvironment) env := new(MockedEnvironment)
env.On("getWindowTitle", "spotify.exe").Return(args.spotifyWindowsTitle, args.spotifyNotRunningError) env.On("getWindowTitle", "spotify.exe").Return(args.title, args.runError)
props := &properties{} props := &properties{}
s := &spotify{ s := &spotify{
env: env, env: env,
@ -27,7 +27,7 @@ func bootStrapSpotifyWindowsTest(args *spotifyArgs) *spotify {
func TestSpotifyWindowsEnabledAndSpotifyNotRunning(t *testing.T) { func TestSpotifyWindowsEnabledAndSpotifyNotRunning(t *testing.T) {
args := &spotifyArgs{ args := &spotifyArgs{
spotifyNotRunningError: errors.New(""), runError: errors.New(""),
} }
s := bootStrapSpotifyWindowsTest(args) s := bootStrapSpotifyWindowsTest(args)
assert.Equal(t, false, s.enabled()) assert.Equal(t, false, s.enabled())
@ -35,7 +35,7 @@ func TestSpotifyWindowsEnabledAndSpotifyNotRunning(t *testing.T) {
func TestSpotifyWindowsEnabledAndSpotifyPlaying(t *testing.T) { func TestSpotifyWindowsEnabledAndSpotifyPlaying(t *testing.T) {
args := &spotifyArgs{ args := &spotifyArgs{
spotifyWindowsTitle: "Candlemass - Spellbreaker", title: "Candlemass - Spellbreaker",
} }
s := bootStrapSpotifyWindowsTest(args) s := bootStrapSpotifyWindowsTest(args)
assert.Equal(t, true, s.enabled()) assert.Equal(t, true, s.enabled())
@ -44,7 +44,7 @@ func TestSpotifyWindowsEnabledAndSpotifyPlaying(t *testing.T) {
func TestSpotifyWindowsEnabledAndSpotifyStopped(t *testing.T) { func TestSpotifyWindowsEnabledAndSpotifyStopped(t *testing.T) {
args := &spotifyArgs{ args := &spotifyArgs{
spotifyWindowsTitle: "Spotify premium", title: "Spotify premium",
} }
s := bootStrapSpotifyWindowsTest(args) s := bootStrapSpotifyWindowsTest(args)
assert.Equal(t, true, s.enabled()) assert.Equal(t, true, s.enabled())

0
segment_terraform_test.go Executable file → Normal file
View file

0
segment_test.go Executable file → Normal file
View file

View file

@ -6,7 +6,7 @@ type text struct {
} }
const ( const (
//TextProperty represents text to write // TextProperty represents text to write
TextProperty Property = "text" TextProperty Property = "text"
) )

View file

@ -10,7 +10,7 @@ type tempus struct {
} }
const ( const (
//TimeFormat uses the reference time Mon Jan 2 15:04:05 MST 2006 to show the pattern with which to format the current time // TimeFormat uses the reference time Mon Jan 2 15:04:05 MST 2006 to show the pattern with which to format the current time
TimeFormat Property = "time_format" TimeFormat Property = "time_format"
) )

18
settings.go Executable file → Normal file
View file

@ -6,31 +6,31 @@ import (
"os" "os"
) )
//Settings holds all the theme for rendering the prompt // Settings holds all the theme for rendering the prompt
type Settings struct { type Settings struct {
FinalSpace bool `json:"final_space"` FinalSpace bool `json:"final_space"`
ConsoleTitle bool `json:"console_title"` ConsoleTitle bool `json:"console_title"`
Blocks []*Block `json:"blocks"` Blocks []*Block `json:"blocks"`
} }
//BlockType type of block // BlockType type of block
type BlockType string type BlockType string
//BlockAlignment aligment of a Block // BlockAlignment aligment of a Block
type BlockAlignment string type BlockAlignment string
const ( const (
//Prompt writes one or more Segments // Prompt writes one or more Segments
Prompt BlockType = "prompt" Prompt BlockType = "prompt"
//LineBreak creates a line break in the prompt // LineBreak creates a line break in the prompt
LineBreak BlockType = "newline" LineBreak BlockType = "newline"
//Left aligns left // Left aligns left
Left BlockAlignment = "left" Left BlockAlignment = "left"
//Right aligns right // Right aligns right
Right BlockAlignment = "right" Right BlockAlignment = "right"
) )
//Block defines a part of the prompt with optional segments // Block defines a part of the prompt with optional segments
type Block struct { type Block struct {
Type BlockType `json:"type"` Type BlockType `json:"type"`
Alignment BlockAlignment `json:"alignment"` Alignment BlockAlignment `json:"alignment"`
@ -39,7 +39,7 @@ type Block struct {
Segments []*Segment `json:"segments"` Segments []*Segment `json:"segments"`
} }
//GetSettings returns the default configuration including possible user overrides // GetSettings returns the default configuration including possible user overrides
func GetSettings(env environmentInfo) *Settings { func GetSettings(env environmentInfo) *Settings {
settings, err := loadUserConfiguration(env) settings, err := loadUserConfiguration(env)
if err != nil { if err != nil {