「実践Rustプログラミング入門」「プログラムをつくる」p.152から。
2日目の続き。
p.152 deriveマクロを使った記述方式
use clap::Clap;
# [derive(Clap, Debug)]
# [clap(
name = "My RPN program",
version = "1.0.0",
author = "kencoba",
about = "Super awesome sample RPN calculator"
)]
struct Opts {
/// Sets the level of verbosity
#[clap(short, long)]
verbose: bool,
/// Formulas written in RPN
#[clap(name = "FILE")]
formula_file: Option<String>,
}
fn main() {
let opts = Opts::parse();
match opts.formula_file {
Some(file) => println!("File specified: {}", file),
None => println!("No file specified."),
}
println!("Is verbosity specified?: {}", opts.verbose);
}
実行する。
PS samplecli> cargo run
Compiling samplecli v0.1.0 (samplecli)
Finished dev [unoptimized + debuginfo] target(s) in 1.58s
Running `target\debug\samplecli.exe`
No file specified.
Is verbosity specified?: false
PS samplecli>
これが引数なしの動作。formula_fileの指定がない旨のメッセージが出る。
PS samplecli> cargo run -- -v input.txt
Finished dev [unoptimized + debuginfo] target(s) in 0.10s
Running `target\debug\samplecli.exe -v input.txt`
File specified: input.txt
Is verbosity specified?: true
trueが返される。-v
がverbose
のオプションなのはデフォルトで組み込まれているということ?
PS samplecli> cargo run -- -v -d input.txt
Finished dev [unoptimized + debuginfo] target(s) in 0.11s
Running `target\debug\samplecli.exe -v -d input.txt`
error: Found argument '-d' which wasn't expected, or isn't valid in this context
If you tried to supply `-d` as a PATTERN use `-- -d`
USAGE:
samplecli.exe [FLAGS] [FILE]
For more information try --help
error: process didn't exit successfully: `target\debug\samplecli.exe -v -d input.txt` (exit code: 2)
-d
は定義していないわけだし、当然エラーになる。
p.153 第一引数に数値を与えられるようにする。
NUMBERの指定を追加する。
use clap::Clap;
# [derive(Clap, Debug)]
# [clap(
name = "My RPN program",
version = "1.0.0",
author = "kencoba",
about = "Super awesome sample RPN calculator"
)]
struct Opts {
/// Sets the level of verbosity
#[clap(short, long)]
verbose: bool,
/// Number
#[clap(name = "NUMBER")]
num: i32,
/// Formulas written in RPN
#[clap(name = "FILE")]
formula_file: Option<String>,
}
fn main() {
let opts = Opts::parse();
match opts.formula_file {
Some(file) => println!("File specified: {}", file),
None => println!("No file specified."),
}
println!("Is verbosity specified?: {}", opts.verbose);
}
引数を-v input.txt
として実行する。
PS samplecli> cargo run -- -v input.txt
Compiling samplecli v0.1.0 (samplecli)
Finished dev [unoptimized + debuginfo] target(s) in 1.17s
Running `target\debug\samplecli.exe -v input.txt`
error: Invalid value for '<NUMBER>': invalid digit found in stringerror: process didn't exit successfully: `target\debug\samplecli.exe -v input.txt` (exit code: 2)
最初の引数が数値、ということなのでエラー。
PS samplecli> cargo run -- 42 -v input.txt
Finished dev [unoptimized + debuginfo] target(s) in 0.09s
Running `target\debug\samplecli.exe 42 -v input.txt`
File specified: input.txt
Is verbosity specified?: true
先頭が数値であればOKとなる。
p.154 デフォルト値を指定する。
こんな書き方をしたら・・・
/// Formulas written in RPN
#[clap(name = "FILE", default_value = "default.txt")]
formula_file: Option<String>,
cargo run
で、こんなエラーが出た。VSCode上ではdefault_value
の箇所で"default_value is meaningless for Option"と出ている。default_value
を指定するなら、型がOption<String>
はおかしい、ということ。
PS samplecli> cargo run
Compiling samplecli v0.1.0 (samplecli)
error: default_value is meaningless for Option
--> src\main.rs:20:27
|
20 | #[clap(name = "FILE", default_value = "default.txt")]
| ^^^^^^^^^^^^^
error: aborting due to previous error
error: could not compile `samplecli`.
To learn more, run the command again with --verbose.
いい感じ。
あらためて、コンパイルが通るコードを示す。書籍p.154に書かれている修正だけはダメで、実際にはmain()の中でOptionからファイル名を取得していた箇所も修正が必要。
use clap::Clap;
# [derive(Clap, Debug)]
# [clap(
name = "My RPN program",
version = "1.0.0",
author = "kencoba",
about = "Super awesome sample RPN calculator"
)]
struct Opts {
/// Sets the level of verbosity
#[clap(short, long)]
verbose: bool,
/// Number
#[clap(name = "NUMBER")]
num: i32,
/// Formulas written in RPN
#[clap(name = "FILE", default_value = "default.txt")]
formula_file: String,
}
fn main() {
let opts = Opts::parse();
println!("Number specified: {}", opts.num); // 追加
println!("File specified: {}", opts.formula_file); // ファイル名取得処理修正
println!("Is verbosity specified?: {}", opts.verbose);
}
実行する。
PS samplecli> cargo run
Compiling samplecli v0.1.0 (samplecli)
Finished dev [unoptimized + debuginfo] target(s) in 0.90s
Running `target\debug\samplecli.exe`
error: The following required arguments were not provided:
<NUMBER>
USAGE:
samplecli.exe <NUMBER> <FILE>
For more information try --help
error: process didn't exit successfully: `target\debug\samplecli.exe` (exit code: 2)
必須引数が指定されない場合は、そもそもUSAGEが出る。
PS samplecli> cargo run -- 42
Finished dev [unoptimized + debuginfo] target(s) in 0.11s
Running `target\debug\samplecli.exe 42`
Number specified: 42
File specified: default.txt
Is verbosity specified?: false
期待通り。
振り返り
1.clap便利。引数処理がここまで簡単確実にできると、コマンド開発が大変はかどる。
2. メッセージを日本語化するにはどうしたら良いか(要調査)。