⚙

Rust で対話的 CLI アプリのテンプレート作っておいた

に公開

へーい。新年明けたらしいですよ。まじで? もう年とりたくないので、何もめでたくないです。いつまでアラサーの見た目で通せるか……(アラフォーですがなにか)

さて、最近、CLI からコマンド入力を受け付けて動作確認しながら動かすようなプログラムを何個か作る機会があり、毎回似たようなコードを書いていたので、テンプレートとして整理しました。

用途に応じて 2 つのバージョンを用意しています。

共通部分

両テンプレートとも、src/cli.rs に再利用可能な CLI フレームワークを実装しています。

共通機能:

  • コマンドと引数のパース(shell-words を使用)
  • 終了コマンド(exit, quit, q)の処理
  • ターミナルカラー対応の出力ヘルパー(Printer)
  • 空行の自動スキップ

template_cli_tokio(非同期版)

非同期ランタイム Tokio を使用したバージョンです。rustyline-async を使って CLI 入力を非同期で処理しつつ、並行して他の処理(ネットワーク通信など)を実行できます。

https://github.com/nodamushi/template_cli_tokio/blob/main/src/main.rs

Pritner 経由で文字列を出力すると、ちゃんといい感じにユーザー入力と分離して表示してくれます。

println! や eprintln! を実行してしまうとユーザー入力と混じってしまうので注意。

template_cli_std(同期版)

標準ライブラリのみを使用したシンプルなバージョンです。rustyline を使ってブロッキング I/O で CLI 入力を処理します。

https://github.com/nodamushi/template_cli_std/blob/main/src/main.rs

Printer 経由では単に色がつくかどうかだけです。 tokio 版と異なり、非同期処理には対応していません。したがって、別に Printer を使わずに println! や eprintln! を直接呼び出しても良いです。

rustyline と並行処理の制約

先程も非同期処理に対応してないと書いたように、標準の rustyline は別スレッドからの出力に対応していません。そのため、template_cli_std ではシングルスレッドで readline → 処理 → readline というシンプルなループを採用しています。

一方、rustyline-async は SharedWriter を提供しており、複数のタスクから安全に出力できるため、template_cli_tokio では Printer を介して並行処理が可能です。

まとめ

対話的な CLI アプリケーションを作る際の定型的な処理をテンプレート化しました。シェル的なコマンド、引数入力をしたい CLI を作るならこれをコピっておけばよいでしょう。たぶん。

実際のプロジェクトでは、src/main.rs のサンプル実装を参考に、独自の処理を実装してください。

あぁ、ライセンス、著作権共に放棄(というのは日本では難しいので Unlicense か CC0)ですが、私個人の望みとしては 必ず nodamushi のGit履歴は削除 して欲しいです。

Discussion