[Go言語]codegangsta/cliで、サブコマンドとして外部コマンドをとれるようにしてみた
June 25, 2014
この記事はQiitaの記事をエクスポートしたものです。内容が古くなっている可能性があります。
codegangsta/cli
コンソールアプリを作るのに便利なライブラリ。 簡単に、オプションやサブコマンドを扱える。
サブコマンドとして外部コマンドをとる
git
コマンドのようにPATHの通っているところにgit-xxxx
みたいな実行可能ファイルがあると、git xxxx
みたいに、あたかもgit
コマンドのサブコマンドとして扱える。
codegangsta/cli
を使って同じようなことをしたい。
cli.App
にBefore
というフィールドがあり、サブコマンドを実行する前に実行できる関数を設定できる。
また、exec.LookPath
を使えば、PATHの通った実行可能ファイルの絶対パスを探すことができる。
この2つを使って、サブコマンドが実行される前に、プログラミング引数の2番目の値を実行可能ファイルとして探し出し、Before
でその外部コマンドを実行するような、cli.Command
を作成して、App
にサブコマンドとして登録してやればよい。
http://golang.org/pkg/os/exec/#LookPath
package main import ( "github.com/codegangsta/cli" "os" "os/exec" "strings" ) func main() { app := cli.NewApp() app.Before = func(c *cli.Context) error { args := c.Args() if len(args) <= 0 { return nil } subcommand := args.First() for _, c := range app.Commands { if c.HasName(subcommand) { return nil } } path, err := exec.LookPath(app.Name + "-" + subcommand) if err != nil { return err } app.Commands = append(app.Commands, cli.Command{ Name: subcommand, Action: func(c *cli.Context) { cmd := exec.Command(path, strings.Join(os.Args[2:], " ")) cmd.Stdout = os.Stdout cmd.Stdin = os.Stdin cmd.Stderr = os.Stderr cmd.Run() }, }) return nil } app.Run(os.Args) }
package main import ( "fmt" "github.com/codegangsta/cli" "os" ) func main() { app := cli.NewApp() app.Action = func(c *cli.Context) { args := c.Args() if len(args) <= 0 { fmt.Println("no params") return } fmt.Println(args.First()) } app.Run(os.Args) }
main.go
はメインとなるプログラムで以下の様にビルドするとする。
% go build -o main main.go
sub.go
はサブコマンドとして呼び出すコマンドで、以下の様にビルドするとする。
% go build -o main-sub sub.go
このようにすると、以下のようにsub.go
から作った実行可能ファイルを、main
のサブコマンドとして実行できる。
% ./main sub hogehoge
hogehoge