Help us understand the problem. What is going on with this article?

cobra / pflags でフラグをパースせずに args に残す

More than 1 year has passed since last update.

docker run のように,コマンドの引数に別のコマンドを引き渡して内部でいい感じに実行する系のやつ.

FlagSet.SetInterspersed

FlagSet.SetInterspersed を使う.

cmd := &cobra.Command{
    // snip.

    // 何らかのコマンドが渡されてることを保証する(not required だが,大抵は必要なはず)
    Args: cobra.MinimumNArgs(1),
}

// ref: https://godoc.org/github.com/spf13/pflag#FlagSet.SetInterspersed
// `Flags()` or `PersistentFlags()` はユースケースによっていい感じに使い分ける
cmd.Flags().SetInterspersed(false)

cobra(pflags)はデフォルトだと引数とオプションがごちゃごちゃ(interspersed)に渡ってきてもちゃんとパースされる.なのでこれを off にすることで,最初の flag じゃない引数より後ろは flag としてパースされなくなる.

実装は pflags の flag.go にあって,最初の引数が見つかった瞬間に flag のパースをやめるというもの.

日本語だと意味不明だけど,だいたい :point_down: みたいな挙動になる.

$ # intespersed: true (default)
$ # args == []string{"run", "qux", "quux"}
$ fooctl --verbose run --bar=42 qux --baz quux

$ # intespersed: false
$ # args == []string{"run", "--bar=42", "qux", "--baz", "quux"}
$ fooctl --verbose run --bar=42 qux --baz quux

SetInterspersed(false) でも,上の例だと run より後ろ(--verbose)は正しくパースされる.もちろん,未定義のフラグならエラーになる.

UnknownFlags?

cobra.CommandFParseErrWhitelist.UnknownFlags というものがあるが,これは単に未知のフラグを無視するようになるだけなので,今回は関係ない.

余談

docker runrunSetInterspersed(false) をしている.
https://github.com/docker/cli/blob/v18.09.0/cli/command/container/run.go#L52-L53

一方,ほぼ同一の interface を持つ kubectl run は interspersed が true のまま.
https://github.com/kubernetes/kubernetes/blob/v1.12.2/pkg/kubectl/cmd/run.go#L166-L193

pflgas は -- 以後の引数はパースしないので,そうやってコマンドを渡す.
yarn run とかとおなじ,わりと一般的な挙動ではある.

$ # args == []string{"curl", "http://example.com/ping"}
$ kubectl run ... --image buildpack-deps:18.04-curl -- curl http://example.com/ping

interspersed を切るかどうかは,その CLI がどんな UX を提供したいかによって判断すると良さそう.

wantedly
「シゴトでココロオドル」ためのビジネスSNS「Wantedly」の開発・運営をしています。
https://wantedlyinc.com/ja/presentations
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした