0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

「実践Rustプログラミング入門」に入門する(5日目)

Last updated at Posted at 2020-09-05

「実践Rustプログラミング入門」「プログラムをつくる」p.152から。
2日目の続き。

p.152 deriveマクロを使った記述方式

main.rs
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が返される。-vverboseのオプションなのはデフォルトで組み込まれているということ?

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の指定を追加する。

main.rs
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 デフォルト値を指定する。

こんな書き方をしたら・・・

main.rs(一部)
    /// 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からファイル名を取得していた箇所も修正が必要。

main.rs
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. メッセージを日本語化するにはどうしたら良いか(要調査)。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?