codegangsta/cli
コンソールアプリを作るのに便利なライブラリ。
簡単に、オプションやサブコマンドを扱える。
サブコマンドとして外部コマンドをとる
git
コマンドのようにPATHの通っているところにgit-xxxx
みたいな実行可能ファイルがあると、git xxxx
みたいに、あたかもgit
コマンドのサブコマンドとして扱える。
codegangsta/cli
を使って同じようなことをしたい。
cli.App
にBefore
というフィールドがあり、サブコマンドを実行する前に実行できる関数を設定できる。
また、exec.LookPath
を使えば、PATHの通った実行可能ファイルの絶対パスを探すことができる。
この2つを使って、サブコマンドが実行される前に、プログラミング引数の2番目の値を実行可能ファイルとして探し出し、Before
でその外部コマンドを実行するような、cli.Command
を作成して、App
にサブコマンドとして登録してやればよい。
main.go
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)
}
sub.go
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