cli
cli copied to clipboard
Is there anyway to support dynamic flag names?
Suppose I have a go web program named goweb
, and the subcommand web
will starts a web daemon.
Most importantly, it can have multiple instances at the same time, of course, they have different port numbers.
This is my /etc/goweb/config.conf
content:
[web]
path = "/var/lib/goweb/default"
port = 8000
[web.user1]
path = "/var/lib/goweb/user1"
port = 8001
[web.user2]
path = "/var/lib/goweb/user2"
port = 8002
What I expect is:
- When I use
goweb web --config /etc/goweb/config.conf
, the web service is based on path/var/lib/goweb/default
and port 8000. - When I use
goweb --user user1 web --config /etc/goweb/config.conf
, the web service is based on path/var/lib/goweb/user1
and port 8001. - Of course, when I use
goweb --user user2 web --config /etc/goweb/config.conf
, the web service is based on path/var/lib/goweb/user2
and port 8002. - And THE MOST WONDERFUL THING is, when I use
goweb --user user1 web --config /etc/goweb/config.conf --port 10000
, the web service is based on path/var/lib/goweb/user1
and port 10000!
This is my []cli.Flag
section:
portFlag := &cli.IntFlag{Name: "port"}
pathFlag := &cli.StringFlag{Name: "path"}
flags := []cli.Flag{
altsrc.NewStringFlag(pathFlag),
altsrc.NewIntFlag(portFlag),
&cli.StringFlag{Name: "config"},
}
And I changed the Aliases
of portFlag
in Before
function:
func(c *cli.Context) error {
var pathAlias string
var portAlias string
if len(user) == 0 {
pathAlias = "web.port"
portAlias = "web.port"
} else {
pathAlias = fmt.Sprint("web.", user, ".path")
portAlias = fmt.Sprint("web.", user, ".port")
}
pathFlag.Aliases = append(pathFlag.Aliases, pathAlias)
portFlag.Aliases = append(portFlag.Aliases, portAlias)
altsrc.InitInputSourceWithContext(flags, altsrc.NewTomlSourceFromFlagFunc("config"))
return nil
}
UNFORTUNATELY, IT DOESN'T WORK. SO, HOW CAN I DO FOR IT?
I don't think there's native support for what you're trying to do.
I've accomplished something similar by parsing CLI flags twice—once to get the non-dynamic flags (in your case, --user
) and then afterwards, create a new cli.App
with configuration based on the options parsed the first go around. Unfortunately, that was rather complex, and I'm not sure that the way I did it was necessarily the best way to do it, but it did work.
With the caveat that my use case is slightly different (the app creates additional flags dynamically) and that I have not migrated from v1 of the app, here is the code: https://github.com/rliebz/tusk/blob/524de887cdfea4e2c1499ce25765e803ca57aaf9/appcli/app.go#L93-L141