GoでCLIを作ろうとなった時には中身のロジックも勿論必要だけどユーザーが入力するインターフェースとなる部分が必要となる。
オプションをわたすようなものの場合は標準のflag
パッケージを使えば良いんだけど、commandを指定して機能をわけたいとかなった時には面倒になる。
このあたりのコマンドとかオプションをよしなにしてくれるのが今回紹介するurfave/cli
!!
urfave/cliとは?
A simple, fast, and fun package for building command line apps in Go
とある。
これを使うとコマンドラインからの引数や指定されたコマンドをうまい感じにハンドリングすることが出来る。
実績でいうとghqとかakamaiのcliとかもこのパッケージを使っている。
使い方
先に今回のサンプルコードをのせる。
package main import ( "fmt" "os" "github.com/urfave/cli" ) func main() { var ( suffix string ) app := cli.NewApp() app.Name = "Hello xxxx" app.Usage = "Make `Hello xxx` for arbitrary text" app.Version = "0.1.0" app.Flags = []cli.Flag{ cli.StringFlag{ Name: "suffix, s", Value: "!!!", Usage: "text after speaking something", Destination: &suffix, EnvVar: "SUFFIX", }, } app.Commands = []cli.Command{ { Name: "hello", Usage: "if use set -t or --text", Flags: []cli.Flag{ cli.StringFlag{ Name: "text, t", Value: "world", Usage: "hello xxx text", }, }, Action: func(c *cli.Context) error { fmt.Printf("Hello %s %s\n", c.String("text"), suffix) return nil }, }, } app.Run(os.Args) }
ビルドしたパッケージは--help
を押すとプログラム内のUsageやFlagsなどに応じてヘルプが表示される。
$ ./cli --help NAME: Hello xxxx - Make `Hello xxx` for arbitrary text USAGE: cli [global options] command [command options] [arguments...] VERSION: 0.1.0 COMMANDS: hello if use set -t or --text help, h Shows a list of commands or help for one command GLOBAL OPTIONS: --suffix value, -s value text after speaking something (default: "!!!") [$SUFFIX] --help, -h show help --version, -v print the version
実行自体は次のような感じになる。
$ ./cli hello Hello world !!!
解説
コードの細い部分を解説していく。
app := cli.NewApp() app.Name = "Hello xxxx" app.Usage = "Make `Hello xxx` for arbitrary text" app.Version = "0.1.0"
app := cli.NewApp()
によりCLIを作る時土台を作り、バージョンや名前とか使い方のようなメタ情報を追加出来る。
ここで指定した情報はヘルプ時に表示される。
app.Flags = []cli.Flag{ cli.StringFlag{ Name: "suffix, s", Value: "!!!", Usage: "text after speaking something", Destination: &suffix, EnvVar: "SUFFIX", }, }
ここのFlagsで指定されたものはglobal optionとして使われるもので、コマンド間で共有されるオプションとなる。
今回はDestinationで格納先を指定したがそれを指定しなかった時はGlobalString
やGlobalInt
などのように指定して参照することが出来る。
またEnvVar
を指定することで環境変数からもオプションの値を指定することもで出来る。
$ SUFFIX='(+_+)' ./cli hello Hello world (+_+)
app.Commands = []cli.Command{ { Name: "hello", Usage: "if use set -t or --text", Flags: []cli.Flag{ cli.StringFlag{ Name: "text, t", Value: "world", Usage: "hello xxx text", }, }, Action: func(c *cli.Context) error { fmt.Printf("Hello %s %s\n", c.String("text"), suffix) return nil }, }, }
この記載でコマンドを定義する。
そのコマンドの中でのオプションを定義したい時は Flags
をキーにしてglobal optionの時のような記載をする。
globalオプションと各コマンドのオプションを指定すると次のような実行になる。
$ ./cli --suffix hogehoge hello --text WORLD Hello WORLD hogehoge
まとめ
今回はGoでCLIが作りやすくなるurfave/cliを紹介した。
これ便利だ