cobraで引数不要なフラグを受け取る
あらすじ及び結論
-h
とか--list
とか、そういうやつが欲しかった。ふつのコマンドでよく使うし標準で専用のメソッドなりがあるのかと思ったがそんなことはない?見つけたのは以下のやつ。ちょっと古い||もっといい方法があるのかもしれませんが
rootCmd.BoolVarP(&verbose, "verbose", "v", false, "verbose output")
このようにBoolVarP
して成否判定やってみてけろ、ということらしい。たとえば今回は「viper
で設定ファイルにある宛先メールアドレスをリストでほしい」という自作コマンドの要望上で欲しかった機能で、サブコマンドconfig
を使って次のようにして表示したかったのです。ショートフラグ非対応なのは趣味です
<メインのコマンド> config --sendto
こうなった
サブコマンドのgoファイル。cobra add <サブコマンド名>
で生成されたやつ
package cmd import ( "fmt" "github.com/spf13/cobra" "github.com/spf13/viper" ) var sendtoFlag bool var configCmd = &cobra.Command{ Use: "config", Short: "設定ファイルでよく参照しそうな中身を表示", Long: `設定ファイルでよく参照しそうなものを表示します。 --sendto 送信先のメールアドレスいちらん `, Run: func(cmd *cobra.Command, args []string) { mails, _ := cmd.Flags().GetBool("sendto") if mails && len(cmd.Flags().Args()) == 0 { // `--sendto`以外は不要 for _, address := range viper.GetStringSlice("sendto") { fmt.Println(address) } } else { fmt.Printf("不正な引数もしくはオプションがあります。\n Args: %v\n", cmd.Flags().Args()) } }, } func init() { rootCmd.AddCommand(configCmd) configCmd.Flags().BoolVarP(&sendtoFlag, "sendto", "", false, "送信先のメールアドレス") }
yamlはこんなのとする。同じ階層にあるのと名前は以下のroot.go
参照。要らん設定たくさんあるけど省くのもめんどくさかったので載せる。記事内のsnippetでは当然sendto
しか使ってないです
applicationName: "ニャー" debug: false user: name: "this is fuckin awesome name" age: 34882349 sendto: [aaa@mail.domain, bbb@mail2.gandum, ccc@koikeya.umai]
root.go
載せる意味あんまなさそうだけどメモとして一部必要そうなところを置いておく。viper
すらも初めて触ったんですがそもそもgoの文法とかよくわかってないので使いやすいのかどうか判断がつきましぇん
. . . type Config struct { User User `yaml:user` ApplicationName string `yaml:applicationName` Debug bool `yaml:debug` SendTo []string `yaml:sendto` } type User struct { Name string `yaml:"name"` Age int `yaml:"age"` } var config Config // 読み込む設定ファイル。定義してない(適当にネット上のソースをコピペしたなのでなんで定義されてないのか知らない) var cfgFile string . . . func init() { cobra.OnInitialize(initConfig) // bra bra bra... } func initConfig() { if cfgFile != "" { // Use config file from the flag. viper.SetConfigFile(cfgFile) } else { viper.AddConfigPath(".") viper.SetConfigName("cfg") viper.SetConfigType("yaml") // もしかして明示的に書く必要ないかもしれない } if err := viper.ReadInConfig(); err != nil { fmt.Println("Can't read config:", err) os.Exit(1) } if err := viper.Unmarshal(&config); err != nil { fmt.Println("config file Unmarshal error") fmt.Println(err) os.Exit(1) } }
試してみるよ
$ go run main.go config --sendto aaa@mail.domain bbb@mail2.gandum ccc@koikeya.umai $ go run main.go config --sendto 193838795237984 不正な引数もしくはオプションがあります。 Args: [193838795237984] $ go run main.go config sendto 不正な引数もしくはオプションがあります。 Args: [sendto] $ go run main.go config --send2 nya- Error: unknown flag: --send2 Usage: cobra_practice config [flags] Flags: -h, --help help for config --sendto 送信先のメールアドレス exit status 1
ちゃんと--sendto
とロングオプションのみつけたときだけ取れてますねぇ。CLIツールとかCLI用ライブラリとかのお作法って知らないんですがどのライブラリもこんな感じなのかな。