🦀
Rust 小ネタ: `clap::Parser` をモジュール内に隠蔽する
こんにちは。Fairy Devices株式会社 となんらかの関わりがある nogiro (Twitter (現 Twitter): @nogiro_iota
) です。Fairy Devices の Slack にある、Rust 雑談チャンネルで話に出た小ネタを共有します。
clap
で derive 機能を使ってコマンドライン引数を解析するとき、clap::Parser::parse()
を呼ぶファイルで use clap::Parser as _;
などして、トレイトをインポートする必要があります [1]。fn main()
で use
しがちですが、引数解析のための型を定義しているモジュールで、ラップした関数を提供しているクレートを見かけてかしこいなと思ったので共有します。
すごく嬉しいわけではないけどちょっと嬉しい、という小ネタです。
やりがちな実装
Rust でコマンドラインライン引数を解析するとき、以下のように引数解析用の型 (Args
) に clap::Parser
を derive して、main 関数で <Args as clap::Parser>::parse()
を呼ぶ、という実装をやりがちです。
src/args.rs
use clap::{ArgAction, Parser};
#[derive(Parser, Debug)]
pub struct Args {
#[arg(short, long, action = ArgAction::Count)]
pub verbose: u8,
}
src/main.rs
mod args;
use clap::Parser as _;
use crate::args::Args;
fn main() {
let args = Args::parse();
println!("args = {args:?}");
todo!()
}
以下を実行して、(vim のところで) 上記のファイルを書けば試せるはずです
cargo new --name clap-capsule ~/tmp/rust-sandbox-clap-capsule
cd "$_"
cargo add --features clap/derive clap
vim src/args.rs src/main.rs
cargo run -- -vv
隠蔽する
Args
に以下のようなメソッドを実装します。
src/args.rs
// ...
impl Args {
pub fn parse() -> Self {
<Self as Parser>::parse()
}
}
そうすると main.rs
は以下のように書き換えることができて、clap::Parser
への依存を隠すことができます。
src/main.rs
mod args;
use crate::args::Args;
fn main() {
let args = Args::parse();
println!("args = {args:?}");
todo!()
}
なにが嬉しいのか?
いろいろなところでバラバラにインポートしなくて良くなるので、少しだけ凝集度が上がって読みやすくなります。
また、clap::Parser
以外の他のトレイトに適用すると、同じような効果が得られることが期待されます。
終わり。
Discussion