From c570055c9d183df3e6f86acd1b31b5c1b9aa4801 Mon Sep 17 00:00:00 2001
From: Volker Schukai <volker.schukai@schukai.com>
Date: Sat, 20 May 2023 14:56:03 +0200
Subject: [PATCH] feat: add multiple string values

---
 .idea/.gitignore   |  8 ++++++++
 .idea/markdown.xml |  9 +++++++++
 .idea/misc.xml     |  6 ++++++
 .idea/modules.xml  |  8 ++++++++
 .idea/vcs.xml      |  6 ++++++
 .idea/xflags.iml   | 10 ++++++++++
 execute.go         |  3 +--
 hint.go            |  3 +++
 mapping.go         | 47 ++++++++++++++++++++++++++++++++++++++++++----
 parse_test.go      | 28 +++++++++++++++++++++++++++
 type.go            |  3 +++
 11 files changed, 125 insertions(+), 6 deletions(-)
 create mode 100644 .idea/.gitignore
 create mode 100644 .idea/markdown.xml
 create mode 100644 .idea/misc.xml
 create mode 100644 .idea/modules.xml
 create mode 100644 .idea/vcs.xml
 create mode 100644 .idea/xflags.iml
 create mode 100644 parse_test.go

diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/markdown.xml b/.idea/markdown.xml
new file mode 100644
index 0000000..ec0b30f
--- /dev/null
+++ b/.idea/markdown.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="MarkdownSettings">
+    <enabledExtensions>
+      <entry key="MermaidLanguageExtension" value="false" />
+      <entry key="PlantUMLLanguageExtension" value="true" />
+    </enabledExtensions>
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..639900d
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectRootManager">
+    <output url="file://$PROJECT_DIR$/out" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..4a09e5c
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/xflags.iml" filepath="$PROJECT_DIR$/.idea/xflags.iml" />
+    </modules>
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="" vcs="Git" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/xflags.iml b/.idea/xflags.iml
new file mode 100644
index 0000000..25ed3f6
--- /dev/null
+++ b/.idea/xflags.iml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+  <component name="Go" enabled="true" />
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$" />
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/execute.go b/execute.go
index 06b96d4..68a06c6 100644
--- a/execute.go
+++ b/execute.go
@@ -80,10 +80,9 @@ func callCmdFunctions[C any](settings *Settings[C], commands []*cmd[C]) bool {
 		if settings.hint == "" {
 			settings.hint = fmt.Sprintf("Did you mean: %v?", strings.Join(availableCommands, ", "))
 		}
+		settings.errors = append(settings.errors, MissingCommandError)
 	}
 
-	settings.errors = append(settings.errors, MissingCommandError)
-
 	return false
 
 }
diff --git a/hint.go b/hint.go
index 3b4f870..8586d20 100644
--- a/hint.go
+++ b/hint.go
@@ -1,3 +1,6 @@
+// Copyright 2023 schukai GmbH
+// SPDX-License-Identifier: AGPL-3.0
+
 package xflags
 
 func (s *Settings[C]) SetHint(hint string) *Settings[C] {
diff --git a/mapping.go b/mapping.go
index 19a0b66..f4f0438 100644
--- a/mapping.go
+++ b/mapping.go
@@ -7,6 +7,7 @@ import (
 	"flag"
 	"gitlab.schukai.com/oss/libraries/go/utilities/pathfinder"
 	"reflect"
+	"strconv"
 	"strings"
 )
 
@@ -37,7 +38,7 @@ func (s *Settings[C]) assignValues(c cmd[C]) {
 	flgs.Visit(func(f *flag.Flag) {
 
 		name := f.Name
-		value := f.Value.String()
+		stringValue := f.Value.String()
 
 		k, ok := c.tagMapping[name]
 		if !ok {
@@ -55,10 +56,48 @@ func (s *Settings[C]) assignValues(c cmd[C]) {
 		}
 
 		if q == nil {
-			q = reflect.New(reflect.TypeOf(q).Elem()).Interface()
+			s.errors = append(s.errors, newUnknownFlagError(name))
+			return
 		}
 
-		err = pathfinder.SetValue(&s.definitions, p, value)
+		typeOf := reflect.TypeOf(q)
+
+		switch typeOf.Kind() {
+		case reflect.String:
+			err = pathfinder.SetValue(&s.definitions, p, stringValue)
+		case reflect.Int:
+			intVar, err := strconv.Atoi(stringValue)
+			if err != nil {
+				s.errors = append(s.errors, err)
+				return
+			}
+			err = pathfinder.SetValue(&s.definitions, p, intVar)
+		case reflect.Bool:
+			boolVar, err := strconv.ParseBool(stringValue)
+			if err != nil {
+				s.errors = append(s.errors, err)
+				return
+			}
+			err = pathfinder.SetValue(&s.definitions, p, boolVar)
+		case reflect.Slice:
+
+			switch typeOf.Elem().Kind() {
+			case reflect.String:
+				qs := q.(StringFlags)
+				stringSliceValue := f.Value.(*StringFlags)
+				for _, v := range *stringSliceValue {
+					err = qs.Set(v)
+					if err != nil {
+						s.errors = append(s.errors, err)
+						return
+					}
+				}
+				err = pathfinder.SetValue(&s.definitions, p, qs)
+			default:
+				err = pathfinder.SetValue(&s.definitions, p, stringValue)
+			}
+
+		}
 
 		if err != nil {
 			s.errors = append(s.errors, err)
@@ -66,7 +105,7 @@ func (s *Settings[C]) assignValues(c cmd[C]) {
 
 		if c.proxyMapping[k] != "" {
 			p = c.proxyMapping[k]
-			s.mapping[p] = value
+			s.mapping[p] = stringValue
 		}
 
 	})
diff --git a/parse_test.go b/parse_test.go
new file mode 100644
index 0000000..36d7f9f
--- /dev/null
+++ b/parse_test.go
@@ -0,0 +1,28 @@
+// Copyright 2022 schukai GmbH
+// SPDX-License-Identifier: AGPL-3.0
+
+package xflags
+
+import (
+	"github.com/stretchr/testify/assert"
+	"testing"
+)
+
+type ParseMultiTestDefinition struct {
+	Values StringFlags `short:"x" long:"yyy" description:"Host to bind to" default:"localhost"`
+}
+
+func TestMultiParseIt(t *testing.T) {
+	setting := New("test", ParseMultiTestDefinition{})
+	setting.Parse([]string{"-x", "a1", "-x", "a2", "--yyy", "a3"})
+	setting.Execute()
+
+	if setting.HasErrors() {
+		for _, err := range setting.Errors() {
+			t.Log(err)
+		}
+	}
+
+	assert.False(t, setting.HasErrors())
+	assert.Equal(t, StringFlags{"a1", "a2", "a3"}, setting.definitions.Values)
+}
diff --git a/type.go b/type.go
index c03332a..b5602b6 100644
--- a/type.go
+++ b/type.go
@@ -1,3 +1,6 @@
+// Copyright 2023 schukai GmbH
+// SPDX-License-Identifier: AGPL-3.0
+
 package xflags
 
 import (
-- 
GitLab