「実践Rustプログラミング入門」に入門する(7日目)Section4-2計算ロジックを追加する

[「実践Rustプログラミング入門」](https://www.shuwasystem.co.jp/book/9784798061702.html)を参考に。

# p.154 Section 4-2 計算ロジックを追加する

## p.155 ソースコード

完全なコード。p.154の`default_value`指定は外しておく。

```rust:main.rs
use clap::Clap;
use std::fs::File;
use std::io::{BufRead, BufReader};

#[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();

    if let Some(path) = opts.formula_file {
        let f = File::open(path).unwrap();
        let reader = BufReader::new(f);

        for line in reader.lines() {
            let line = line.unwrap();
            println!("{}", line);
        }
    } else {
        // ファイルを指定しなかった場合
        println!("No file is specified");
    }
}
```

## p.156 `cargo run -- noexist.txt

書籍の記述通りに実行。

```shell
PS \samplecli> cargo run -- notexist.txt
   Compiling samplecli v0.1.0 (\samplecli)
    Finished dev [unoptimized + debuginfo] target(s) in 1.74s
     Running `target\debug\samplecli.exe notexist.txt`       
error: Invalid value for '<NUMBER>': invalid digit found in stringerror: process didn't exit successfully: `target\debug\samplecli.exe notexist.txt` (exit code: 2)
```

あれ?と思ったら、書籍ではこの箇所、NUMBER指定はもう関係ないから外してあるということか。
あらためて、書籍が想定しているコード。

```rust:main.rs
use clap::Clap;
use std::fs::File;
use std::io::{BufRead, BufReader};

#[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();

    if let Some(path) = opts.formula_file {
        let f = File::open(path).unwrap();
        let reader = BufReader::new(f);

        for line in reader.lines() {
            let line = line.unwrap();
            println!("{}", line);
        }
    } else {
        // ファイルを指定しなかった場合
        println!("No file is specified");
    }
}
```

実行結果。存在しないファイルを指定した場合。

``` shell
PS \samplecli> cargo run -- notexist.txt
   Compiling samplecli v0.1.0 (\samplecli)
    Finished dev [unoptimized + debuginfo] target(s) in 1.17s
     Running `target\debug\samplecli.exe notexist.txt`       
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: "指定されたファイルが見つかりません。" }', src\main.rs:26:17
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: process didn't exit successfully: `target\debug\samplecli.exe notexist.txt` (exit code: 101)
```

エラーメッセージ「指定されたファイルが見つかりません。」が出る。日本語で出るのか。どこで指定しているんだろう。

プロジェクトディレクトリ直下に、input.txtを作成する。

```input.txt
1 1 +
1 2 + 3 4 + *
1000 1000 *
```

input.txtを指定して実行。

```shell
PS \samplecli> cargo run -- input.txt
    Finished dev [unoptimized + debuginfo] target(s) in 0.10s
     Running `target\debug\samplecli.exe input.txt`
1 1 +
1 2 + 3 4 + *
1000 1000 *
```

# 振り返り

1. 日本語エラーメッセージが出てくる箇所。メッセージのカスタマイズはどうやればよいか。