Reputation: 233
I'm trying to create command lines like the following
myapp --config=config1.yaml --start=step1 --start=step2 --config=config2.yamp --start=step1
There are multipe --start flags, each of it corresponds with the previous --config flag. Is there any cli framework that supports flags like this? Can this be done with the standard go flags package
Upvotes: 2
Views: 38
Reputation: 4490
Can this be done with the standard go flags package?
There is no default behavior, but you can implement it yourself. For example, you can create custom implementation of flag.Value interface to Parse flags (use FlagSet) with "position" in args and than define which --start
flags belong to --config
flag.
var (
// flag position
fPosition = 1
)
type FlagWithPosition struct {
Position int
Val string
}
type FlagsWithPosition []FlagWithPosition
func (s *FlagsWithPosition) String() string {
return fmt.Sprintf("%v", *s)
}
func (s *FlagsWithPosition) Set(value string) error {
value = strings.TrimSpace(value)
if value == "" {
return nil
}
*s = append(*s, FlagWithPosition{
Position: fPosition, //position in args
Val: value,
})
fPosition++ // increment position in args
return nil
}
func main() {
var (
configs FlagsWithPosition
steps FlagsWithPosition
)
// Use FlagSet
fs := flag.NewFlagSet("ExampleValue", flag.ExitOnError)
fs.Var(&configs, "config", "configurations")
fs.Var(&steps, "start", "steps")
// prepare args
args := strings.Split("--config=config1.yaml --start=step1 --start=step2 --config=config2.yamp --start=step1", " ")
// parse flags using FlagSet
_ = fs.Parse(args)
fmt.Println(configs)
fmt.Println(steps)
fmt.Println(getConfigsWithSteps(configs, steps)) // map[config1.yaml:[step1 step2] config2.yamp:[step1]]
}
// getConfigsWithSteps - EXAMPLE
func getConfigsWithSteps(configs, steps FlagsWithPosition) map[string][]string {
configsWithSteps := make(map[string][]string, len(configs))
for i, config := range configs {
var (
nextPosition = -1
)
if len(configs) > i+1 {
nextPosition = configs[i+1].Position
}
for j, step := range steps {
if nextPosition > -1 && step.Position >= nextPosition {
steps = steps[j:]
break
}
configsWithSteps[config.Val] = append(configsWithSteps[config.Val], step.Val)
}
}
return configsWithSteps
}
Upvotes: 0