mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2025-01-13 12:17:26 -08:00
feat(config): migrate deprecated keys
This commit is contained in:
parent
0e056cd50d
commit
0373d2c507
15
.vscode/launch.json
vendored
15
.vscode/launch.json
vendored
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
193
src/engine/migrations.go
Normal 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
|
||||
}
|
339
src/engine/migrations_test.go
Normal file
339
src/engine/migrations_test.go
Normal 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)
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -54,6 +54,8 @@ type Args struct {
|
|||
PrintTransient *bool
|
||||
Plain *bool
|
||||
CachePath *bool
|
||||
Migrate *bool
|
||||
Write *bool
|
||||
}
|
||||
|
||||
type CommandError struct {
|
||||
|
|
18
src/go.mod
18
src/go.mod
|
@ -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
|
||||
|
|
21
src/go.sum
21
src/go.sum
|
@ -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=
|
||||
|
|
23
src/main.go
23
src/main.go
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue