go-promptを使ったリッチなコマンドラインツールの作り方

先週go-promptというGoの端末制御ライブラリを公開しました。

> c-bata/go-prompt: A library for building powerful interactive prompts inspired by python-prompt-toolkit, making it easier to build cross-platform command line tools using Go.
> https://github.com/c-bata/go-prompt

このライブラリを使うと [kube-prompt](https://github.com/c-bata/kube-prompt) のような強力な補完を持つツールが簡単に開発できます。
この記事ではgo-promptの使い方について解説していきます

## Getting Started

それではさっそくgo-promptを使ってリッチなコマンドラインツールを作ってみましょう。

#### Download

```bash
$ go get github.com/c-bata/go-prompt
```

#### 簡単なサンプル

```go
package main

import (
	"fmt"

	"github.com/c-bata/go-prompt"
)

func completer(in prompt.Document) []prompt.Suggest {
	s := []prompt.Suggest{
		{Text: "users", Description: "Store the username and age"},
		{Text: "articles", Description: "Store the article text posted by user"},
		{Text: "comments", Description: "Store the text commented to articles"},
		{Text: "groups", Description: "Combine users with specific rules"},
	}
	return prompt.FilterHasPrefix(s, in.GetWordBeforeCursor(), true)
}

func main() {
	in := prompt.Input(">>> ", completer, prompt.OptionTitle("sql-prompt"))
	fmt.Println("Your input: " + in)
}
```

それでは実行してみましょう

![simple-input.gif](https://qiita-image-store.s3.amazonaws.com/0/29989/a94f96ec-7525-ed00-88ce-4e2b50c858af.gif)

上のプログラムでは、例えば 「a」と入力すると `completer` 関数が返す `prompt.Suggest` の中で「a」から始まるアイテムの一覧を返します。
`prompt.Input` 関数はユーザが入力した文字列をそのまま返してくれます。

## オプションでカスタマイズする

go-promptには様々なオプションが用意されています。
詳細は [GoDoc c-bata/go-prompt](https://godoc.org/github.com/c-bata/go-prompt#Option) にまとまっていますが、色に関するオプションは沢山あり、紛らわしいので↓の画像を参考にしてください。

![prompt-options](https://raw.githubusercontent.com/c-bata/assets/master/go-prompt/prompt-options.png)

それでは実際にoptionをカスタマイズしてみましょう。

```go
package main

import (
	"fmt"

	"github.com/c-bata/go-prompt"
)

func completer(in prompt.Document) []prompt.Suggest {
	s := []prompt.Suggest{
		{Text: "users", Description: "Store the username and age"},
		{Text: "articles", Description: "Store the article text posted by user"},
		{Text: "comments", Description: "Store the text commented to articles"},
		{Text: "groups", Description: "Combine users with specific rules"},
	}
	return prompt.FilterHasPrefix(s, in.GetWordBeforeCursor(), true)
}

func main() {
	in := prompt.Input(">>> ", completer,
		prompt.OptionTitle("sql-prompt"),  // Terminalのタイトルを変更
		prompt.OptionHistory([]string{"SELECT * FROM users;"}),  // 歴史を予め追加(本来はlogファイルみたいなところに書き出しておいて、起動時に読み込んだりします)
		prompt.OptionPrefixTextColor(prompt.Yellow),  // Prefix(ここでは >>>) の色を黄色に変更
		prompt.OptionPreviewSuggestionTextColor(prompt.Blue),
		prompt.OptionSelectedSuggestionBGColor(prompt.LightGray),
		prompt.OptionSuggestionBGColor(prompt.DarkGray))
	fmt.Println("Your input: " + in)
}
```

実行すると次のようになります。

![customized.gif](https://qiita-image-store.s3.amazonaws.com/0/29989/a5febb44-3f1a-a0e3-dcdb-c69d4dd2be27.gif)


## kube-prompt

実際にkube-promptというKubernetesのクライアントも作成しました。
go-promptを使って何かツールを書く際は、kube-promptの実装も参考にしてみてください。

> c-bata/kube-prompt: An interactive kubernetes client featuring auto-complete using go-prompt.
> https://github.com/c-bata/kube-prompt


## おわりに

キーバインドのカスタマイズなど、今回解説していない機能もありますが、これだけでも強力な補完が可能なコマンドラインツールの開発ができます。

ぜひ活用してみてください。