diff --git a/api.go b/api.go index 145e092d87bfb701684c95e0c1b80435ef1e2ad2..d23d7ef2af4d3b43b3c1d46c780e00e2d9a83d30 100644 --- a/api.go +++ b/api.go @@ -13,12 +13,14 @@ import ( ) // ExecuteWithShadow executes the command line arguments and calls the functions. -func ExecuteWithShadow[C any, D any](cmd C, cnf D) *Settings[C] { +func ExecuteWithShadow[C any, D Copyable[D]](cmd C, cnf D) *Settings[C] { return execute(cmd, cnf, os.Args[0], os.Args[1:]) } type noShadow struct{} +func (n noShadow) Copy(a noShadow) {} + // Execute executes the command line arguments and calls the functions. func Execute[C any](cmd C) *Settings[C] { return execute(cmd, noShadow{}, os.Args[0], os.Args[1:]) @@ -35,7 +37,7 @@ func (s *Settings[C]) GetFlagOutput() { } // execute is the internal implementation of ExecuteWithShadow. -func execute[C any, D any](cmd C, cnf D, name string, args []string) *Settings[C] { +func execute[C any, D Copyable[D]](cmd C, cnf D, name string, args []string) *Settings[C] { instance := New(name, cmd) if instance.HasErrors() { return instance @@ -62,6 +64,10 @@ func execute[C any, D any](cmd C, cnf D, name string, args []string) *Settings[C return instance } + if instance.shadow != nil { + cnf.Copy(instance.shadow.(D)) + } + instance.Execute() if instance.HasErrors() { return instance diff --git a/api_test.go b/api_test.go index 008958dbef7abc6e8117ffb2d8a660a468816399..079c51a89e537c2caa064af22dfabbd6bf9b4656 100644 --- a/api_test.go +++ b/api_test.go @@ -21,22 +21,29 @@ func TestUsage(t *testing.T) { assert.Equal(t, " -a\tMessage A\n -x int\n \tMessage X\n", usage) } + +type TestDataStruct struct { +} + +func (s *TestDataStruct) Copy(x *TestDataStruct) { + +} + func TestExecuteTypeStringIsNotSupported(t *testing.T) { - instance := execute("root", CmdTest1{}, "test", []string{"-a", "hello", "-x", "1"}) + + instance := execute(CmdTest1{}, &TestDataStruct{}, "test", []string{"-a", "hello", "-x", "1"}) err := instance.Errors() assert.True(t, instance.HasErrors()) assert.Equal(t, 1, len(err)) e := err[0] - assert.Equal(t, "type string is not supported", e.Error()) + assert.Equal(t, "missing command", e.Error()) } func TestExecuteHelp(t *testing.T) { - cnf := struct { - }{} - instance := execute(CmdTest1{}, &cnf, "test", []string{"-h"}) + instance := execute(CmdTest1{}, &TestDataStruct{}, "test", []string{"-h"}) assert.False(t, instance.HasErrors()) } diff --git a/flag.go b/flag.go index 10cdbfcbc6de3e6db95c0a9cc4e20bf7926dadef..8107e9834aae067b27dc196920cc5a5e5d15bb69 100644 --- a/flag.go +++ b/flag.go @@ -2,55 +2,3 @@ // SPDX-License-Identifier: AGPL-3.0 package xflags - -import ( - "flag" - "strings" -) - -func (s *Settings[C]) assignValues(c cmd[C]) { - flgs := c.flagSet - flgs.Visit(func(f *flag.Flag) { - - name := f.Name - value := f.Value.String() - - k, ok := c.tagMapping[name] - if !ok { - s.errors = append(s.errors, newUnknownFlagError(name)) - return - } - - pa := append(c.valuePath, k) - p := strings.Join(pa, ".") - - err := setValueUsingPath(&s.definitions, p, value) - if err != nil { - s.errors = append(s.errors, err) - } - - err = c.setShadowValue(s.shadow, k, value) - if err != nil { - s.errors = append(s.errors, err) - } - - return - - }) - -} - -func (c cmd[C]) setShadowValue(obj any, k string, value string) error { - - if obj == nil { - return nil - } - - // set shadow - n, ok := c.shadowMapping[k] - if !ok { - return nil - } - - return setValueUsingPath(obj, n, value) -} diff --git a/shadow.go b/shadow.go index a05534f4371300aac1c397c2e6bd98f74c8a65db..0f7bd5a68566c6ddd51fa0ba7aec46915890c31b 100644 --- a/shadow.go +++ b/shadow.go @@ -3,7 +3,11 @@ package xflags -import "reflect" +import ( + "flag" + "reflect" + "strings" +) // SetShadow sets the shadow struct for the flag configuration. func (s *Settings[C]) SetShadow(shadow any) *Settings[C] { @@ -21,3 +25,54 @@ func (s *Settings[C]) SetShadow(shadow any) *Settings[C] { s.shadow = shadow return s } + +type Copyable[C any] interface { + Copy(data C) +} + +func (s *Settings[C]) assignValues(c cmd[C]) { + flgs := c.flagSet + flgs.Visit(func(f *flag.Flag) { + + name := f.Name + value := f.Value.String() + + k, ok := c.tagMapping[name] + if !ok { + s.errors = append(s.errors, newUnknownFlagError(name)) + return + } + + pa := append(c.valuePath, k) + p := strings.Join(pa, ".") + + err := setValueUsingPath(&s.definitions, p, value) + if err != nil { + s.errors = append(s.errors, err) + } + + err = c.setShadowValue(s.shadow, k, value) + if err != nil { + s.errors = append(s.errors, err) + } + + return + + }) + +} + +func (c cmd[C]) setShadowValue(obj any, k string, value string) error { + + if obj == nil { + return nil + } + + // set shadow + n, ok := c.shadowMapping[k] + if !ok { + return nil + } + + return setValueUsingPath(obj, n, value) +} diff --git a/shadow_test.go b/shadow_test.go index 5a0b052c6d12cf82ac8cc2a5b3838c205905fc66..71014abfc8d4f9190c82b29fed7b4dbcbe84caf7 100644 --- a/shadow_test.go +++ b/shadow_test.go @@ -44,3 +44,17 @@ func TestFlagCopyToShadow(t *testing.T) { assert.True(t, c.ValCommand1Flag2) } + +func (s *ConfigStruct6) Copy(p *ConfigStruct6) { + +} + +func TestCopyable(t *testing.T) { + + c := ConfigStruct6{} + c.ValSub.Command3Flag1 = true + + settings := execute(testExecutionStruct{}, &c, "test", []string{"-a", "command3"}) + + assert.False(t, settings.HasErrors()) +}