-
Notifications
You must be signed in to change notification settings - Fork 0
/
parser.go
124 lines (106 loc) · 3.51 KB
/
parser.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package dynflags
import (
"fmt"
"strings"
)
// Parse parses the CLI arguments and populates parsed and unknown groups.
func (df *DynFlags) Parse(args []string) error {
for i := 0; i < len(args); i++ {
arg := args[i]
// Extract the key and value
fullKey, value, err := df.extractKeyValue(arg, args, &i)
if err != nil {
// Handle unparseable arguments
if df.parseBehavior == ExitOnError {
return err
}
df.unparsedArgs = append(df.unparsedArgs, arg)
continue
}
// Validate and split the key
parentName, identifier, flagName, err := df.splitKey(fullKey)
if err != nil {
// Handle invalid keys
if df.parseBehavior == ExitOnError {
return err
}
df.unparsedArgs = append(df.unparsedArgs, arg)
continue
}
// Handle the flag
if err := df.handleFlag(parentName, identifier, flagName, value); err != nil {
if df.parseBehavior == ExitOnError {
return err
}
df.unparsedArgs = append(df.unparsedArgs, arg)
}
}
return nil
}
// extractKeyValue extracts the key and value from an argument.
func (df *DynFlags) extractKeyValue(arg string, args []string, index *int) (string, string, error) {
if !strings.HasPrefix(arg, "--") {
// Invalid argument format
return "", "", fmt.Errorf("invalid argument format: %s", arg)
}
arg = strings.TrimPrefix(arg, "--")
// Handle "--key=value" format
if strings.Contains(arg, "=") {
parts := strings.SplitN(arg, "=", 2)
return parts[0], parts[1], nil
}
// Handle "--key value" format
if *index+1 < len(args) && !strings.HasPrefix(args[*index+1], "--") {
*index++
return arg, args[*index], nil
}
// Missing value for the key
return "", "", fmt.Errorf("missing value for flag: --%s", arg)
}
// splitKey validates and splits a key into its components.
func (df *DynFlags) splitKey(fullKey string) (string, string, string, error) {
parts := strings.Split(fullKey, ".")
if len(parts) != 3 {
return "", "", "", fmt.Errorf("flag must follow the pattern: --<group>.<identifier>.<flag>")
}
return parts[0], parts[1], parts[2], nil
}
// handleFlag processes a known or unknown flag.
func (df *DynFlags) handleFlag(parentName, identifier, flagName, value string) error {
if parentGroup, exists := df.configGroups[parentName]; exists {
if flag := parentGroup.Lookup(flagName); flag != nil {
// Known flag
parsedGroup := df.createOrGetParsedGroup(parentGroup, identifier)
return df.setFlagValue(parsedGroup, flagName, flag, value)
}
}
// Unknown flag
return fmt.Errorf("unknown flag '%s' in group '%s'", flagName, parentName)
}
// setFlagValue sets the value of a known flag in the parsed group.
func (df *DynFlags) setFlagValue(parsedGroup *ParsedGroup, flagName string, flag *Flag, value string) error {
parsedValue, err := flag.value.Parse(value)
if err != nil {
return fmt.Errorf("failed to parse value for flag '%s': %v", flagName, err)
}
if err := flag.value.Set(parsedValue); err != nil {
return fmt.Errorf("failed to set value for flag '%s': %v", flagName, err)
}
parsedGroup.Values[flagName] = parsedValue
return nil
}
// createOrGetParsedGroup retrieves or initializes a parsed group.
func (df *DynFlags) createOrGetParsedGroup(parentGroup *ConfigGroup, identifier string) *ParsedGroup {
for _, group := range df.parsedGroups[parentGroup.Name] {
if group.Name == identifier {
return group
}
}
newGroup := &ParsedGroup{
Parent: parentGroup,
Name: identifier,
Values: make(map[string]interface{}),
}
df.parsedGroups[parentGroup.Name] = append(df.parsedGroups[parentGroup.Name], newGroup)
return newGroup
}