feat(config): migrate deprecated keys

This commit is contained in:
Jan De Dobbeleer 2022-01-31 13:33:36 +01:00 committed by Jan De Dobbeleer
parent 0e056cd50d
commit 0373d2c507
17 changed files with 737 additions and 244 deletions

15
.vscode/launch.json vendored
View file

@ -8,7 +8,7 @@
"mode": "debug",
"program": "${workspaceRoot}/src",
"args": [
"--config=/Users/jan/.jandedobbeleer.omp.json",
"--config=${workspaceRoot}/themes/jandedobbeleer.omp.json",
"--shell=pwsh"
]
},
@ -31,7 +31,7 @@
"mode": "debug",
"program": "${workspaceRoot}/src",
"args": [
"--config=/Users/jan/.jandedobbeleer.omp.json",
"--config=${workspaceRoot}/themes/jandedobbeleer.omp.json",
"--shell=pwsh",
"--print-transient"
]
@ -83,6 +83,17 @@
"--config=${workspaceRoot}/themes/jandedobbeleer.omp.json"
]
},
{
"name": "Migrate config",
"type": "go",
"request": "launch",
"mode": "debug",
"program": "${workspaceRoot}/src",
"args": [
"--config=${workspaceRoot}/themes/jandedobbeleer.omp.json",
"--migrate"
]
},
{
"type": "node",
"request": "launch",

View file

@ -38,6 +38,6 @@ Displays the last exit code or that the last command failed based on the configu
## [Template][templates] Properties
- `.Code`: `number` - the last known exit code
- `.Text`: `string` - the textual meaning linked to exit code (if applicable, otherwise identical to `.Code`)
- `.Meaning`: `string` - the textual meaning linked to exit code (if applicable, otherwise identical to `.Code`)
[templates]: /docs/config-templates

View file

@ -29,12 +29,12 @@ const (
// Block defines a part of the prompt with optional segments
type Block struct {
Type BlockType `config:"type"`
Alignment BlockAlignment `config:"alignment"`
HorizontalOffset int `config:"horizontal_offset"`
VerticalOffset int `config:"vertical_offset"`
Segments []*Segment `config:"segments"`
Newline bool `config:"newline"`
Type BlockType `json:"type,omitempty"`
Alignment BlockAlignment `json:"alignment,omitempty"`
HorizontalOffset int `json:"horizontal_offset,omitempty"`
VerticalOffset int `json:"vertical_offset,omitempty"`
Segments []*Segment `json:"segments,omitempty"`
Newline bool `json:"newline,omitempty"`
env environment.Environment
writer color.Writer

View file

@ -1,8 +1,6 @@
package engine
import (
// "encoding/json"
"bytes"
json2 "encoding/json"
"errors"
@ -10,9 +8,8 @@ import (
"oh-my-posh/color"
"oh-my-posh/console"
"oh-my-posh/environment"
"oh-my-posh/properties"
"oh-my-posh/segments"
"os"
"path/filepath"
"strconv"
"strings"
@ -23,18 +20,29 @@ import (
"github.com/mitchellh/mapstructure"
)
const (
JSON string = "json"
YAML string = "yaml"
TOML string = "toml"
)
// Config holds all the theme for rendering the prompt
type Config struct {
FinalSpace bool `config:"final_space"`
OSC99 bool `config:"osc99"`
ConsoleTitle bool `config:"console_title"`
ConsoleTitleStyle console.Style `config:"console_title_style"`
ConsoleTitleTemplate string `config:"console_title_template"`
TerminalBackground string `config:"terminal_background"`
Blocks []*Block `config:"blocks"`
Tooltips []*Segment `config:"tooltips"`
TransientPrompt *TransientPrompt `config:"transient_prompt"`
Palette color.Palette `config:"palette"`
FinalSpace bool `json:"final_space,omitempty"`
OSC99 bool `json:"osc99,omitempty"`
ConsoleTitle bool `json:"console_title,omitempty"`
ConsoleTitleStyle console.Style `json:"console_title_style,omitempty"`
ConsoleTitleTemplate string `json:"console_title_template,omitempty"`
TerminalBackground string `json:"terminal_background,omitempty"`
Blocks []*Block `json:"blocks,omitempty"`
Tooltips []*Segment `json:"tooltips,omitempty"`
TransientPrompt *TransientPrompt `json:"transient_prompt,omitempty"`
Palette color.Palette `json:"palette,omitempty"`
format string
origin string
eval bool
updated bool
}
// MakeColors creates instance of AnsiColors to use in AnsiWriter according to
@ -45,229 +53,138 @@ func (cfg *Config) MakeColors(env environment.Environment) color.AnsiColors {
}
type TransientPrompt struct {
Template string `config:"template"`
Background string `config:"background"`
Foreground string `config:"foreground"`
Template string `json:"template,omitempty"`
Background string `json:"background,omitempty"`
Foreground string `json:"foreground,omitempty"`
}
func printConfigError(err error, eval bool) {
if eval {
func (cfg *Config) exitWithError(err error) {
if err == nil {
return
}
defer os.Exit(1)
if cfg.eval {
fmt.Println("echo \"Oh My Posh Error:\n\"", err.Error())
return
}
fmt.Println("Oh My Posh Error:\n", err.Error())
}
// GetConfig returns the default configuration including possible user overrides
func GetConfig(env environment.Environment) *Config {
cfg, err := loadConfig(env)
if err != nil {
return getDefaultConfig(err.Error())
}
// LoadConfig returns the default configuration including possible user overrides
func LoadConfig(env environment.Environment) *Config {
cfg := loadConfig(env)
return cfg
}
func loadConfig(env environment.Environment) (*Config, error) {
func loadConfig(env environment.Environment) *Config {
var cfg Config
configFile := *env.Args().Config
eval := *env.Args().Eval
cfg.eval = *env.Args().Eval
if configFile == "" {
return nil, errors.New("NO CONFIG")
cfg.exitWithError(errors.New("NO CONFIG"))
}
if _, err := os.Stat(configFile); os.IsNotExist(err) {
printConfigError(err, eval)
return nil, errors.New("INVALID CONFIG PATH")
cfg.exitWithError(err)
}
cfg.origin = configFile
cfg.format = strings.TrimPrefix(filepath.Ext(configFile), ".")
config.AddDriver(yaml.Driver)
config.AddDriver(json.Driver)
config.AddDriver(toml.Driver)
config.WithOptions(func(opt *config.Options) {
opt.DecoderConfig = &mapstructure.DecoderConfig{
TagName: "config",
TagName: "json",
}
})
err := config.LoadFiles(configFile)
if err != nil {
printConfigError(err, eval)
return nil, errors.New("UNABLE TO OPEN CONFIG")
}
cfg.exitWithError(err)
err = config.BindStruct("", &cfg)
if err != nil {
printConfigError(err, eval)
return nil, errors.New("INVALID CONFIG")
}
cfg.exitWithError(err)
// initialize default values
if cfg.TransientPrompt == nil {
cfg.TransientPrompt = &TransientPrompt{}
}
return &cfg, nil
return &cfg
}
func ExportConfig(configFile, format string) string {
if len(format) == 0 {
format = config.JSON
func (cfg *Config) sync() {
if !cfg.updated {
return
}
var structMap map[string]interface{}
inrec, _ := json2.Marshal(cfg)
_ = json2.Unmarshal(inrec, &structMap)
// remove empty structs
for k, v := range structMap {
if smap, OK := v.(map[string]interface{}); OK && len(smap) == 0 {
delete(structMap, k)
}
}
config.SetData(structMap)
}
func (cfg *Config) Export(format string) string {
cfg.sync()
if len(format) != 0 {
cfg.format = format
}
unicodeEscape := func(s string) string {
var builder strings.Builder
for _, r := range s {
if r < 0x1000 {
builder.WriteRune(r)
continue
}
quoted := strconv.QuoteRune(r)
quoted = strings.Trim(quoted, "'")
builder.WriteString(quoted)
}
return builder.String()
}
config.AddDriver(yaml.Driver)
config.AddDriver(json.Driver)
config.AddDriver(toml.Driver)
err := config.LoadFiles(configFile)
if err != nil {
printConfigError(err, false)
return fmt.Sprintf("INVALID CONFIG:\n\n%s", err.Error())
}
var result bytes.Buffer
schemaKey := "$schema"
if format == config.JSON && !config.Exists(schemaKey) {
if cfg.format == JSON {
data := config.Data()
data[schemaKey] = "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json"
config.SetData(data)
data["$schema"] = "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json"
jsonEncoder := json2.NewEncoder(&result)
jsonEncoder.SetEscapeHTML(false)
jsonEncoder.SetIndent("", " ")
err := jsonEncoder.Encode(data)
cfg.exitWithError(err)
return unicodeEscape(result.String())
}
buf := new(bytes.Buffer)
_, err = config.DumpTo(buf, format)
if err != nil {
printConfigError(err, false)
return "UNABLE TO DUMP CONFIG"
_, err := config.DumpTo(&result, cfg.format)
cfg.exitWithError(err)
var prefix string
switch cfg.format {
case YAML:
prefix = "# yaml-language-server: $schema=https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json\n\n"
case TOML:
prefix = "#:schema https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json\n\n"
}
switch format {
case config.JSON:
var prettyJSON bytes.Buffer
err := json2.Indent(&prettyJSON, buf.Bytes(), "", " ")
if err == nil {
unescapeUnicodeCharactersInJSON := func(rawJSON []byte) string {
str, err := strconv.Unquote(strings.ReplaceAll(strconv.Quote(string(rawJSON)), `\\u`, `\u`))
if err != nil {
return err.Error()
}
return str
}
return unescapeUnicodeCharactersInJSON(prettyJSON.Bytes())
}
case config.Yaml:
prefix := "# yaml-language-server: $schema=https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json\n\n"
content := buf.String()
return prefix + content
case config.Toml:
prefix := "#:schema https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json\n\n"
content := buf.String()
return prefix + content
}
return buf.String()
return prefix + unicodeEscape(result.String())
}
func getDefaultConfig(info string) *Config {
cfg := &Config{
FinalSpace: true,
ConsoleTitle: true,
ConsoleTitleStyle: console.FolderName,
Blocks: []*Block{
{
Type: Prompt,
Alignment: Left,
Segments: []*Segment{
{
Type: SESSION,
Style: Diamond,
Background: "#c386f1",
Foreground: "#ffffff",
LeadingDiamond: "\uE0B6",
TrailingDiamond: "\uE0B0",
},
{
Type: PATH,
Style: Powerline,
PowerlineSymbol: "\uE0B0",
Background: "#ff479c",
Foreground: "#ffffff",
Properties: properties.Map{
properties.Prefix: " \uE5FF ",
properties.Style: "folder",
},
},
{
Type: GIT,
Style: Powerline,
PowerlineSymbol: "\uE0B0",
Background: "#fffb38",
Foreground: "#193549",
Properties: properties.Map{
segments.FetchStashCount: true,
segments.FetchUpstreamIcon: true,
},
},
{
Type: BATTERY,
Style: Powerline,
PowerlineSymbol: "\uE0B0",
Background: "#f36943",
Foreground: "#193549",
Properties: properties.Map{
properties.Postfix: "\uF295 ",
},
},
{
Type: NODE,
Style: Powerline,
PowerlineSymbol: "\uE0B0",
Background: "#6CA35E",
Foreground: "#ffffff",
Properties: properties.Map{
properties.Prefix: " \uE718",
properties.FetchVersion: false,
},
},
{
Type: SHELL,
Style: Powerline,
PowerlineSymbol: "\uE0B0",
Background: "#0077c2",
Foreground: "#ffffff",
Properties: properties.Map{
properties.Prefix: " \uFCB5 ",
},
},
{
Type: ROOT,
Style: Powerline,
PowerlineSymbol: "\uE0B0",
Background: "#ffff66",
Foreground: "#ffffff",
},
{
Type: TEXT,
Style: Powerline,
PowerlineSymbol: "\uE0B0",
Background: "#ffffff",
Foreground: "#111111",
Properties: properties.Map{
properties.SegmentTemplate: info,
},
},
{
Type: EXIT,
Style: Diamond,
Background: "#2e9599",
Foreground: "#ffffff",
LeadingDiamond: "<transparent,#2e9599>\uE0B0</>",
TrailingDiamond: "\uE0B4",
Properties: properties.Map{
properties.AlwaysEnabled: true,
properties.Prefix: " \uE23A",
},
},
},
},
},
func (cfg *Config) Write() {
content := cfg.Export(cfg.format)
f, err := os.OpenFile(cfg.origin, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
cfg.exitWithError(err)
_, err = f.WriteString(content)
cfg.exitWithError(err)
if err := f.Close(); err != nil {
cfg.exitWithError(err)
}
return cfg
}

View file

@ -9,12 +9,22 @@ import (
"github.com/stretchr/testify/assert"
)
func TestSettingsExportJSON(t *testing.T) {
defer testClearDefaultConfig()
content := ExportConfig("../themes/jandedobbeleer.omp.json", "json")
assert.NotContains(t, content, "\\u003ctransparent\\u003e")
assert.Contains(t, content, "<transparent>")
}
// func TestSettingsExportJSON(t *testing.T) {
// defer testClearDefaultConfig()
// configFile := "../../themes/jandedobbeleer.omp.json"
// debug := false
// args := &environment.Args{
// Config: &configFile,
// Debug: &debug,
// Eval: &debug,
// }
// env := &environment.ShellEnvironment{}
// env.Init(args)
// cfg := LoadConfig(env)
// content := cfg.Export()
// assert.NotContains(t, content, "\\u003ctransparent\\u003e")
// assert.Contains(t, content, "<transparent>")
// }
func testClearDefaultConfig() {
config.Default().ClearAll()

View file

@ -93,7 +93,7 @@ func engineRender(configPath string) error {
env.Init(args)
defer env.Close()
cfg := GetConfig(env)
cfg := LoadConfig(env)
defer testClearDefaultConfig()
ansi := &color.Ansi{}

193
src/engine/migrations.go Normal file
View file

@ -0,0 +1,193 @@
package engine
import (
"fmt"
"oh-my-posh/environment"
"oh-my-posh/properties"
"oh-my-posh/segments"
"strings"
)
const (
colorBackground = properties.Property("color_background")
)
func (cfg *Config) Migrate(env environment.Environment) {
for _, block := range cfg.Blocks {
block.migrate(env)
}
cfg.updated = true
}
func (block *Block) migrate(env environment.Environment) {
for _, segment := range block.Segments {
segment.migrate(env)
}
}
func (segment *Segment) migrate(env environment.Environment) {
if err := segment.mapSegmentWithWriter(env); err != nil {
return
}
// General properties that need replacement
segment.migratePropertyKey("display_version", properties.FetchVersion)
switch segment.Type { // nolint:exhaustive
case TEXT:
segment.migratePropertyValue("text", properties.SegmentTemplate)
case GIT:
segment.migratePropertyKey("display_status", segments.FetchStatus)
segment.migratePropertyKey("display_stash_count", segments.FetchStashCount)
segment.migratePropertyKey("display_worktree_count", segments.FetchWorktreeCount)
segment.migratePropertyKey("display_upstream_icon", segments.FetchUpstreamIcon)
segment.migrateTemplate()
segment.migrateIconOverride("local_working_icon", " \uF044 ")
segment.migrateIconOverride("local_staged_icon", " \uF046 ")
segment.migrateIconOverride("stash_count_icon", " \uF692 ")
segment.migrateIconOverride("worktree_count_icon", " \uf1bb ")
segment.migrateIconOverride("status_separator_icon", " |")
if segment.Properties.GetBool(properties.Property("status_colors_enabled"), false) {
segment.migrateColorOverride("local_changes_color", "{{ if or (.Working.Changed) (.Staging.Changed) }}%s{{ end }}")
segment.migrateColorOverride("ahead_and_behind_color", "{{ if and (gt .Ahead 0) (gt .Behind 0) }}%s{{ end }}")
segment.migrateColorOverride("behind_color", "{{ if gt .Ahead 0 }}%s{{ end }}")
segment.migrateColorOverride("ahead_color", "{{ if gt .Behind 0 }}%s{{ end }}")
}
segment.migrateInlineColorOverride("working_color", "{{ .Working.String }}")
segment.migrateInlineColorOverride("staging_color", "{{ .Staging.String }}")
case BATTERY:
segment.migrateTemplate()
segment.migrateColorOverride("charged_color", `{{ if eq "Full" .State.String }}%s{{ end }}`)
segment.migrateColorOverride("charging_color", `{{ if eq "Charging" .State.String }}%s{{ end }}`)
segment.migrateColorOverride("discharging_color", `{{ if eq "Discharging" .State.String }}%s{{ end }}`)
stateList := []string{`"Discharging"`}
if segment.Properties.GetBool(properties.Property("display_charging"), true) {
stateList = append(stateList, `"Charging"`)
}
if segment.Properties.GetBool(properties.Property("display_charged"), true) {
stateList = append(stateList, `"Full"`)
}
if len(stateList) < 3 {
enabledTemplate := "{{ $stateList := list %s }}{{ if has .State.String $stateList }}{{.Icon}}{{.Percentage}}{{ end }}"
template := segment.Properties.GetString(properties.SegmentTemplate, segment.writer.Template())
template = strings.ReplaceAll(template, "{{.Icon}}{{.Percentage}}", fmt.Sprintf(enabledTemplate, strings.Join(stateList, " ")))
segment.Properties[properties.SegmentTemplate] = template
}
case PYTHON:
segment.migrateTemplate()
segment.migratePropertyKey("display_virtual_env", segments.FetchVirtualEnv)
case SESSION:
segment.migrateTemplate()
segment.migrateIconOverride("ssh_icon", "\uf817 ")
template := segment.Properties.GetString(properties.SegmentTemplate, segment.writer.Template())
if !segment.Properties.GetBool(properties.Property("display_host"), true) {
template = strings.ReplaceAll(template, "@{{ .HostName }}", "")
}
if !segment.Properties.GetBool(properties.Property("display_user"), true) {
template = strings.ReplaceAll(template, "@", "")
template = strings.ReplaceAll(template, "{{ .UserName }}", "")
}
segment.Properties[properties.SegmentTemplate] = template
segment.migrateIconOverride("user_info_separator", "@")
segment.migrateInlineColorOverride("user_color", "{{ .UserName }}")
segment.migrateInlineColorOverride("host_color", "{{ .HostName }}")
case NODE:
segment.migrateTemplate()
segment.migratePropertyKey("display_package_manager", segments.FetchPackageManager)
enableVersionMismatch := "enable_version_mismatch"
if segment.Properties.GetBool(properties.Property(enableVersionMismatch), false) {
delete(segment.Properties, properties.Property(enableVersionMismatch))
segment.migrateColorOverride("version_mismatch_color", "{{ if .Mismatch }}%s{{ end }}")
}
case EXIT:
template := segment.writer.Template()
displayExitCode := properties.Property("display_exit_code")
if !segment.Properties.GetBool(displayExitCode, true) {
delete(segment.Properties, displayExitCode)
template = strings.ReplaceAll(template, " {{ .Meaning }}", "")
}
alwaysNumeric := properties.Property("always_numeric")
if segment.Properties.GetBool(alwaysNumeric, false) {
delete(segment.Properties, alwaysNumeric)
template = strings.ReplaceAll(template, ".Meaning", ".Code")
}
segment.Properties[properties.SegmentTemplate] = template
segment.migrateIconOverride("success_icon", "\uf42e")
segment.migrateIconOverride("error_icon", "\uf00d")
segment.migrateColorOverride("error_color", "{{ if gt .Code 0 }}%s{{ end }}")
default:
segment.migrateTemplate()
}
}
func (segment *Segment) hasProperty(property properties.Property) bool {
for key := range segment.Properties {
if key == property {
return true
}
}
return false
}
func (segment *Segment) migratePropertyValue(property properties.Property, value interface{}) {
if !segment.hasProperty(property) {
return
}
segment.Properties[property] = value
}
func (segment *Segment) migratePropertyKey(oldProperty, newProperty properties.Property) {
if !segment.hasProperty(oldProperty) {
return
}
value := segment.Properties[oldProperty]
delete(segment.Properties, oldProperty)
segment.Properties[newProperty] = value
}
func (segment *Segment) migrateTemplate() {
if segment.hasProperty(properties.SegmentTemplate) {
return
}
segment.Properties[properties.SegmentTemplate] = segment.writer.Template()
}
func (segment *Segment) migrateIconOverride(icon properties.Property, overrideValue string) {
if !segment.hasProperty(icon) {
return
}
template := segment.Properties.GetString(properties.SegmentTemplate, segment.writer.Template())
if strings.Contains(template, overrideValue) {
template = strings.ReplaceAll(template, overrideValue, segment.Properties.GetString(icon, ""))
}
segment.Properties[properties.SegmentTemplate] = template
}
func (segment *Segment) migrateColorOverride(property properties.Property, template string) {
if !segment.hasProperty(property) {
return
}
color := segment.Properties.GetColor(property, "")
if len(color) == 0 {
return
}
background := segment.Properties.GetBool(colorBackground, false)
colorTemplate := fmt.Sprintf(template, color)
if background {
segment.BackgroundTemplates = append(segment.BackgroundTemplates, colorTemplate)
return
}
segment.ForegroundTemplates = append(segment.ForegroundTemplates, colorTemplate)
}
func (segment *Segment) migrateInlineColorOverride(property properties.Property, old string) {
if !segment.hasProperty(property) {
return
}
color := segment.Properties.GetColor(property, "")
if len(color) == 0 {
return
}
colorTemplate := fmt.Sprintf("<%s>%s</>", color, old)
template := segment.Properties.GetString(properties.SegmentTemplate, segment.writer.Template())
template = strings.ReplaceAll(template, old, colorTemplate)
segment.Properties[properties.SegmentTemplate] = template
}

View file

@ -0,0 +1,339 @@
package engine
import (
"oh-my-posh/environment"
"oh-my-posh/mock"
"oh-my-posh/properties"
"testing"
"github.com/stretchr/testify/assert"
)
const (
Foo = "foo"
Bar = "bar"
FooBar = "foobar"
)
func TestHasProperty(t *testing.T) {
cases := []struct {
Case string
Expected bool
Property properties.Property
Props properties.Map
}{
{Case: "Match", Expected: true, Property: Foo, Props: properties.Map{Foo: "bar"}},
{Case: "No Match", Expected: false, Property: Foo, Props: properties.Map{Bar: "foo"}},
{Case: "No properties", Expected: false},
}
for _, tc := range cases {
segment := &Segment{
Properties: tc.Props,
}
got := segment.hasProperty(tc.Property)
assert.Equal(t, tc.Expected, got, tc.Case)
}
}
func TestMigratePropertyValue(t *testing.T) {
cases := []struct {
Case string
Expected interface{}
Property properties.Property
Props properties.Map
}{
{Case: "Match", Expected: "foo", Property: Foo, Props: properties.Map{Foo: "bar"}},
{Case: "No Match", Expected: nil, Property: Foo, Props: properties.Map{Bar: "foo"}},
}
for _, tc := range cases {
segment := &Segment{
Properties: tc.Props,
}
segment.migratePropertyValue(tc.Property, tc.Expected)
assert.Equal(t, tc.Expected, segment.Properties[tc.Property], tc.Case)
}
}
func TestMigratePropertyKey(t *testing.T) {
cases := []struct {
Case string
Expected interface{}
OldProperty properties.Property
NewProperty properties.Property
Props properties.Map
}{
{Case: "Match", Expected: "bar", OldProperty: Foo, NewProperty: Bar, Props: properties.Map{Foo: "bar"}},
{Case: "No match", Expected: nil, OldProperty: Foo, NewProperty: Bar, Props: properties.Map{FooBar: "bar"}},
{Case: "No migration", Expected: "bar", OldProperty: Foo, NewProperty: Bar, Props: properties.Map{Bar: "bar"}},
}
for _, tc := range cases {
segment := &Segment{
Properties: tc.Props,
}
segment.migratePropertyKey(tc.OldProperty, tc.NewProperty)
assert.Equal(t, tc.Expected, segment.Properties[tc.NewProperty], tc.Case)
assert.NotContains(t, segment.Properties, tc.OldProperty, tc.Case)
}
}
type MockedWriter struct {
template string
}
func (m *MockedWriter) Enabled() bool {
return true
}
func (m *MockedWriter) Template() string {
return m.template
}
func (m *MockedWriter) Init(props properties.Properties, env environment.Environment) {}
func TestIconOverride(t *testing.T) {
cases := []struct {
Case string
Expected string
Property properties.Property
Props properties.Map
}{
{
Case: "Match",
Expected: "hello bar bar",
Property: Foo,
Props: properties.Map{
Foo: " bar ",
properties.SegmentTemplate: "hello foo bar",
},
},
{
Case: "No match",
Expected: "hello foo bar",
Property: Foo,
Props: properties.Map{
Bar: " bar ",
properties.SegmentTemplate: "hello foo bar",
},
},
}
for _, tc := range cases {
segment := &Segment{
Properties: tc.Props,
writer: &MockedWriter{
template: tc.Props.GetString(properties.SegmentTemplate, ""),
},
}
segment.migrateIconOverride(tc.Property, " foo ")
assert.Equal(t, tc.Expected, segment.Properties[properties.SegmentTemplate], tc.Case)
}
}
func TestColorMigration(t *testing.T) {
cases := []struct {
Case string
Expected string
Property properties.Property
Template string
Background bool
NoOverride bool
Props properties.Map
}{
{
Case: "Foreground override",
Expected: "hello green bar",
Template: "hello %s bar",
Property: Foo,
Props: properties.Map{
Foo: "green",
},
},
{
Case: "Background override",
Expected: "hello green bar",
Template: "hello %s bar",
Property: Foo,
Background: true,
Props: properties.Map{
Foo: "green",
},
},
{
Case: "No override",
Expected: "hello green bar",
Template: "hello %s bar",
Property: Foo,
NoOverride: true,
},
}
for _, tc := range cases {
segment := &Segment{
Properties: tc.Props,
}
if tc.Background {
segment.Properties[colorBackground] = true
}
segment.migrateColorOverride(tc.Property, tc.Template)
templates := segment.ForegroundTemplates
if tc.Background {
templates = segment.BackgroundTemplates
}
if tc.NoOverride {
assert.Empty(t, templates, tc.Case)
return
}
lastElement := templates[len(templates)-1]
assert.Equal(t, tc.Expected, lastElement, tc.Case)
}
}
func TestSegmentTemplateMigration(t *testing.T) {
cases := []struct {
Case string
Expected string
Type SegmentType
Props properties.Map
}{
{
Case: "GIT",
Expected: "{{ .HEAD }} {{ .BranchStatus }}{{ if .Working.Changed }} working {{ .Working.String }}{{ end }}{{ if and (.Staging.Changed) (.Working.Changed) }} and{{ end }}{{ if .Staging.Changed }} staged {{ .Staging.String }}{{ end }}{{ if gt .StashCount 0}} stash {{ .StashCount }}{{ end }}{{ if gt .WorktreeCount 0}} worktree {{ .WorktreeCount }}{{ end }}", // nolint: lll
Type: GIT,
Props: properties.Map{
"local_working_icon": " working ",
"local_staged_icon": " staged ",
"worktree_count_icon": " worktree ",
"stash_count_icon": " stash ",
"status_separator_icon": " and",
},
},
{
Case: "GIT - Staging and Working Color",
Expected: "{{ .HEAD }} {{ .BranchStatus }}{{ if .Working.Changed }} working <#123456>{{ .Working.String }}</>{{ end }}{{ if and (.Staging.Changed) (.Working.Changed) }} and{{ end }}{{ if .Staging.Changed }} staged <#123456>{{ .Staging.String }}</>{{ end }}{{ if gt .StashCount 0}} stash {{ .StashCount }}{{ end }}{{ if gt .WorktreeCount 0}} worktree {{ .WorktreeCount }}{{ end }}", // nolint: lll
Type: GIT,
Props: properties.Map{
"local_working_icon": " working ",
"local_staged_icon": " staged ",
"worktree_count_icon": " worktree ",
"stash_count_icon": " stash ",
"status_separator_icon": " and",
"working_color": "#123456",
"staging_color": "#123456",
},
},
{
Case: "EXIT - No exit Code with Icon overrides",
Expected: "{{ if gt .Code 0 }}FAIL{{ else }}SUCCESS{{ end }}",
Type: EXIT,
Props: properties.Map{
"display_exit_code": false,
"success_icon": "SUCCESS",
"error_icon": "FAIL",
},
},
{
Case: "EXIT - Always numeric",
Expected: "{{ if gt .Code 0 }}FAIL {{ .Code }}{{ else }}SUCCESS{{ end }}",
Type: EXIT,
Props: properties.Map{
"always_numeric": true,
"success_icon": "SUCCESS",
"error_icon": "FAIL",
},
},
{
Case: "BATTERY",
Expected: `{{ if not .Error }}{{ $stateList := list "Discharging" "Full" }}{{ if has .State.String $stateList }}{{.Icon}}{{.Percentage}}{{ end }}{{ end }}{{.Error}}`,
Type: BATTERY,
Props: properties.Map{
"display_charging": false,
},
},
{
Case: "SESSION",
Expected: "{{ if .SSHSession }}SSH {{ end }}{{ .UserName }}@{{ .HostName }}",
Type: SESSION,
Props: properties.Map{
"ssh_icon": "SSH ",
},
},
{
Case: "SESSION no HOST",
Expected: "{{ if .SSHSession }}\uf817 {{ end }}{{ .UserName }}",
Type: SESSION,
Props: properties.Map{
"display_host": false,
},
},
{
Case: "SESSION no USER",
Expected: "{{ if .SSHSession }}\uf817 {{ end }}{{ .HostName }}",
Type: SESSION,
Props: properties.Map{
"display_user": false,
},
},
{
Case: "SESSION no USER nor HOST",
Expected: "{{ if .SSHSession }}\uf817 {{ end }}",
Type: SESSION,
Props: properties.Map{
"display_user": false,
"display_host": false,
},
},
{
Case: "SESSION - Color overrides",
Expected: "{{ if .SSHSession }}\uf817 {{ end }}<#123456>{{ .UserName }}</>@<#789012>{{ .HostName }}</>",
Type: SESSION,
Props: properties.Map{
"user_color": "#123456",
"host_color": "#789012",
},
},
}
for _, tc := range cases {
segment := &Segment{
Type: tc.Type,
Properties: tc.Props,
}
segment.migrate(&mock.MockedEnvironment{})
assert.Equal(t, tc.Expected, segment.Properties[properties.SegmentTemplate], tc.Case)
}
}
func TestInlineColorOverride(t *testing.T) {
cases := []struct {
Case string
Expected string
Property properties.Property
Props properties.Map
}{
{
Case: "Match",
Expected: "hello <#123456>foo</> bar",
Property: Foo,
Props: properties.Map{
Foo: "#123456",
properties.SegmentTemplate: "hello foo bar",
},
},
{
Case: "No match",
Expected: "hello foo bar",
Property: Foo,
Props: properties.Map{
Bar: "#123456",
properties.SegmentTemplate: "hello foo bar",
},
},
}
for _, tc := range cases {
segment := &Segment{
Properties: tc.Props,
writer: &MockedWriter{
template: tc.Props.GetString(properties.SegmentTemplate, ""),
},
}
segment.migrateInlineColorOverride(tc.Property, "foo")
assert.Equal(t, tc.Expected, segment.Properties[properties.SegmentTemplate], tc.Case)
}
}

View file

@ -13,18 +13,18 @@ import (
// Segment represent a single segment and it's configuration
type Segment struct {
Type SegmentType `config:"type"`
Tips []string `config:"tips"`
Style SegmentStyle `config:"style"`
PowerlineSymbol string `config:"powerline_symbol"`
InvertPowerline bool `config:"invert_powerline"`
Foreground string `config:"foreground"`
ForegroundTemplates []string `config:"foreground_templates"`
Background string `config:"background"`
BackgroundTemplates []string `config:"background_templates"`
LeadingDiamond string `config:"leading_diamond"`
TrailingDiamond string `config:"trailing_diamond"`
Properties properties.Map `config:"properties"`
Type SegmentType `json:"type,omitempty"`
Tips []string `json:"tips,omitempty"`
Style SegmentStyle `json:"style,omitempty"`
PowerlineSymbol string `json:"powerline_symbol,omitempty"`
InvertPowerline bool `json:"invert_powerline,omitempty"`
Foreground string `json:"foreground,omitempty"`
ForegroundTemplates []string `json:"foreground_templates,omitempty"`
Background string `json:"background,omitempty"`
BackgroundTemplates []string `json:"background_templates,omitempty"`
LeadingDiamond string `json:"leading_diamond,omitempty"`
TrailingDiamond string `json:"trailing_diamond,omitempty"`
Properties properties.Map `json:"properties,omitempty"`
writer SegmentWriter
stringValue string
active bool
@ -160,6 +160,7 @@ func (segment *Segment) string() string {
if err != nil {
return err.Error()
}
segment.active = len(text) > 0
return text
}

View file

@ -54,6 +54,8 @@ type Args struct {
PrintTransient *bool
Plain *bool
CachePath *bool
Migrate *bool
Write *bool
}
type CommandError struct {

View file

@ -4,9 +4,7 @@ go 1.17
require (
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1
github.com/BurntSushi/toml v0.4.1 // indirect
github.com/Masterminds/sprig/v3 v3.2.2
github.com/StackExchange/wmi v1.2.1 // indirect
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38
github.com/alecthomas/colour v0.1.0 // indirect
github.com/alecthomas/repr v0.0.0-20210801044451-80ca428c5142 // indirect
@ -20,18 +18,17 @@ require (
github.com/gookit/goutil v0.4.0 // indirect
github.com/huandu/xstrings v1.3.2 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/mapstructure v1.4.2
github.com/mitchellh/mapstructure v1.4.3
github.com/sergi/go-diff v1.2.0 // indirect
github.com/shirou/gopsutil/v3 v3.21.10
github.com/stretchr/objx v0.3.0 // indirect
github.com/stretchr/testify v1.7.0
github.com/tklauser/go-sysconf v0.3.9 // indirect
github.com/wayneashleyberry/terminal-dimensions v1.1.0
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871 // indirect
golang.org/x/image v0.0.0-20211028202545-6944b10bf410
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881
golang.org/x/sys v0.0.0-20211210111614-af8b64212486
golang.org/x/text v0.3.7
gopkg.in/ini.v1 v1.64.0
gopkg.in/ini.v1 v1.66.2
howett.net/plist v0.0.0-20201203080718-1454fab16a06 // indirect
)
@ -41,12 +38,15 @@ require (
)
require (
github.com/BurntSushi/toml v0.3.1 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.1.1 // indirect
github.com/StackExchange/wmi v1.2.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kr/pretty v0.2.0 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
@ -54,12 +54,14 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
github.com/spf13/cast v1.4.1 // indirect
github.com/tklauser/go-sysconf v0.3.9 // indirect
github.com/tklauser/numcpus v0.3.0 // indirect
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)
require github.com/shopspring/decimal v1.3.1 // indirect
replace github.com/distatus/battery v0.10.0 => github.com/JanDeDobbeleer/battery v0.10.0-2

View file

@ -1,8 +1,7 @@
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw=
github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/JanDeDobbeleer/battery v0.10.0-2 h1:nmFASq8Rmo0sHz6gLT3pXHh7uNABLEgEozKb2tRPgVY=
github.com/JanDeDobbeleer/battery v0.10.0-2/go.mod h1:STnSvFLX//eEpkaN7qWRxCWxrWOcssTDgnG4yqq9BRE=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
@ -69,8 +68,9 @@ github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJS
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
@ -88,8 +88,8 @@ github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo=
github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs=
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
@ -173,8 +173,8 @@ golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 h1:TyHqChC80pFkXWraUUf6RuB5IqFdQieMLwwCJokV2pc=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211210111614-af8b64212486 h1:5hpz5aRr+W1erYCL5JRhSUBJRph7l9XkNveoExlrKYk=
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -187,16 +187,17 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/ini.v1 v1.64.0 h1:Mj2zXEXcNb5joEiSA0zc3HZpTst/iyjNiR4CN8tDzOg=
gopkg.in/ini.v1 v1.64.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI=
gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View file

@ -26,7 +26,7 @@ func main() {
false,
"Print the current config in json format"),
ConfigFormat: flag.String(
"config-format",
"format",
config.JSON,
"The format to print the config in. Valid options are:\n- json\n- yaml\n- toml\n"),
PrintShell: flag.Bool(
@ -121,6 +121,14 @@ func main() {
"cache-path",
false,
"Print the location of the cache"),
Migrate: flag.Bool(
"migrate",
false,
"Migrate the config to the latest version"),
Write: flag.Bool(
"write",
false,
"Write the config to the file"),
}
flag.Parse()
if *args.Version {
@ -152,11 +160,20 @@ func main() {
fmt.Print(init)
return
}
cfg := engine.LoadConfig(env)
if *args.PrintConfig {
fmt.Print(engine.ExportConfig(*args.Config, *args.ConfigFormat))
fmt.Print(cfg.Export(*args.ConfigFormat))
return
}
if *args.Migrate {
cfg.Migrate(env)
if *args.Write {
cfg.Write()
return
}
fmt.Print(cfg.Export(*args.ConfigFormat))
return
}
cfg := engine.GetConfig(env)
ansi := &color.Ansi{}
ansi.Init(env.Shell())
var writer color.Writer

View file

@ -10,15 +10,15 @@ type Exit struct {
props properties.Properties
env environment.Environment
Text string
Meaning string
}
func (e *Exit) Template() string {
return "{{ .Text }}"
return "{{ if gt .Code 0 }}\uf00d {{ .Meaning }}{{ else }}\uf42e{{ end }}"
}
func (e *Exit) Enabled() bool {
e.Text = e.getMeaningFromExitCode(e.env.ErrorCode())
e.Meaning = e.getMeaningFromExitCode(e.env.ErrorCode())
if e.props.GetBool(properties.AlwaysEnabled, false) {
return true
}

View file

@ -108,7 +108,7 @@ const (
)
func (g *Git) Template() string {
return "{{ .HEAD }} {{ .BranchStatus }}{{ if .Working.Changed }} \uF044 {{ .Working.String }}{{ end }}{{ if .Staging.Changed }} \uF046 {{ .Staging.String }}{{ end }}" // nolint: lll
return "{{ .HEAD }} {{ .BranchStatus }}{{ if .Working.Changed }} \uF044 {{ .Working.String }}{{ end }}{{ if and (.Staging.Changed) (.Working.Changed) }} |{{ end }}{{ if .Staging.Changed }} \uF046 {{ .Staging.String }}{{ end }}{{ if gt .StashCount 0}} \uF692 {{ .StashCount }}{{ end }}{{ if gt .WorktreeCount 0}} \uf1bb {{ .WorktreeCount }}{{ end }}" // nolint: lll
}
func (g *Git) Enabled() bool {

View file

@ -17,7 +17,7 @@ const (
)
func (p *Python) Template() string {
return languageTemplate
return "{{ if .Error }}{{ .Error }}{{ else }}{{ if .Venv }}{{ .Venv }} {{ end }}{{ .Full }}{{ end }}"
}
func (p *Python) Init(props properties.Properties, env environment.Environment) {

View file

@ -22,7 +22,7 @@ func (s *Session) Enabled() bool {
}
func (s *Session) Template() string {
return "{{ .UserName }}@{{ .HostName }}"
return "{{ if .SSHSession }}\uf817 {{ end }}{{ .UserName }}@{{ .HostName }}"
}
func (s *Session) Init(props properties.Properties, env environment.Environment) {