Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • oss/libraries/go/application/xflags
1 result
Select Git revision
Show changes
Commits on Source (3)
<a name="v1.9.0"></a>
## [v1.9.0] - 2022-10-15
### Add Features
- feat implements proxy interface [#2](https://gitlab.schukai.com/oss/libraries/go/application/xflags/issues/2)
<a name="v1.8.3"></a>
## [v1.8.3] - 2022-10-15
### Bug Fixes
......@@ -102,6 +108,7 @@
<a name="v1.0.0"></a>
## v1.0.0 - 2022-10-04
[v1.9.0]: https://gitlab.schukai.com/oss/libraries/go/application/xflags/compare/v1.8.3...v1.9.0
[v1.8.3]: https://gitlab.schukai.com/oss/libraries/go/application/xflags/compare/v1.8.2...v1.8.3
[v1.8.2]: https://gitlab.schukai.com/oss/libraries/go/application/xflags/compare/v1.8.1...v1.8.2
[v1.8.1]: https://gitlab.schukai.com/oss/libraries/go/application/xflags/compare/v1.8.0...v1.8.1
......
......@@ -146,14 +146,16 @@ The function `Execute()` executes the command. See the section
setting.Execute()
```
### Shadow
### Proxy
The shadow structure is used to copy the values of the flags to the
shadow structure. The shadow structure is set using the `SetShadow()`
and configured using the tag `shadow`.
The proxy structure is used to copy the values of the flags to the
proxy structure. The proxy structure is used to access the values of the
flags.
The proxy structure must implement the `Proxy` interface.
```go
type Shadow struct {
type MyObj struct {
Verbose bool
Serve struct {
Host string
......@@ -161,12 +163,14 @@ type Shadow struct {
}
}
func (m *MyObj) Copy(_ map[string]any) {
}
func main() {
setting := New(os.Args[0], Definition{})
setting.SetShadow(Shadow{})
setting.SetProxy(&MyObj{})
setting.Parse(os.Args[1:])
setting.Execute()
fmt.Printf("Shadow: %+v", setting.GetShadow())
}
```
......
......@@ -12,18 +12,22 @@ import (
"reflect"
)
// ExecuteWithShadow executes the command line arguments and calls the functions.
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{}
type dummyCopyArg struct{}
func (n noShadow) Copy(a noShadow) {}
func (n dummyCopyArg) Copy(_ map[string]any) {}
// 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:])
func Execute[C any](cmd C, cpy ...Proxy) *Settings[C] {
if cpy == nil {
return execute(cmd, dummyCopyArg{}, os.Args[0], os.Args[1:])
}
if len(cpy) > 1 {
panic("too many arguments")
}
return execute(cmd, cpy[0], os.Args[0], os.Args[1:])
}
// PrintFlagOutput prints the flag output to the standard output.
......@@ -36,15 +40,15 @@ func (s *Settings[C]) GetFlagOutput() {
fmt.Println(s.command.flagSet.Output())
}
// execute is the internal implementation of ExecuteWithShadow.
func execute[C any, D Copyable[D]](cmd C, cnf D, name string, args []string) *Settings[C] {
// execute is the internal implementation of Execute.
func execute[C any, D Proxy](cmd C, proxy D, name string, args []string) *Settings[C] {
instance := New(name, cmd)
if instance.HasErrors() {
return instance
}
if (reflect.ValueOf(&cnf).Elem().Type() != reflect.TypeOf(noShadow{})) {
instance.SetShadow(cnf)
if (reflect.ValueOf(&proxy).Elem().Type() != reflect.TypeOf(dummyCopyArg{})) {
instance.SetProxy(proxy)
if instance.HasErrors() {
return instance
}
......@@ -59,10 +63,6 @@ func execute[C any, D Copyable[D]](cmd C, cnf D, name string, args []string) *Se
return instance
}
if instance.shadow != nil {
cnf.Copy(instance.shadow.(D))
}
instance.Execute()
if instance.HasErrors() {
return instance
......@@ -87,6 +87,8 @@ func New[C any](name string, definitions C) *Settings[C] {
return s
}
s.mapping = make(map[string]any)
buf := bytes.NewBufferString("")
s.flagOutput = io.Writer(buf)
s.definitions = definitions
......
......@@ -25,7 +25,7 @@ func TestUsage(t *testing.T) {
type TestDataStruct struct {
}
func (s *TestDataStruct) Copy(x *TestDataStruct) {
func (s *TestDataStruct) Copy(_ map[string]any) {
}
......@@ -44,8 +44,7 @@ func TestExecuteTypeStringIsNotSupported(t *testing.T) {
func TestExecuteHelp(t *testing.T) {
instance := execute(CmdTest1{}, &TestDataStruct{}, "test", []string{"-h"})
assert.False(t, instance.HasErrors())
assert.True(t, instance.HelpRequested())
}
func TestNewIntWithError(t *testing.T) {
......
......@@ -9,14 +9,13 @@ import (
)
type cmd[C any] struct {
name string
flagSet *flag.FlagSet
tagMapping map[string]string
shadowMapping map[string]string
commands []*cmd[C]
settings *Settings[C]
valuePath []string
functionName string
name string
flagSet *flag.FlagSet
tagMapping map[string]string
commands []*cmd[C]
settings *Settings[C]
valuePath []string
functionName string
}
func (c *cmd[C]) parse(args []string) {
......@@ -56,14 +55,13 @@ func (c *cmd[C]) parse(args []string) {
func buildCommandStruct[C any](s *Settings[C], name, fkt string, errorHandling flag.ErrorHandling, path []string) *cmd[C] {
cc := &cmd[C]{
name: name,
flagSet: flag.NewFlagSet(name, errorHandling),
commands: []*cmd[C]{},
settings: s,
tagMapping: map[string]string{},
shadowMapping: map[string]string{},
valuePath: path,
functionName: fkt,
name: name,
flagSet: flag.NewFlagSet(name, errorHandling),
commands: []*cmd[C]{},
settings: s,
tagMapping: map[string]string{},
valuePath: path,
functionName: fkt,
}
cc.flagSet.SetOutput(s.flagOutput)
......@@ -157,15 +155,8 @@ func (c *cmd[C]) parseStruct(dta any) {
if m[tagLong] != "" {
c.tagMapping[m[tagLong]] = v.Type().Field(i).Name
}
if m[tagShadow] != "" {
c.shadowMapping[v.Type().Field(i).Name] = m[tagShadow]
}
c.initFlags(x, m)
} else if m[tagCommand] != "" {
//c.valuePath = append(c.valuePath, )
c.tagMapping[m[tagCommand]] = v.Type().Field(i).Name
c.initCommands(x, m, v.Type().Field(i).Name)
......
......@@ -126,3 +126,9 @@ type MissingFunctionError error
func newMissingFunctionError(missing string) MissingFunctionError {
return MissingFunctionError(errors.New("missing function " + missing))
}
type InvalidTypeForPathError error
func newInvalidTypeForPathError(path string, pt string, nt string) InvalidTypeForPathError {
return InvalidTypeForPathError(errors.New("invalid type for path " + path + ": expected " + pt + ", got " + nt))
}
......@@ -96,3 +96,9 @@ func TestMissingFunctionError(t *testing.T) {
_, ok := err.(MissingFunctionError)
assert.True(t, ok)
}
func TestInvalidTypeForPathError(t *testing.T) {
err := newInvalidTypeForPathError("test", "test", "test")
_, ok := err.(InvalidTypeForPathError)
assert.True(t, ok)
}
......@@ -6,8 +6,10 @@ package xflags
import (
"flag"
"fmt"
"github.com/stretchr/testify/assert"
"reflect"
"strings"
"testing"
)
func (s *Settings[C]) Execute() *Settings[C] {
......@@ -31,7 +33,6 @@ func (s *Settings[C]) Execute() *Settings[C] {
func callCmdFunctions[C any](settings *Settings[C], commands []*cmd[C]) bool {
//result := false
wasExecuted := false
shouldExecute := false
......@@ -117,3 +118,33 @@ func (s *Settings[C]) MissingCommand() bool {
func (s *Settings[C]) WasExecuted() bool {
return s.wasExecuted
}
func TestWrongDefinitionType(t *testing.T) {
c := New("root", 2)
c.Parse([]string{"test"})
c.Execute()
assert.True(t, c.HasErrors())
}
type testExecuteCommandStruct struct {
Command1 struct {
} `command:"command1" description:"Command 1" callback:"command1Callback" `
Command2 struct {
Command3 struct {
} `command:"command3" description:"Command 3" callback:"command3Callback" call:"DoCmd3"`
} `command:"command2" description:"Command 2" callback:"command2Callback" `
}
func (c *testExecuteCommandStruct) DoCmd3(s *Settings[testExecuteCommandStruct]) {
}
func (c *testExecuteCommandStruct) command1Callback(args []string) {
fmt.Println("command1Callback", args)
}
func TestExecute1(t *testing.T) {
c := New("root", testExecuteCommandStruct{})
c.Parse([]string{"command2", "command3", "commandX"})
c.Execute()
assert.False(t, c.HasErrors())
}
// Copyright 2022 schukai GmbH
// SPDX-License-Identifier: AGPL-3.0
package xflags
// Copyright 2022 schukai GmbH
// SPDX-License-Identifier: AGPL-3.0
package xflags
import (
"fmt"
"github.com/stretchr/testify/assert"
"testing"
)
func TestWrongDefinitionType(t *testing.T) {
c := New("root", 2)
c.Parse([]string{"test"})
c.Execute()
assert.True(t, c.HasErrors())
}
type testExecuteCommandStruct struct {
Command1 struct {
} `command:"command1" description:"Command 1" callback:"command1Callback" `
Command2 struct {
Command3 struct {
} `command:"command3" description:"Command 3" callback:"command3Callback" call:"DoCmd3"`
} `command:"command2" description:"Command 2" callback:"command2Callback" `
}
func (c *testExecuteCommandStruct) DoCmd3(s *Settings[testExecuteCommandStruct]) {
}
func (c *testExecuteCommandStruct) command1Callback(args []string) {
fmt.Println("command1Callback", args)
}
func TestExecute1(t *testing.T) {
c := New("root", testExecuteCommandStruct{})
c.Parse([]string{"command2", "command3", "commandX"})
c.Execute()
assert.False(t, c.HasErrors())
}
......@@ -60,7 +60,7 @@ func TestIssue1TestCallCMD4(tp *testing.T) {
for i, tt := range testData {
tp.Run(strconv.Itoa(i)+":"+strings.Join(tt.args, ","), func(t *testing.T) {
s := execute(testCmdStructIssue1{}, noShadow{}, "test", tt.args)
s := execute(testCmdStructIssue1{}, dummyCopyArg{}, "test", tt.args)
assert.Equal(t, tt.hasErrors, s.HasErrors())
assert.Equal(t, tt.hasHint, s.HasHint())
......@@ -75,27 +75,27 @@ func TestIssue1TestCallCMD4(tp *testing.T) {
}
func TestIssue1TestNoCallback(t *testing.T) {
s := execute(testCmdStructIssue1{}, noShadow{}, "test", []string{"cmd1", "cmd6", "cmd7"})
s := execute(testCmdStructIssue1{}, dummyCopyArg{}, "test", []string{"cmd1", "cmd6", "cmd7"})
assert.Equal(t, 3, len(s.Errors()))
assert.False(t, s.WasExecuted())
}
func TestIssue1TestToMuchCommands(t *testing.T) {
s := execute(testCmdStructIssue1{}, noShadow{}, "test", []string{"cmd1", "cmd9"})
s := execute(testCmdStructIssue1{}, dummyCopyArg{}, "test", []string{"cmd1", "cmd9"})
assert.True(t, s.MissingCommand())
assert.False(t, s.WasExecuted())
}
// here it is tested whether the last and defined callback is called
func TestIssue1TestCallCMD3(t *testing.T) {
s := execute(testCmdStructIssue1{}, noShadow{}, "test", []string{"cmd1", "cmd2", "cmd3"})
s := execute(testCmdStructIssue1{}, dummyCopyArg{}, "test", []string{"cmd1", "cmd2", "cmd3"})
assert.Equal(t, 0, len(s.Errors()))
assert.True(t, s.WasExecuted())
}
// NoShadow is an internal Struct for testing
func TestIssue1MessageWithNoShadow(t *testing.T) {
s := execute(testCmdStructIssue1{}, noShadow{}, "test", []string{"cmd1", "cmd2", "cmd3", "-v3"})
s := execute(testCmdStructIssue1{}, dummyCopyArg{}, "test", []string{"cmd1", "cmd2", "cmd3", "-v3"})
assert.Equal(t, 0, len(s.Errors()))
}
......@@ -139,7 +139,7 @@ func TestIssue1Summary(tp *testing.T) {
for _, tt := range data {
tp.Run(tt.args[0], func(t *testing.T) {
s := execute(testCmdStructIssue1{}, noShadow{}, "test", tt.args)
s := execute(testCmdStructIssue1{}, dummyCopyArg{}, "test", tt.args)
assert.Equal(t, tt.helpRequested, s.HelpRequested())
assert.Equal(t, tt.wasExecuted, s.WasExecuted())
assert.Equal(t, tt.missingCommand, s.MissingCommand())
......
......@@ -9,25 +9,26 @@ import (
"strings"
)
// SetShadow sets the shadow struct for the flag configuration.
func (s *Settings[C]) SetShadow(shadow any) *Settings[C] {
// SetProxy sets the shadow struct for the flag configuration.
func (s *Settings[C]) SetProxy(proxy Proxy) *Settings[C] {
if reflect.TypeOf(shadow).Kind() != reflect.Ptr {
if reflect.TypeOf(proxy).Kind() != reflect.Ptr {
s.errors = append(s.errors, ShadowMustBePointerError)
return s
}
if reflect.TypeOf(shadow).Elem().Kind() != reflect.Struct {
if reflect.TypeOf(proxy).Elem().Kind() != reflect.Struct {
s.errors = append(s.errors, ShadowMustBePointerError)
return s
}
s.shadow = shadow
s.proxy = proxy
return s
}
type Copyable[C any] interface {
Copy(data C)
// Proxy is the interface for the proxy struct.
type Proxy interface {
Copy(map[string]any)
}
func (s *Settings[C]) assignValues(c cmd[C]) {
......@@ -46,33 +47,15 @@ func (s *Settings[C]) assignValues(c cmd[C]) {
pa := append(c.valuePath, k)
p := strings.Join(pa, ".")
err := setValueUsingPath(&s.definitions, p, value)
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)
}
s.mapping[p] = value
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)
}
......@@ -20,13 +20,6 @@ type ConfigStruct6 struct {
ValSub ConfigStruct6Sub1
}
func TestFlagSetShadowError(t *testing.T) {
settings := New("test", testExecutionStruct{})
settings.SetShadow(3)
assert.True(t, settings.HasErrors())
}
func TestFlagCopyToShadow(t *testing.T) {
c := ConfigStruct6{}
......@@ -35,7 +28,7 @@ func TestFlagCopyToShadow(t *testing.T) {
settings := New("test", testExecutionStruct{})
assert.NotNil(t, settings)
settings.SetShadow(&c)
settings.SetProxy(&c)
assert.False(t, settings.HasErrors())
settings.Parse([]string{"-a", "command1", "-d"})
......@@ -45,8 +38,9 @@ func TestFlagCopyToShadow(t *testing.T) {
}
func (s *ConfigStruct6) Copy(p *ConfigStruct6) {
func (s *ConfigStruct6) Copy(m map[string]any) {
SetValueUsingPath(s, "ValGlobal1", (m["Global1"]))
SetValueUsingPath(s, "ValCommand1Flag2", (m["Command1.Command1Flag2"]))
}
func TestCopyable(t *testing.T) {
......
......@@ -38,5 +38,9 @@ func (s *Settings[C]) Parse(args []string) *Settings[C] {
s.command.parse(r)
if s.mapping != nil && s.proxy != nil {
s.proxy.Copy(s.mapping)
}
return s
}
......@@ -4,13 +4,14 @@
package xflags
import (
"fmt"
"reflect"
"strconv"
"strings"
)
// This function returns the value of a field in a struct, given a path to the field.
func getValueFrom[D any](obj D, keyWithDots string) (interface{}, error) {
func GetValueFrom[D any](obj D, keyWithDots string) (any, error) {
keySlice := strings.Split(keyWithDots, ".")
v := reflect.ValueOf(obj)
......@@ -49,7 +50,7 @@ func getValueFrom[D any](obj D, keyWithDots string) (interface{}, error) {
}
// This function sets the value of a field in a struct, given a path to the field.
func setValueUsingPath[D any](obj D, keyWithDots string, newValue string) error {
func SetValueUsingPath[D any](obj D, keyWithDots string, newValue any) error {
keySlice := strings.Split(keyWithDots, ".")
v := reflect.ValueOf(obj)
......@@ -94,29 +95,83 @@ func setValueUsingPath[D any](obj D, keyWithDots string, newValue string) error
return newCannotSetError(keyWithDots)
}
switch v.Kind() {
case reflect.Ptr:
if newValue == nil {
v.Set(reflect.Zero(v.Type()))
} else {
v.Set(reflect.ValueOf(&newValue))
}
return nil
}
newValueType := reflect.TypeOf(newValue)
if newValueType == nil {
return newUnsupportedTypePathError(keyWithDots, v.Type())
}
newValueKind := reflect.TypeOf(newValue).Kind()
switch v.Kind() {
case reflect.String:
v.SetString(newValue)
case reflect.Int:
if newValueKind == reflect.String {
v.SetString(newValue.(string))
} else {
v.SetString(fmt.Sprintf("%v", newValue))
}
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
s, err := strconv.Atoi(newValue)
if err != nil {
return err
if newValueKind == reflect.Int {
v.SetInt(int64(newValue.(int)))
} else {
s, err := strconv.ParseInt(newValue.(string), 10, 64)
if err != nil {
return err
}
v.SetInt(s)
}
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
if newValueKind == reflect.Int {
v.SetUint(uint64(newValue.(int)))
} else {
s, err := strconv.ParseInt(newValue.(string), 10, 64)
if err != nil {
return err
}
v.SetUint(uint64(s))
}
v.SetInt(int64(s))
case reflect.Bool:
v.SetBool(newValue == "true")
case reflect.Float64:
s, err := strconv.ParseFloat(newValue, 64)
if err != nil {
return err
if newValueKind == reflect.Bool {
v.SetBool(newValue.(bool))
} else {
b, err := strconv.ParseBool(newValue.(string))
if err != nil {
return err
}
v.SetBool(b)
}
case reflect.Float64, reflect.Float32:
if newValueKind == reflect.Float64 {
v.SetFloat(newValue.(float64))
} else {
s, err := strconv.ParseFloat(newValue.(string), 64)
if err != nil {
return err
}
v.SetFloat(s)
}
v.SetFloat(s)
default:
return newUnsupportedTypeAtTopOfPathError(keyWithDots, v.Type())
return newInvalidTypeForPathError(keyWithDots, v.Type().String(), newValueKind.String())
}
return nil
......
......@@ -32,7 +32,7 @@ func TestPathFindError(t *testing.T) {
s := PathfindTestStruct1{}
_, err := getValueFrom[PathfindTestStruct1](s, "Sub1.Sub2.Sub3.XX")
_, err := GetValueFrom[PathfindTestStruct1](s, "Sub1.Sub2.Sub3.XX")
if err == nil {
t.Error("err == nil")
}
......@@ -58,7 +58,7 @@ func TestPathFindSetValueString(t *testing.T) {
for k, v := range testData {
s := &PathfindTestStruct1{}
err := setValueUsingPath[*PathfindTestStruct1](s, k, v)
err := SetValueUsingPath[*PathfindTestStruct1](s, k, v)
if err != nil {
t.Error(err)
}
......@@ -74,7 +74,7 @@ func TestPathFindGetValueFrom(t *testing.T) {
s.Sub1.Bs = "3"
s.Sub1.Bf = 4.0
v, err := getValueFrom[PathfindTestStruct1](s, "Sub1.B")
v, err := GetValueFrom[PathfindTestStruct1](s, "Sub1.B")
if err != nil {
t.Error(err)
}
......@@ -83,7 +83,7 @@ func TestPathFindGetValueFrom(t *testing.T) {
t.Error("v != true")
}
v, err = getValueFrom[PathfindTestStruct1](s, "Sub1.Bi")
v, err = GetValueFrom[PathfindTestStruct1](s, "Sub1.Bi")
if err != nil {
t.Error(err)
}
......@@ -92,7 +92,7 @@ func TestPathFindGetValueFrom(t *testing.T) {
t.Error("v != 2")
}
v, err = getValueFrom[PathfindTestStruct1](s, "Sub1.Bs")
v, err = GetValueFrom[PathfindTestStruct1](s, "Sub1.Bs")
if err != nil {
t.Error(err)
}
......@@ -101,7 +101,7 @@ func TestPathFindGetValueFrom(t *testing.T) {
t.Error("v != 3")
}
v, err = getValueFrom[PathfindTestStruct1](s, "Sub1.Bf")
v, err = GetValueFrom[PathfindTestStruct1](s, "Sub1.Bf")
if err != nil {
t.Error(err)
}
......@@ -115,7 +115,7 @@ func TestPathFindGetValueFrom(t *testing.T) {
s.Sub1.Sub2.Cs = "3"
s.Sub1.Sub2.Cf = 4.0
v, err = getValueFrom[PathfindTestStruct1](s, "Sub1.Sub2.C")
v, err = GetValueFrom[PathfindTestStruct1](s, "Sub1.Sub2.C")
if err != nil {
t.Error(err)
}
......@@ -124,7 +124,7 @@ func TestPathFindGetValueFrom(t *testing.T) {
t.Error("v != true")
}
v, err = getValueFrom[PathfindTestStruct1](s, "Sub1.Sub2.Ci")
v, err = GetValueFrom[PathfindTestStruct1](s, "Sub1.Sub2.Ci")
if err != nil {
t.Error(err)
}
......@@ -133,7 +133,7 @@ func TestPathFindGetValueFrom(t *testing.T) {
t.Error("v != 2")
}
v, err = getValueFrom[PathfindTestStruct1](s, "Sub1.Sub2.Cs")
v, err = GetValueFrom[PathfindTestStruct1](s, "Sub1.Sub2.Cs")
if err != nil {
t.Error(err)
}
......@@ -142,7 +142,7 @@ func TestPathFindGetValueFrom(t *testing.T) {
t.Error("v != 3")
}
v, err = getValueFrom[PathfindTestStruct1](s, "Sub1.Sub2.Cf")
v, err = GetValueFrom[PathfindTestStruct1](s, "Sub1.Sub2.Cf")
if err != nil {
t.Error(err)
}
......@@ -156,7 +156,7 @@ func TestPathFindGetValueFrom(t *testing.T) {
s.Sub1.Sub2.Sub3.Ds = "3"
s.Sub1.Sub2.Sub3.Df = 4.0
v, err = getValueFrom[PathfindTestStruct1](s, "Sub1.Sub2.Sub3.D")
v, err = GetValueFrom[PathfindTestStruct1](s, "Sub1.Sub2.Sub3.D")
if err != nil {
t.Error(err)
......@@ -166,7 +166,7 @@ func TestPathFindGetValueFrom(t *testing.T) {
t.Error("v != true")
}
v, err = getValueFrom[PathfindTestStruct1](s, "Sub1.Sub2.Sub3.Di")
v, err = GetValueFrom[PathfindTestStruct1](s, "Sub1.Sub2.Sub3.Di")
if err != nil {
t.Error(err)
}
......@@ -175,7 +175,7 @@ func TestPathFindGetValueFrom(t *testing.T) {
t.Error("v != 2")
}
v, err = getValueFrom[PathfindTestStruct1](s, "Sub1.Sub2.Sub3.Ds")
v, err = GetValueFrom[PathfindTestStruct1](s, "Sub1.Sub2.Sub3.Ds")
if err != nil {
t.Error(err)
}
......@@ -184,7 +184,7 @@ func TestPathFindGetValueFrom(t *testing.T) {
t.Error("v != 3")
}
v, err = getValueFrom[PathfindTestStruct1](s, "Sub1.Sub2.Sub3.Df")
v, err = GetValueFrom[PathfindTestStruct1](s, "Sub1.Sub2.Sub3.Df")
if err != nil {
t.Error(err)
}
......@@ -198,10 +198,10 @@ func TestPathFindGetValueFrom(t *testing.T) {
func TestPathFindSetValueFrom(t *testing.T) {
s := &PathfindTestStruct1{}
setValueUsingPath[*PathfindTestStruct1](s, "Sub1.B", "true")
setValueUsingPath[*PathfindTestStruct1](s, "Sub1.Bi", "2")
setValueUsingPath[*PathfindTestStruct1](s, "Sub1.Bs", "3")
setValueUsingPath[*PathfindTestStruct1](s, "Sub1.Bf", "4.0")
SetValueUsingPath[*PathfindTestStruct1](s, "Sub1.B", "true")
SetValueUsingPath[*PathfindTestStruct1](s, "Sub1.Bi", "2")
SetValueUsingPath[*PathfindTestStruct1](s, "Sub1.Bs", "3")
SetValueUsingPath[*PathfindTestStruct1](s, "Sub1.Bf", "4.0")
if s.Sub1.B != true {
t.Error("s.Sub1.B != true")
......@@ -220,10 +220,10 @@ func TestPathFindSetValueFrom(t *testing.T) {
t.Error("s.Sub1.Bf != 4.0")
}
setValueUsingPath[*PathfindTestStruct1](s, "Sub1.Sub2.C", "true")
setValueUsingPath[*PathfindTestStruct1](s, "Sub1.Sub2.Ci", "2")
setValueUsingPath[*PathfindTestStruct1](s, "Sub1.Sub2.Cs", "3")
setValueUsingPath[*PathfindTestStruct1](s, "Sub1.Sub2.Cf", "4.0")
SetValueUsingPath[*PathfindTestStruct1](s, "Sub1.Sub2.C", "true")
SetValueUsingPath[*PathfindTestStruct1](s, "Sub1.Sub2.Ci", "2")
SetValueUsingPath[*PathfindTestStruct1](s, "Sub1.Sub2.Cs", "3")
SetValueUsingPath[*PathfindTestStruct1](s, "Sub1.Sub2.Cf", "4.0")
if s.Sub1.Sub2.C != true {
t.Error("s.Sub1.Sub2.C != true")
......@@ -250,10 +250,10 @@ func TestPathFindSetValueFrom(t *testing.T) {
}
setValueUsingPath[*PathfindTestStruct1](s, "Sub1.Sub2.Sub3.D", "true")
setValueUsingPath[*PathfindTestStruct1](s, "Sub1.Sub2.Sub3.Di", "2")
setValueUsingPath[*PathfindTestStruct1](s, "Sub1.Sub2.Sub3.Ds", "3")
setValueUsingPath[*PathfindTestStruct1](s, "Sub1.Sub2.Sub3.Df", "4.0")
SetValueUsingPath[*PathfindTestStruct1](s, "Sub1.Sub2.Sub3.D", "true")
SetValueUsingPath[*PathfindTestStruct1](s, "Sub1.Sub2.Sub3.Di", "2")
SetValueUsingPath[*PathfindTestStruct1](s, "Sub1.Sub2.Sub3.Ds", "3")
SetValueUsingPath[*PathfindTestStruct1](s, "Sub1.Sub2.Sub3.Df", "4.0")
if s.Sub1.Sub2.Sub3.D != true {
t.Error("s.Sub1.Sub2.Sub3.D != true")
......
......@@ -25,6 +25,13 @@ func TestReadMeInit(t *testing.T) {
setting.Parse([]string{"-v", "serve", "-h", "localhost", "-p", "8080"})
setting.Execute()
assert.True(t, setting.definitions.Verbose)
if setting.HasErrors() {
for _, err := range setting.Errors() {
t.Log(err)
}
}
assert.False(t, setting.HasErrors())
}
......
{"version":"1.8.3"}
{"version":"1.9.0"}
......@@ -17,6 +17,7 @@ type config struct {
errorHandling flag.ErrorHandling
}
// Settings[C] is the main struct for the xflags package.
type Settings[C any] struct {
definitions C
......@@ -29,7 +30,8 @@ type Settings[C any] struct {
config config
shadow any
mapping map[string]any
proxy Proxy
wasExecuted bool
hint string
......
......@@ -15,7 +15,6 @@ const (
tagShort = "short"
tagLong = "long"
tagDescription = "description"
tagShadow = "shadow"
)
func getTagMap(field reflect.StructField) (value map[string]string) {
......