From e8b137d73840c43a5eadc6707688273670f32b30 Mon Sep 17 00:00:00 2001 From: mdrakos Date: Thu, 3 Oct 2024 15:08:20 -0700 Subject: [PATCH 01/13] Add list output to state config --- cmd/state/internal/cmdtree/config.go | 4 +- internal/config/instance.go | 26 +++++++++ internal/locale/locales/en-us.yaml | 4 ++ internal/mediators/config/registry.go | 27 ++++++++- internal/runbits/runtime/runtime.go | 2 +- internal/runners/config/config.go | 81 +++++++++++++++++++++++++-- 6 files changed, 133 insertions(+), 11 deletions(-) diff --git a/cmd/state/internal/cmdtree/config.go b/cmd/state/internal/cmdtree/config.go index e213eca340..1753585602 100644 --- a/cmd/state/internal/cmdtree/config.go +++ b/cmd/state/internal/cmdtree/config.go @@ -10,13 +10,13 @@ import ( func newConfigCommand(prime *primer.Values) *captain.Command { return captain.NewCommand( "config", - locale.Tl("config_title", "Config"), + locale.Tl("config_title", "Listing Configuration Keys and Values"), locale.Tl("config_description", "Manage the State Tool configuration"), prime, []*captain.Flag{}, []*captain.Argument{}, func(ccmd *captain.Command, _ []string) error { - runner, err := config.NewConfig(prime) + runner, err := config.NewList(prime) if err != nil { return err } diff --git a/internal/config/instance.go b/internal/config/instance.go index fd6d68fe48..2658b2ee2b 100644 --- a/internal/config/instance.go +++ b/internal/config/instance.go @@ -190,6 +190,10 @@ func (i *Instance) Get(key string) interface{} { return nil } +func (i *Instance) Default(key string) interface{} { + return mediator.GetDefault(mediator.GetOption(key)) +} + // GetString retrieves a string for a given key func (i *Instance) GetString(key string) string { return cast.ToString(i.Get(key)) @@ -220,6 +224,28 @@ func (i *Instance) AllKeys() []string { return keys } +// AllValues returns all of the current config keys and values +func (i *Instance) AllValues() map[string]interface{} { + rows, err := i.db.Query(`SELECT key, value FROM config`) + if err != nil { + multilog.Error("config:AllValues query failed: %s", errs.JoinMessage(err)) + return nil + } + defer rows.Close() + + values := make(map[string]interface{}) + for rows.Next() { + var key string + var value string + if err := rows.Scan(&key, &value); err != nil { + multilog.Error("config:AllValues scan failed: %s", errs.JoinMessage(err)) + return nil + } + values[key] = value + } + return values +} + // GetStringMapStringSlice retrieves a map of string slices for a given key func (i *Instance) GetStringMapStringSlice(key string) map[string][]string { return cast.ToStringMapStringSlice(i.Get(key)) diff --git a/internal/locale/locales/en-us.yaml b/internal/locale/locales/en-us.yaml index 50558aa40b..60da73f045 100644 --- a/internal/locale/locales/en-us.yaml +++ b/internal/locale/locales/en-us.yaml @@ -1560,3 +1560,7 @@ install_report_updated: other: "Updated: [NOTICE]{{.V0}}[/RESET]" install_report_removed: other: "Removed: [NOTICE]{{.V0}}[/RESET]" +config_get_help: + other: "To GET the value for a specific config key run '[ACTIONABLE]state config get [/RESET]'" +config_set_help: + other: "To SET the value for a specific config key run '[ACTIONABLE]state config set [/RESET]'" diff --git a/internal/mediators/config/registry.go b/internal/mediators/config/registry.go index 526a641c88..8c0bc5a9b3 100644 --- a/internal/mediators/config/registry.go +++ b/internal/mediators/config/registry.go @@ -29,6 +29,7 @@ type Option struct { GetEvent Event SetEvent Event isRegistered bool + isHidden bool } type Registry map[string]Option @@ -49,19 +50,28 @@ func NewEnum(options []string, default_ string) *Enums { func GetOption(key string) Option { rule, ok := registry[key] if !ok { - return Option{key, String, "", EmptyEvent, EmptyEvent, false} + return Option{key, String, "", EmptyEvent, EmptyEvent, false, false} } return rule } // Registers a config option without get/set events. func RegisterOption(key string, t Type, defaultValue interface{}) { - RegisterOptionWithEvents(key, t, defaultValue, EmptyEvent, EmptyEvent) + registerOption(key, t, defaultValue, EmptyEvent, EmptyEvent, false) +} + +// Registers a hidden config option without get/set events. +func RegisterHiddenOption(key string, t Type, defaultValue interface{}) { + registerOption(key, t, defaultValue, EmptyEvent, EmptyEvent, true) } // Registers a config option with get/set events. func RegisterOptionWithEvents(key string, t Type, defaultValue interface{}, get, set Event) { - registry[key] = Option{key, t, defaultValue, get, set, true} + registerOption(key, t, defaultValue, get, set, false) +} + +func registerOption(key string, t Type, defaultValue interface{}, get, set Event, hidden bool) { + registry[key] = Option{key, t, defaultValue, get, set, true, hidden} } func KnownOption(rule Option) bool { @@ -74,3 +84,14 @@ func GetDefault(opt Option) interface{} { } return opt.Default } + +func AllRegistered() []Option { + var opts []Option + for _, opt := range registry { + if opt.isHidden { + continue + } + opts = append(opts, opt) + } + return opts +} diff --git a/internal/runbits/runtime/runtime.go b/internal/runbits/runtime/runtime.go index 8a1256ed99..f4b72ba59b 100644 --- a/internal/runbits/runtime/runtime.go +++ b/internal/runbits/runtime/runtime.go @@ -35,7 +35,7 @@ import ( ) func init() { - configMediator.RegisterOption(constants.AsyncRuntimeConfig, configMediator.Bool, false) + configMediator.RegisterHiddenOption(constants.AsyncRuntimeConfig, configMediator.Bool, false) } type Opts struct { diff --git a/internal/runners/config/config.go b/internal/runners/config/config.go index 9734b6553d..904f5607ad 100644 --- a/internal/runners/config/config.go +++ b/internal/runners/config/config.go @@ -1,12 +1,17 @@ package config import ( + "fmt" + "sort" + "github.com/ActiveState/cli/internal/config" + "github.com/ActiveState/cli/internal/locale" + mediator "github.com/ActiveState/cli/internal/mediators/config" "github.com/ActiveState/cli/internal/output" "github.com/ActiveState/cli/internal/primer" ) -type Config struct { +type List struct { out output.Outputer cfg *config.Instance } @@ -18,13 +23,79 @@ type primeable interface { primer.Analyticer } -func NewConfig(prime primeable) (*Config, error) { - return &Config{ +func NewList(prime primeable) (*List, error) { + return &List{ out: prime.Output(), cfg: prime.Config(), }, nil } -func (c *Config) Run(usageFunc func() error) error { - return usageFunc() +type report struct { + Key string `locale:"key,Key"` + Value string `locale:"value,Value"` + Default string `locale:"default,Default"` +} + +func (c *List) Run(usageFunc func() error) error { + registered := mediator.AllRegistered() + + sort.SliceStable(registered, func(i, j int) bool { + return registered[i].Name < registered[j].Name + }) + + var reports []report + for _, opt := range registered { + configuredValue := c.cfg.Get(opt.Name) + reports = append(reports, report{ + Key: fmt.Sprintf("[CYAN]%s[/RESET]", opt.Name), + Value: formatValue(opt, configuredValue), + Default: formatDefault(mediator.GetDefault(opt)), + }) + } + + c.out.Print(struct { + Reports []report `opts:"table,hideDash,omitKey"` + }{reports}) + + c.out.Print("") + c.out.Print(locale.T("config_get_help")) + c.out.Print(locale.T("config_set_help")) + + return nil +} + +func formatValue(opt mediator.Option, value interface{}) string { + var v string + switch opt.Type { + case mediator.Enum: + return fmt.Sprintf("\"%s\"", value) + default: + v = fmt.Sprintf("%v", value) + } + + if v == "" { + return "\"\"" + } + + if len(v) > 100 { + v = v[:100] + "..." + } + + if isDefault(value, opt.Default) { + return fmt.Sprintf("[GREEN]%s[/RESET]", v) + } + + return fmt.Sprintf("[BOLD][RED]%s*[/RESET]", v) +} + +func isDefault[T comparable](configured, defaultValue T) bool { + return configured == defaultValue +} + +func formatDefault[T any](defaultValue T) string { + v := fmt.Sprintf("%v", defaultValue) + if v == "" { + v = "\"\"" + } + return fmt.Sprintf("[DISABLED]%s[/RESET]", v) } From cedee00ae4900d015d3cffd0ce1ed6e4dacf4c80 Mon Sep 17 00:00:00 2001 From: mdrakos Date: Thu, 3 Oct 2024 15:23:33 -0700 Subject: [PATCH 02/13] Ensure structured output works --- internal/runners/config/config.go | 52 ++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/internal/runners/config/config.go b/internal/runners/config/config.go index 904f5607ad..fad84c861e 100644 --- a/internal/runners/config/config.go +++ b/internal/runners/config/config.go @@ -30,40 +30,68 @@ func NewList(prime primeable) (*List, error) { }, nil } -type report struct { +type configData struct { Key string `locale:"key,Key"` Value string `locale:"value,Value"` Default string `locale:"default,Default"` } +type configOutput struct { + out output.Outputer + cfg *config.Instance + options []mediator.Option + data []configData +} + +func (c *configOutput) MarshalOutput(format output.Format) interface{} { + if format != output.PlainFormatName { + return c.data + } + + c.out.Print(struct { + Data []configData `opts:"table,hideDash,omitKey"` + }{c.data}) + c.out.Print("") + c.out.Print(locale.T("config_get_help")) + c.out.Print(locale.T("config_set_help")) + + return output.Suppress +} + +func (c *configOutput) MarshalStructured(format output.Format) interface{} { + return c.data +} + func (c *List) Run(usageFunc func() error) error { registered := mediator.AllRegistered() - sort.SliceStable(registered, func(i, j int) bool { return registered[i].Name < registered[j].Name }) - var reports []report + var data []configData for _, opt := range registered { configuredValue := c.cfg.Get(opt.Name) - reports = append(reports, report{ - Key: fmt.Sprintf("[CYAN]%s[/RESET]", opt.Name), + data = append(data, configData{ + Key: formatKey(opt.Name), Value: formatValue(opt, configuredValue), Default: formatDefault(mediator.GetDefault(opt)), }) } - c.out.Print(struct { - Reports []report `opts:"table,hideDash,omitKey"` - }{reports}) - - c.out.Print("") - c.out.Print(locale.T("config_get_help")) - c.out.Print(locale.T("config_set_help")) + c.out.Print(&configOutput{ + out: c.out, + cfg: c.cfg, + options: registered, + data: data, + }) return nil } +func formatKey(key string) string { + return fmt.Sprintf("[CYAN]%s[/RESET]", key) +} + func formatValue(opt mediator.Option, value interface{}) string { var v string switch opt.Type { From 0aa822ab2f13b8c04ffe05bb970d4bea3f1de293 Mon Sep 17 00:00:00 2001 From: mdrakos Date: Thu, 3 Oct 2024 16:08:29 -0700 Subject: [PATCH 03/13] Add integration test --- test/integration/config_int_test.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/test/integration/config_int_test.go b/test/integration/config_int_test.go index db1bb3dfe9..df2021309e 100644 --- a/test/integration/config_int_test.go +++ b/test/integration/config_int_test.go @@ -88,6 +88,33 @@ func (suite *ConfigIntegrationTestSuite) TestJSON() { AssertValidJSON(suite.T(), cp) } +func (suite *ConfigIntegrationTestSuite) TestList() { + suite.OnlyRunForTags(tagsuite.Config) + ts := e2e.New(suite.T(), false) + defer ts.Close() + + cp := ts.Spawn("config") + cp.Expect("Key") + cp.Expect("Value") + cp.Expect("Default") + cp.Expect("optin.buildscripts") + cp.Expect("false") + cp.ExpectExitCode(0) + + cp = ts.Spawn("config", "set", "optin.buildscripts", "true") + cp.Expect("Successfully") + cp.ExpectExitCode(0) + + cp = ts.Spawn("config") + cp.Expect("Key") + cp.Expect("Value") + cp.Expect("Default") + cp.Expect("optin.buildscripts") + cp.Expect("true*") + cp.ExpectExitCode(0) + + suite.Require().NotContains(cp.Snapshot(), constants.AsyncRuntimeConfig) +} func TestConfigIntegrationTestSuite(t *testing.T) { suite.Run(t, new(ConfigIntegrationTestSuite)) } From 378a436fd26edc51afd7c520b80b914ab6c7a78b Mon Sep 17 00:00:00 2001 From: mdrakos Date: Tue, 8 Oct 2024 11:25:54 -0700 Subject: [PATCH 04/13] Reorganize --- internal/runners/config/config.go | 44 ++++++++++++++----------------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/internal/runners/config/config.go b/internal/runners/config/config.go index fad84c861e..ff68585a4e 100644 --- a/internal/runners/config/config.go +++ b/internal/runners/config/config.go @@ -43,25 +43,6 @@ type configOutput struct { data []configData } -func (c *configOutput) MarshalOutput(format output.Format) interface{} { - if format != output.PlainFormatName { - return c.data - } - - c.out.Print(struct { - Data []configData `opts:"table,hideDash,omitKey"` - }{c.data}) - c.out.Print("") - c.out.Print(locale.T("config_get_help")) - c.out.Print(locale.T("config_set_help")) - - return output.Suppress -} - -func (c *configOutput) MarshalStructured(format output.Format) interface{} { - return c.data -} - func (c *List) Run(usageFunc func() error) error { registered := mediator.AllRegistered() sort.SliceStable(registered, func(i, j int) bool { @@ -109,17 +90,13 @@ func formatValue(opt mediator.Option, value interface{}) string { v = v[:100] + "..." } - if isDefault(value, opt.Default) { + if value == opt.Default { return fmt.Sprintf("[GREEN]%s[/RESET]", v) } return fmt.Sprintf("[BOLD][RED]%s*[/RESET]", v) } -func isDefault[T comparable](configured, defaultValue T) bool { - return configured == defaultValue -} - func formatDefault[T any](defaultValue T) string { v := fmt.Sprintf("%v", defaultValue) if v == "" { @@ -127,3 +104,22 @@ func formatDefault[T any](defaultValue T) string { } return fmt.Sprintf("[DISABLED]%s[/RESET]", v) } + +func (c *configOutput) MarshalOutput(format output.Format) interface{} { + if format != output.PlainFormatName { + return c.data + } + + c.out.Print(struct { + Data []configData `opts:"table,hideDash,omitKey"` + }{c.data}) + c.out.Print("") + c.out.Print(locale.T("config_get_help")) + c.out.Print(locale.T("config_set_help")) + + return output.Suppress +} + +func (c *configOutput) MarshalStructured(format output.Format) interface{} { + return c.data +} From 910581496f549ec0f6f9ea19c690456ac7140bed Mon Sep 17 00:00:00 2001 From: mdrakos Date: Tue, 8 Oct 2024 11:26:58 -0700 Subject: [PATCH 05/13] Revert config instance changes --- internal/config/instance.go | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/internal/config/instance.go b/internal/config/instance.go index 2658b2ee2b..fd6d68fe48 100644 --- a/internal/config/instance.go +++ b/internal/config/instance.go @@ -190,10 +190,6 @@ func (i *Instance) Get(key string) interface{} { return nil } -func (i *Instance) Default(key string) interface{} { - return mediator.GetDefault(mediator.GetOption(key)) -} - // GetString retrieves a string for a given key func (i *Instance) GetString(key string) string { return cast.ToString(i.Get(key)) @@ -224,28 +220,6 @@ func (i *Instance) AllKeys() []string { return keys } -// AllValues returns all of the current config keys and values -func (i *Instance) AllValues() map[string]interface{} { - rows, err := i.db.Query(`SELECT key, value FROM config`) - if err != nil { - multilog.Error("config:AllValues query failed: %s", errs.JoinMessage(err)) - return nil - } - defer rows.Close() - - values := make(map[string]interface{}) - for rows.Next() { - var key string - var value string - if err := rows.Scan(&key, &value); err != nil { - multilog.Error("config:AllValues scan failed: %s", errs.JoinMessage(err)) - return nil - } - values[key] = value - } - return values -} - // GetStringMapStringSlice retrieves a map of string slices for a given key func (i *Instance) GetStringMapStringSlice(key string) map[string][]string { return cast.ToStringMapStringSlice(i.Get(key)) From d43bc4921ea8fccf7f1848f4ba2e22004121e145 Mon Sep 17 00:00:00 2001 From: mdrakos Date: Tue, 8 Oct 2024 11:27:23 -0700 Subject: [PATCH 06/13] Add comment --- internal/mediators/config/registry.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/mediators/config/registry.go b/internal/mediators/config/registry.go index 8c0bc5a9b3..2d962f4ebe 100644 --- a/internal/mediators/config/registry.go +++ b/internal/mediators/config/registry.go @@ -85,6 +85,7 @@ func GetDefault(opt Option) interface{} { return opt.Default } +// AllRegistered returns all registered options, excluding hidden ones func AllRegistered() []Option { var opts []Option for _, opt := range registry { From c4dccde24823f87e9ab1e0f6e1aaced7dc6b6e8d Mon Sep 17 00:00:00 2001 From: mdrakos Date: Wed, 9 Oct 2024 11:49:42 -0700 Subject: [PATCH 07/13] Manually construct table --- internal/runners/config/config.go | 83 +++++++++++++++---------------- 1 file changed, 40 insertions(+), 43 deletions(-) diff --git a/internal/runners/config/config.go b/internal/runners/config/config.go index ff68585a4e..6ddf4941a7 100644 --- a/internal/runners/config/config.go +++ b/internal/runners/config/config.go @@ -9,6 +9,7 @@ import ( mediator "github.com/ActiveState/cli/internal/mediators/config" "github.com/ActiveState/cli/internal/output" "github.com/ActiveState/cli/internal/primer" + "github.com/ActiveState/cli/internal/table" ) type List struct { @@ -30,17 +31,11 @@ func NewList(prime primeable) (*List, error) { }, nil } -type configData struct { - Key string `locale:"key,Key"` - Value string `locale:"value,Value"` - Default string `locale:"default,Default"` -} - -type configOutput struct { - out output.Outputer - cfg *config.Instance - options []mediator.Option - data []configData +type structuredConfigData struct { + Key string `json:"key"` + Value interface{} `json:"value"` + Default interface{} `json:"default"` + opt mediator.Option } func (c *List) Run(usageFunc func() error) error { @@ -49,22 +44,43 @@ func (c *List) Run(usageFunc func() error) error { return registered[i].Name < registered[j].Name }) - var data []configData + var data []structuredConfigData for _, opt := range registered { configuredValue := c.cfg.Get(opt.Name) - data = append(data, configData{ - Key: formatKey(opt.Name), - Value: formatValue(opt, configuredValue), - Default: formatDefault(mediator.GetDefault(opt)), + data = append(data, structuredConfigData{ + Key: opt.Name, + Value: configuredValue, + Default: mediator.GetDefault(opt), + opt: opt, }) } - c.out.Print(&configOutput{ - out: c.out, - cfg: c.cfg, - options: registered, - data: data, - }) + if c.out.Type().IsStructured() { + c.out.Print(output.Structured(data)) + } else { + if err := c.renderUserFacing(data); err != nil { + return err + } + } + + return nil +} + +func (c *List) renderUserFacing(configData []structuredConfigData) error { + tbl := table.New(locale.Ts("Key", "Value", "Default")) + tbl.HideDash = true + for _, config := range configData { + tbl.AddRow([]string{ + formatKey(config.Key), + formatValue(config.opt, config.Value), + formatDefault(config.Default), + }) + } + + c.out.Print(tbl.Render()) + c.out.Print("") + c.out.Print(locale.T("config_get_help")) + c.out.Print(locale.T("config_set_help")) return nil } @@ -90,36 +106,17 @@ func formatValue(opt mediator.Option, value interface{}) string { v = v[:100] + "..." } - if value == opt.Default { + if value == mediator.GetDefault(opt) { return fmt.Sprintf("[GREEN]%s[/RESET]", v) } return fmt.Sprintf("[BOLD][RED]%s*[/RESET]", v) } -func formatDefault[T any](defaultValue T) string { +func formatDefault(defaultValue interface{}) string { v := fmt.Sprintf("%v", defaultValue) if v == "" { v = "\"\"" } return fmt.Sprintf("[DISABLED]%s[/RESET]", v) } - -func (c *configOutput) MarshalOutput(format output.Format) interface{} { - if format != output.PlainFormatName { - return c.data - } - - c.out.Print(struct { - Data []configData `opts:"table,hideDash,omitKey"` - }{c.data}) - c.out.Print("") - c.out.Print(locale.T("config_get_help")) - c.out.Print(locale.T("config_set_help")) - - return output.Suppress -} - -func (c *configOutput) MarshalStructured(format output.Format) interface{} { - return c.data -} From 129a0365af5ee733d1dfab97ea63efaa1bf54e96 Mon Sep 17 00:00:00 2001 From: mdrakos Date: Wed, 9 Oct 2024 13:48:22 -0700 Subject: [PATCH 08/13] Address more PR review comments --- cmd/state/internal/cmdtree/config.go | 2 +- internal/mediators/config/registry.go | 9 ++- internal/runners/config/config.go | 94 +++++++++++++++------------ 3 files changed, 60 insertions(+), 45 deletions(-) diff --git a/cmd/state/internal/cmdtree/config.go b/cmd/state/internal/cmdtree/config.go index 1753585602..d09608e4e4 100644 --- a/cmd/state/internal/cmdtree/config.go +++ b/cmd/state/internal/cmdtree/config.go @@ -20,7 +20,7 @@ func newConfigCommand(prime *primer.Values) *captain.Command { if err != nil { return err } - return runner.Run(ccmd.Usage) + return runner.Run() }).SetGroup(UtilsGroup).SetSupportsStructuredOutput() } diff --git a/internal/mediators/config/registry.go b/internal/mediators/config/registry.go index 2d962f4ebe..f6f327f53d 100644 --- a/internal/mediators/config/registry.go +++ b/internal/mediators/config/registry.go @@ -1,5 +1,7 @@ package config +import "sort" + type Type int const ( @@ -85,8 +87,8 @@ func GetDefault(opt Option) interface{} { return opt.Default } -// AllRegistered returns all registered options, excluding hidden ones -func AllRegistered() []Option { +// Registered returns all registered options, excluding hidden ones +func Registered() []Option { var opts []Option for _, opt := range registry { if opt.isHidden { @@ -94,5 +96,8 @@ func AllRegistered() []Option { } opts = append(opts, opt) } + sort.SliceStable(opts, func(i, j int) bool { + return opts[i].Name < opts[j].Name + }) return opts } diff --git a/internal/runners/config/config.go b/internal/runners/config/config.go index 6ddf4941a7..f6eb43c464 100644 --- a/internal/runners/config/config.go +++ b/internal/runners/config/config.go @@ -2,7 +2,7 @@ package config import ( "fmt" - "sort" + "strings" "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/locale" @@ -13,8 +13,7 @@ import ( ) type List struct { - out output.Outputer - cfg *config.Instance + prime primeable } type primeable interface { @@ -26,8 +25,7 @@ type primeable interface { func NewList(prime primeable) (*List, error) { return &List{ - out: prime.Output(), - cfg: prime.Config(), + prime: prime, }, nil } @@ -38,15 +36,15 @@ type structuredConfigData struct { opt mediator.Option } -func (c *List) Run(usageFunc func() error) error { - registered := mediator.AllRegistered() - sort.SliceStable(registered, func(i, j int) bool { - return registered[i].Name < registered[j].Name - }) +func (c *List) Run() error { + registered := mediator.Registered() + + cfg := c.prime.Config() + out := c.prime.Output() var data []structuredConfigData for _, opt := range registered { - configuredValue := c.cfg.Get(opt.Name) + configuredValue := cfg.Get(opt.Name) data = append(data, structuredConfigData{ Key: opt.Name, Value: configuredValue, @@ -55,8 +53,8 @@ func (c *List) Run(usageFunc func() error) error { }) } - if c.out.Type().IsStructured() { - c.out.Print(output.Structured(data)) + if out.Type().IsStructured() { + out.Print(output.Structured(data)) } else { if err := c.renderUserFacing(data); err != nil { return err @@ -67,56 +65,68 @@ func (c *List) Run(usageFunc func() error) error { } func (c *List) renderUserFacing(configData []structuredConfigData) error { + cfg := c.prime.Config() + out := c.prime.Output() + tbl := table.New(locale.Ts("Key", "Value", "Default")) tbl.HideDash = true for _, config := range configData { tbl.AddRow([]string{ - formatKey(config.Key), - formatValue(config.opt, config.Value), - formatDefault(config.Default), + fmt.Sprintf("[CYAN]%s[/RESET]", config.Key), + colorizeValue(cfg, config.opt, config.Value), + fmt.Sprintf("[DISABLED]%s[/RESET]", formatValue(config.opt, config.Default)), }) } - c.out.Print(tbl.Render()) - c.out.Print("") - c.out.Print(locale.T("config_get_help")) - c.out.Print(locale.T("config_set_help")) + out.Print(tbl.Render()) + out.Print("") + out.Print(locale.T("config_get_help")) + out.Print(locale.T("config_set_help")) return nil } -func formatKey(key string) string { - return fmt.Sprintf("[CYAN]%s[/RESET]", key) +func colorizeValue(cfg *config.Instance, opt mediator.Option, value interface{}) string { + v := formatValue(opt, value) + + var tags []string + if opt.Type == mediator.Bool { + if v == "true" { + tags = append(tags, "[GREEN]") + } else { + tags = append(tags, "[RED]") + } + } + + if cfg.IsSet(opt.Name) { + tags = append(tags, "[BOLD]") + v = v + "*" + } + + if len(tags) > 0 { + return fmt.Sprintf("%s%s[/RESET]", strings.Join(tags, ""), v) + } + + return v } func formatValue(opt mediator.Option, value interface{}) string { - var v string switch opt.Type { - case mediator.Enum: - return fmt.Sprintf("\"%s\"", value) + case mediator.Enum, mediator.String: + return formatString(fmt.Sprintf("%v", value)) default: - v = fmt.Sprintf("%v", value) + return fmt.Sprintf("%v", value) } +} - if v == "" { +func formatString(value string) string { + if value == "" { return "\"\"" } - if len(v) > 100 { - v = v[:100] + "..." - } - - if value == mediator.GetDefault(opt) { - return fmt.Sprintf("[GREEN]%s[/RESET]", v) + if len(value) > 100 { + value = value[:100] + "..." } - return fmt.Sprintf("[BOLD][RED]%s*[/RESET]", v) -} - -func formatDefault(defaultValue interface{}) string { - v := fmt.Sprintf("%v", defaultValue) - if v == "" { - v = "\"\"" - } - return fmt.Sprintf("[DISABLED]%s[/RESET]", v) + return fmt.Sprintf("\"%s\"", value) } From c29e7fa3b18b318676988f45d542f2edda2e0f16 Mon Sep 17 00:00:00 2001 From: mdrakos Date: Wed, 9 Oct 2024 15:47:18 -0700 Subject: [PATCH 09/13] Break up value processing --- internal/runners/config/config.go | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/internal/runners/config/config.go b/internal/runners/config/config.go index f6eb43c464..f10959425a 100644 --- a/internal/runners/config/config.go +++ b/internal/runners/config/config.go @@ -71,9 +71,10 @@ func (c *List) renderUserFacing(configData []structuredConfigData) error { tbl := table.New(locale.Ts("Key", "Value", "Default")) tbl.HideDash = true for _, config := range configData { + v := formatValue(config.opt, config.Value) tbl.AddRow([]string{ fmt.Sprintf("[CYAN]%s[/RESET]", config.Key), - colorizeValue(cfg, config.opt, config.Value), + colorizeValue(cfg, config.opt, v), fmt.Sprintf("[DISABLED]%s[/RESET]", formatValue(config.opt, config.Default)), }) } @@ -86,12 +87,10 @@ func (c *List) renderUserFacing(configData []structuredConfigData) error { return nil } -func colorizeValue(cfg *config.Instance, opt mediator.Option, value interface{}) string { - v := formatValue(opt, value) - +func colorizeValue(cfg *config.Instance, opt mediator.Option, value string) string { var tags []string if opt.Type == mediator.Bool { - if v == "true" { + if value == "true" { tags = append(tags, "[GREEN]") } else { tags = append(tags, "[RED]") @@ -100,14 +99,14 @@ func colorizeValue(cfg *config.Instance, opt mediator.Option, value interface{}) if cfg.IsSet(opt.Name) { tags = append(tags, "[BOLD]") - v = v + "*" + value = value + "*" } if len(tags) > 0 { - return fmt.Sprintf("%s%s[/RESET]", strings.Join(tags, ""), v) + return fmt.Sprintf("%s%s[/RESET]", strings.Join(tags, ""), value) } - return v + return value } func formatValue(opt mediator.Option, value interface{}) string { From 49f6ed0ccc0e8cc25fb0f2d14efc9cef18887f80 Mon Sep 17 00:00:00 2001 From: mdrakos Date: Thu, 10 Oct 2024 12:37:03 -0700 Subject: [PATCH 10/13] Fix bold output --- internal/colorize/colorize.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/internal/colorize/colorize.go b/internal/colorize/colorize.go index 9fdd9b06c5..c351727f6c 100644 --- a/internal/colorize/colorize.go +++ b/internal/colorize/colorize.go @@ -180,6 +180,8 @@ func colorize(ct ColorTheme, writer io.Writer, arg string) { ct.Warning(writer) case `ERROR`: ct.Error(writer) + case `BOLD`: + ct.Bold(writer) case `DISABLED`: ct.Disabled(writer) case `ACTIONABLE`: From 2fe66b57bfab6a549c887bd962cdc0f389a58875 Mon Sep 17 00:00:00 2001 From: mdrakos Date: Thu, 10 Oct 2024 12:58:42 -0700 Subject: [PATCH 11/13] Don't format config value separately --- internal/runners/config/config.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/internal/runners/config/config.go b/internal/runners/config/config.go index f10959425a..c3746f8e77 100644 --- a/internal/runners/config/config.go +++ b/internal/runners/config/config.go @@ -71,10 +71,9 @@ func (c *List) renderUserFacing(configData []structuredConfigData) error { tbl := table.New(locale.Ts("Key", "Value", "Default")) tbl.HideDash = true for _, config := range configData { - v := formatValue(config.opt, config.Value) tbl.AddRow([]string{ fmt.Sprintf("[CYAN]%s[/RESET]", config.Key), - colorizeValue(cfg, config.opt, v), + renderConfigValue(cfg, config.opt), fmt.Sprintf("[DISABLED]%s[/RESET]", formatValue(config.opt, config.Default)), }) } @@ -87,16 +86,18 @@ func (c *List) renderUserFacing(configData []structuredConfigData) error { return nil } -func colorizeValue(cfg *config.Instance, opt mediator.Option, value string) string { +func renderConfigValue(cfg *config.Instance, opt mediator.Option) string { + configured := cfg.Get(opt.Name) var tags []string if opt.Type == mediator.Bool { - if value == "true" { + if configured == true { tags = append(tags, "[GREEN]") } else { tags = append(tags, "[RED]") } } + value := formatValue(opt, configured) if cfg.IsSet(opt.Name) { tags = append(tags, "[BOLD]") value = value + "*" From c111f3c99580d595f00d88444c862efead56687b Mon Sep 17 00:00:00 2001 From: mdrakos Date: Thu, 10 Oct 2024 13:03:51 -0700 Subject: [PATCH 12/13] Localize table headers --- internal/locale/locales/en-us.yaml | 6 ++++++ internal/runners/config/config.go | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/internal/locale/locales/en-us.yaml b/internal/locale/locales/en-us.yaml index 60da73f045..a23b5d66b3 100644 --- a/internal/locale/locales/en-us.yaml +++ b/internal/locale/locales/en-us.yaml @@ -1518,6 +1518,12 @@ version: other: Version license: other: License +key: + other: Key +value: + other: Value +default: + other: Default vulnerabilities: other: Vulnerabilities (CVEs) dependency_row: diff --git a/internal/runners/config/config.go b/internal/runners/config/config.go index c3746f8e77..775a821370 100644 --- a/internal/runners/config/config.go +++ b/internal/runners/config/config.go @@ -68,7 +68,7 @@ func (c *List) renderUserFacing(configData []structuredConfigData) error { cfg := c.prime.Config() out := c.prime.Output() - tbl := table.New(locale.Ts("Key", "Value", "Default")) + tbl := table.New(locale.Ts("key", "value", "default")) tbl.HideDash = true for _, config := range configData { tbl.AddRow([]string{ From f900b877deac2c6b93ac20652d680390147fb0d1 Mon Sep 17 00:00:00 2001 From: Mike Drakos Date: Thu, 10 Oct 2024 13:04:34 -0700 Subject: [PATCH 13/13] Update internal/runners/config/config.go Co-authored-by: Nathan Rijksen --- internal/runners/config/config.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/runners/config/config.go b/internal/runners/config/config.go index 775a821370..689b40e7ef 100644 --- a/internal/runners/config/config.go +++ b/internal/runners/config/config.go @@ -79,9 +79,9 @@ func (c *List) renderUserFacing(configData []structuredConfigData) error { } out.Print(tbl.Render()) - out.Print("") - out.Print(locale.T("config_get_help")) - out.Print(locale.T("config_set_help")) + out.Notice("") + out.Notice(locale.T("config_get_help")) + out.Notice(locale.T("config_set_help")) return nil }