Rustのコマンドラインパーサーclapにて、Arg
のmin_values()
やtakes_value()
が見当たらずにnot foundエラーになったので備忘録。
はじめに
Rustの練習帳というオライリー本のサンプルコードが最近のclapのバージョンだと動かなかったのをきっかけに、clapのAPI変遷を調べたのでその記録メモです。
# 作業バージョン clap = "4.5.16"
clapのmin_valuesやtakes_valueが見当たらない
問題
問題のコードはこちら:
use clap::{Arg, Command}; fn main() { let matchs = Command::new("echors") .version("0.1.0") .author("BioErrorLog") .about("Rust echo") .arg( Arg::new("text") .value_name("TEXT") .help("Input text") .required(true) .min_value(1), ) .arg( Arg::new("omit_newline") .short('n') .help("Do not print newline") .takes_value(false), ) .get_matches(); println!("{:#?}", matchs) }
こちらを実行する下記のようなエラーが発生します。
error[E0599]: no method named `min_value` found for struct `Arg` in the current scope --> src/main.rs:13:18 | 9 | / Arg::new("text") 10 | | .value_name("TEXT") 11 | | .help("Input text") 12 | | .required(true) 13 | | .min_value(1), | | -^^^^^^^^^ method not found in `Arg` | |_________________| | error[E0599]: no method named `takes_value` found for struct `Arg` in the current scope --> src/main.rs:19:18 | 16 | / Arg::new("omit_newline") 17 | | .short('n') 18 | | .help("Do not print newline") 19 | | .takes_value(false), | | -^^^^^^^^^^^ method not found in `Arg` | |_________________| | For more information about this error, try `rustc --explain E0599`. error: could not compile `echors` (bin "echors") due to 2 previous errors
Arg
のmin_values()
とtakes_value()
に関するシンプルなnot foundエラーですね。
解決策
代わりにnum_args()を使います。
num_args()
に範囲指定を渡すことで、引数の数の条件を設定できます。
use clap::{Arg, Command}; fn main() { let matchs = Command::new("echors") .version("0.1.0") .author("BioErrorLog") .about("Rust echo") .arg( Arg::new("text") .value_name("TEXT") .help("Input text") .required(true) .num_args(1..), // 引数1個以上 ) .arg( Arg::new("omit_newline") .short('n') .help("Do not print newline") .num_args(0), // 引数なし ) .get_matches(); println!("{:#?}", matchs) }
num_args(0)
のように引数の数を直接指定することもできますし、num_args(1..)
のように範囲を指定することも可能です。
範囲はRustでの通常の範囲構文と同じく、
<start>..
:<start>
以上..<end>
:<end>
未満 (排他)<start>..<end>
:<start>
以上<end>
未満 (排他)<start>..=<end>
:<start>
以上<end>
以下 (含有)
のように書きます。
背景
CHANGELOGを覗いてみると、clapのversion 4.0.0にて変更が入ったことがわかります。
元々clapには引数を指定するための方法が複数存在していました。
- Arg::multiple_values(true)
- Arg::number_of_values(4)
- Arg::min_values(2)
- Arg::max_values(20)
- Arg::takes_value(true)
4.0.0からは、これら引数の数を指定する場合にはnum_args()
一本で済むようになった、ということです。
確かにこっちの方がシンプルで良いですね。
この辺りの背景議論は下記のissueで確認することができます。
Simplify the `takes_value` API (range-based `takes_values`) · Issue #2688 · clap-rs/clap · GitHub
おわりに
以上、clapのtakes_value系APIがnot foundエラーになる問題の対処法メモでした。
どなたかの参考になれば幸いです。
[関連記事]
参考
clap/CHANGELOG.md at master · clap-rs/clap · GitHub
Simplify the `takes_value` API (range-based `takes_values`) · Issue #2688 · clap-rs/clap · GitHub