スキップしてメイン コンテンツに移動

structoptで踏み出すRustのCLIの第一歩

要所でRustが使われるシーンも多くなってきているように感じて、Rustのスキル向上の圧を自分の内側からも感じてる。

わかりやすいところから入ってわかった気になるのが好きなので、まずはCLIとしてどうできるのか、みたいなところを取っ掛かりにする。

つい先月のOreillyのニュースレターで次の記事とリポジトリが紹介されていた。

内容としては、GoとRust、どっちが本当に早いのか、ということで、機能的には同じことをする処理を2言語で書き分けて比較するという内容だった。
(Rustの方が早いことが多かったものの、ビルドはGoの方が早いという結果だったと記憶してる)

Rustを不必要にWeb APIのサーバーとして使うケースは趣味の範疇で見かけることも多いのだけど、ライブラリ群の成長の仕方を見てもまだまだMatureではないと思えるし、そうともすれば、組織として一定のRustへのこだわりがない限り採択はしないだろうから、もし仕事に使えることを念頭に置くならCLIの側面での使いっぷりを見ていく方が現実線だと個人的には思っている。
というわけで、そのCLIの方面での優れた例だと思ったので、サブコマンドの設定とヘルプの表示までを見てみた。

ソースコードはGitHubにある。 Rustは1.46で試した。

$ ./target/debug/rust-cli-play --help
rust-cli-play 0.1.0
rust-cli-play COMMAND [OPTIONS, ...]
USAGE:
   rust-cli-play <SUBCOMMAND>
FLAGS:
   -h, --help       Prints help information
   -V, --version    Prints version information
SUBCOMMANDS:
   help      Prints this message or the help of the given subcommand(s)
   status    Display recent status
$ ./target/debug/rust-cli-play status --help
rust-cli-play-status 0.1.0
Display recent status
USAGE:
   rust-cli-play status --verbose <verbose>
FLAGS:
   -h, --help       Prints help information
   -V, --version    Prints version information
OPTIONS:
   -v, --verbose <verbose>    Enable extended description output.
$ ./target/debug/rust-cli-play status -v hello
Your verbose arg value: hello


元リポジトリであるhashtrackを参考にしながら不要なライブラリを削ったのだけど、hashtrackではstructoptというライブラリを使用していた。(使用したのは0.3.17だけど、0.3の前後でBreaking Changesがあるらしい)

Rustでは、コマンド引数の取り扱い周りとしてclapが有名らしい。
実のところは目下clapにstructoptが統合される対応中のようだけど、ひとまずstructoptの強みは、clapがCLIらしい引数やヘルプの構成を作るのにメソッド等々をたくさん呼ぶ必要があるのを、structoptは次のようにさくっと済まして、内部でclapに対応するコードを自動生成するような作りの様子。

#[derive(StructOpt)]
#[structopt(about = "rust-cli-play COMMAND [OPTIONS, ...]")]
pub enum SubCommands {
   #[structopt(about = "Display recent status")]
   Status {
       #[structopt(short, long, help = "Enable extended description output.")]
       verbose: String,
   },
}

clap - crates.io: Rust Package Registry https://crates.io/crates/clap

ただ、実際に使ってみると、サブコマンドの説明文を出すために指定すべきなのがaboutなのかhelpなのか(aboutだった)がわからずIDE(VSCodeを使ってる)の補完も効かなかったことなどは地味に痛くて、ドキュメントも確かに書かれているのだけどまだ多少玄人向きな雰囲気があるなあと感じる。

この辺は多分慣れていくしかないのだけど。


それはそうと、hashtrackを手元のRust 1.37で試したら動かず、次のようなエラーに遭遇した。

error: `core::slice::<impl [T]>::len` is not yet stable as a const fn

幸い、Stack Overflowで既出だったからよかったけれど、このメッセージからRustのバージョンをあげないといけなかったんだと、わかるにはちょっと時間が必要な気がする。
Rustaceanならすぐにわかるのだろうか......。