API叩いて云々するようなアプリを作りたいと思うと、やっぱりサブコマンドを実装したCLIツールを
自作したいと思うのはエンジニアの嵯峨ですよね?w
いろいろと調べていたらmitchellh/cli(以下cliパッケージ)という”Go CLI Library”を発見したので触ってみました。
このcliパッケージですが、Packer・Serf・Consul・Vault・Terraform・Nomadなどで使用されているそうです。
使い方
ライブラリのインストール
$ go get github.com/mitchellh/cli
書き方
cliパッケージにはtype Command interface {}
というインターフェースが用意されており、
Help() string
・Run(args []string) int
・Synopsis() string
のメソッドを
実装することで簡単に使用できます。
とりあえず、ここではisay
という名前で以下のようなアプリを作成します。
$ ./isay --help
Usage: isay [--version] [--help] <command> [<args>]
Available commands are:
goodbye Say Hello.
hello Say Goodbye.
実装編
とりあえず、main.go
という名前で以下のコードを記述してみます。
package main
import (
"github.com/mitchellh/cli"
"os"
"fmt"
)
// helloサブコマンドの実装
type HelloCommand struct {}
func (c *HelloCommand) Run(args []string) int {
fmt.Println("You say Hello, I say Goodbye.")
return 0
}
func (c *HelloCommand) Synopsis() string {
return "Say Goodbye."
}
func (c *HelloCommand) Help() string {
return "Usage: isay hello"
}
// goodbye サブコマンドの実装
type GoodbyeCommand struct {}
func (c *GoodbyeCommand) Run(args []string) int {
fmt.Println("You say Goodbye, I say Hello.")
return 0
}
func (c *GoodbyeCommand) Synopsis() string {
return "Say Hello."
}
func (c *GoodbyeCommand) Help() string {
return "Usage: isay goodbye"
}
func main() {
// コマンド(アプリ)名とバージョン定義
c := cli.NewCLI("isay", "0.0.1")
// サブコマンドの名前と実装の関連付け
c.Args = os.Args[1:]
c.Commands = map[string]cli.CommandFactory{
"hello": func() (cli.Command, error) {
return &HelloCommand{}, nil
},
"goodbye": func() (cli.Command, error) {
return &GoodbyeCommand{}, nil
},
}
// サブコマンドの実行と終了処理
exitStatus, err := c.Run()
if err != nil {
fmt.Println(err)
}
os.Exit(exitStatus)
}
ビルド
$ go build -o isay main.go
動作確認と解説
とりあえず、実行してみましょう。
$ ./isay hello
You say Hello, I say Goodbye.
$ ./isay goodbye
You say Goodbye, I say Hello.
func Run(args []string) int {}
で実装した結果が表示されましたね。
続いて、何も指定せず実行してみます。
$ ./isay
するとUsageが表示されます。なお./isay --help
も同様の出力を得る事ができます。
Usage: isay [--version] [--help] <command> [<args>]
Available commands are:
goodbye Say Hello.
hello Say Goodbye.
このあたりは、cli
パッケージが自動生成してくれており、コマンド名及び--version
の値は
cli.NewCLI("isay", "0.0.1")
で指定したものになります。
$ ./isay --version
0.0.1
なお、Available commands are:
の部分についてはfunc Synopsis() string {}
の実装(返り値)が表示されます。
最後に、func Help() string {}
について。お気づきかもしれませんがサブコマンドの--help
オプションの結果として表示することができます。
./isay hello --help
Usage: isay hello
$ ./isay goodbye --help
Usage: isay goodbye
コードを貼ると大分記事が長くなってしまうので今回はここまで。
触ってみて非常に便利だなと思いつつ、コマンド(アプリ)名とバージョンがハードコーティングになるところはうまくやりくりしたいですね。
ちなみに参考にpackerのソースをほんの少しだけ読みかじってみましたが、Help()
の部分はハードコーティングされていました。
参考
以上。