Rust の簡単な CLI用テンプレート


シンプルなケース

標準ライブラリのみのシンプルなケース。

use std::env;
use std::process;
use std::error::Error;
use std::path::PathBuf;

fn main() {

    let opt = Opt::from_args().unwrap_or_else(|err| {
        eprintln!("args error: {}", err);
        process::exit(1);
    });

    if let Err(e) = run(opt) {
        eprintln!("exec error: {}", e);
        process::exit(1);
    }
}

fn run(opt: Opt) -> Result<(), Box<dyn Error>> {
    println!("{:?}", opt);
    Ok(())
}

#[derive(Debug)]
struct Opt {
    filename: PathBuf,
}

impl Opt {
    fn from_args() -> Result<Opt, Box<dyn Error>> {
        let filename =  env::args().nth(1)
            .ok_or("no filename given.".to_owned())?;
        Ok(Opt {
            filename : PathBuf::from(filename),
        })
    }
}


StructOpt 利用

StructOpt の依存を Cargo.toml に追加

[dependencies]
structopt = "0.3"


derive でオプションを定義する。

use std::process;
use std::error::Error;
use std::path::PathBuf;
use structopt::StructOpt;

fn main() {
    let opt = Opt::from_args();
    if let Err(e) = run(opt) {
        eprintln!("exec error: {}", e);
        process::exit(1);
    }
}

fn run(opt: Opt) -> Result<(), Box<dyn Error>> {
    println!("{:?}", opt);
    Ok(())
}

#[derive(Debug, StructOpt)]
struct Opt {
    #[structopt(short = "f", long = "file")]
    filename: PathBuf,
}


以下のようにいい感じに表示できる。

f:id:Naotsugu:20210310213056p:plain


なお、cargo run でアプリケーション側に引数を渡すには -- を指定する。

cargo run -- --file foo.txt