はじめに
「とぅーす!」(かわいい) nikkieです。
Pythonのargparseで書いたCLIをRustのCLAPで再実装してみようシリーズ(※小さな素振り群)の続編、2話連続放送です!
第1話はこちら
CLAPの素振り その1:オプション引数
今手元にあるのは位置引数で指定するバージョン
$ cargo run --quiet シオン 3 シオンシオンシオン
#[derive(Parser)] struct Cli { string: String, #[clap(default_value = "3")] number: usize, }
これをオプション引数で渡せるように変更します。
$ cargo run --quiet -- -s シオン -n 3 シオンシオンシオン
そのやり方はExampleにありました。
https://docs.rs/clap/latest/clap/#example
[#[arg(short, long)]]1!
#[derive(Parser)] struct Cli { #[arg(short)] string: String, #[arg(short, default_value = "3")] number: usize, }
[#[arg(short, long)]]との違いの1つはヘルプメッセージです(longを指定してよいと思います)
Options: -s <STRING> -n <NUMBER> [default: 3]
Options: -s, --string <STRING> -n, --number <NUMBER> [default: 3]
CLAPの素振り その2:サブコマンド
参考:Pythonのargparseの例はこちら
位置引数サブコマンドとオプション引数サブコマンドを実装してみます。
$ cargo run --quiet -- position 天才 5 天才天才天才天才天才 $ cargo run --quiet -- option -s おはぎ -n 2 おはぎおはぎ
参考にしたのは、cookbookのgitの例。
use clap::{Parser, Subcommand}; #[derive(Parser)] struct Cli { #[command(subcommand)] command: Commands, } #[derive(Subcommand)] enum Commands { Position { string: String, #[arg(default_value = "3")] number: usize, }, Option { #[arg(short, long)] string: String, #[arg(short, long, default_value = "3")] number: usize, }, }
コマンド自体の実装はこのように続きます
fn main() { let args = Cli::parse(); match args.command { Commands::Position { string, number } => { println!("{}", string.repeat(number)); } Commands::Option { string, number } => { println!("{}", string.repeat(number)); } } }
enumのコマンドに応じてパターンマッチ!
enumだから、args.commandはCommands::PositionまたはCommands::Optionなわけですね。
サブコマンドまでできちゃった!
終わりに
RustのCLAPで
- オプション引数も持つCLIが作れました!
[#arg(short, long)]
- サブコマンドも実装できました!
ここまでの3話で、argparseで書いているCLIの8割くらいは、RustのCLAPでも今の私は書けるのではという感触です(※まさに馬鹿の山です)。
コマンドライン引数のパーサはどう書けばいいか分かってきたので、内部の処理に移ったらアイデアがCLIという形にできて楽しそうです。
今回のソースコードはこちらです(引き続きテストもあります!)
-
デフォルト値は
#[clap(default_value = "3")]としていました。#[clap(...)]と#[arg(...)]は交換可能に思われます(さらに詳しくは宿題事項)↩