0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Goで簡易なコマンドラインセレクタを作りました。

Posted at

作成したもの

RustでCLIのメモツールを作成する際、メモ一覧を表示して選択する機能が欲しいと考え、簡易なコマンドラインセレクタを作成いたしました。

本当はRustで作成したかったのですが、RatatuiなどのTUIツールをうまく使いこなすことができなかったため、Goで書くことにしました。

GoのTUIライブラリであるtviewは非常に使いやすく、簡単に作成することができました。

mattnさんのchoにとても影響を受けており、かなり簡易な作りにしてあります。
(mattnさんのchoはWindowsでも使えるため、高度な実装をしていると思います。)

使い方

slctは、標準入力から受け取った文字列を改行で区切り、それを選択肢として表示することを目的としていますので、単体で使うことはまずないと思います。
実際に使用する際は、lsやfindなどのコマンドとパイプラインを組み合わせて使用することを想定しています。

例えば、以下のように使用できます。

ls -a | sclt

asciicast

この処理はls -aで取得したファイル一覧をslctに渡し、選択したファイル名を標準出力に出力しています。

もう一つ挙げますと、以下のように使用できます。

cd $(ghq list --full-path | slct)

asciicast

この処理はghqというリポジトリ管理ツールで管理しているリポジトリ一覧をslctに渡し、選択したリポジトリのパスを標準出力に出力しています。
(非常に便利なため、筆者は愛用しています。)

実装内容

  1. tviewのNewTableを使用して、選択肢を表示するためのテーブルを作成します。
app := tview.NewApplication()

table := tview.NewTable().SetSelectable(true, false)
  1. 標準入力から行を読み取り、それぞれを新しいセルとして表に追加します。このプロセスは、標準入力からの入力がなくなるまで続けます。
scanner := bufio.NewScanner(os.Stdin)
row := 0

for scanner.Scan() {
	line := scanner.Text()
	cell := tview.NewTableCell(line).SetSelectable(true)
	table.SetCell(row, 0, cell)
	row++
}
  1. ユーザーが表のセルを選択したときの動作を定義します。選択されたセルのテキストが表示され、アプリケーションが停止します。
table.SetSelectedFunc(func(row, column int) {
	cell := table.GetCell(row, 0)
	app.Stop()
	fmt.Println(cell.Text)
})
  1. ユーザーが 'q' を押したときにアプリケーションが停止するように設定します。
app.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
	if event.Key() == tcell.KeyRune && event.Rune() == 'q' {
		app.Stop()
	}
	return event
})
  1. 選択されたスタイルを設定し、ステータスバーを作成し、それを表とともにフレックスレイアウトに追加します。
table.SetSelectedStyle(tcell.StyleDefault.Background(tcell.ColorWhite).Foreground(tcell.ColorBlack))

statusBar := tview.NewTextView().SetText("Press 'q' to exit").SetTextAlign(tview.AlignLeft).SetTextColor(tcell.ColorYellow)

flex := tview.NewFlex().SetDirection(tview.FlexRow).AddItem(table, 0, 1, true).AddItem(statusBar, 1, 0, false)
  1. アプリケーションを実行します。
if err := app.SetRoot(flex, true).Run(); err != nil {
	fmt.Fprintf(os.Stderr, "Error running application: %v\n", err)
	os.Exit(1)
}

今後の予定

考えられる改修点をいくつか挙げますと、以下のようなものがあります。

  • テストの追加
  • インクリメンタルサーチの追加
  • config.yamlで設定を変更できるようにする
  • 複数選択に対応する

テストの追加は早めに行う必要があると考えており、config.yamlでの設定変更も文字に色をつけるだけでも実装しようと思っています。

ただ、インクリメンタルサーチと複数選択に関しては、そこまでフォローするくらいなら大人しくpecoを使った方が良いかもしれません。

時間があるときに文字色だけでも変更できるように実装しておきたいと思います。

おわりに

メモツールを作成する前段階が完了しました(長かったです...)ので、次はメモツールの作成に取り掛かりたいと思います。

GoでCLIツールを作成するのは非常に楽しいです。
また、自作ツールがかなり便利で使用頻度が高いのも楽しいです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?