Closed4

urfave/cli でグローバルオプションをコマンドオプションの場所に書きたい

hymkorhymkor

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は、グローバルオプションとサブコマンド用オプションを別々に管理しているので、両方どっちでもいけるという指定は標準機能できないみたい。さて、どうするか…

hymkorhymkor

検証プログラム書いてみた。

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 の場合、サブコマンド側のオプションを省略しても、常に上書きされてしまうかー。そーかー。うーん、うまい逃げ道ないかなー

hymkorhymkor

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にクローズされました