Closed4
urfave/cli でグローバルオプションをコマンドオプションの場所に書きたい
zetamatta/vo: Visual-studio client for command-line Operationという、Visual Studio のビルド機能をコマンドラインから使うツールを開発・利用している。たとえば、Visual Studio 2015 でビルドしたい時、
vo -2015 build
なんて感じにグローバルオプションを指定してすれば、Visual Studio 2015 の実行ファイル devenv.com を探し出して、カレントディレクトリにあるソリューションファイルをビルドしてくれる。だが、これを
vo build -2015
と指定するのもアリとしたい(というか、このように誤って書いてしまうから)。が、サブコマンドを実装するパッケージ urfave/cli: A simple, fast, and fun package for building command line apps in Goは、グローバルオプションとサブコマンド用オプションを別々に管理しているので、両方どっちでもいけるという指定は標準機能できないみたい。さて、どうするか…
検証プログラム書いてみた。
package main
import (
"fmt"
"os"
"github.com/urfave/cli/v2"
)
func main() {
app := &cli.App{
Usage: "Test for urfave/cli/v2",
Flags: []cli.Flag{
&cli.BoolFlag{Name: "x", Usage: "global x-option"},
},
Commands: []*cli.Command{
{
Name: "sub",
Usage: "sub command",
Flags: []cli.Flag{
&cli.BoolFlag{Name: "x", Usage: "subcommands x-option"},
},
Action: func(c *cli.Context) error {
fmt.Printf("x-value=%v\n", c.Bool("x"))
return nil
},
},
},
}
app.Run(os.Args)
}
$ foo sub
x-value=false
$ foo sub -x
x-value=true
$ foo -x sub
x-value=false
$ foo -x sub -x
x-value=true
うーん、Bool の場合、サブコマンド側のオプションを省略しても、常に上書きされてしまうかー。そーかー。うーん、うまい逃げ道ないかなー
Flag に Destination というフィールドがあった。
package main
import (
"fmt"
"os"
"github.com/urfave/cli/v2"
)
func main() {
globalX := false
commandX := false
app := &cli.App{
Usage: "Test for urfave/cli/v2",
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "x",
Usage: "global x-option",
Destination: &globalX,
},
},
Commands: []*cli.Command{
{
Name: "sub",
Usage: "sub command",
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "x",
Usage: "subcommands x-option",
Destination: &commandX,
},
},
Action: func(c *cli.Context) error {
fmt.Printf("x-value=%v\n", globalX || commandX)
return nil
},
},
},
}
app.Run(os.Args)
}
$ foo sub
x-value=false
$ foo sub -x
x-value=true
$ foo -x sub
x-value=true
$ foo -x sub -x
x-value=true
まぁ、これでゆくかな?
対応例:
このスクラップは2020/12/24にクローズされました