Rust Crate 使用:clap

Clap

Github
Crates.io

前言

狠狠狠好用的庫介紹。如果你對控制臺情有獨鐘磺陡,必然會接觸到命令行傳參兢交。 對使用者而言,一份優(yōu)雅的命令列表锭沟,錯誤提示能增進(jìn)軟件的好感抽兆。 但對開發(fā)者而言,維護(hù)一份復(fù)雜的命令列表是頭疼的族淮。重復(fù)的命令行參數(shù)辫红,隨著子參數(shù)增多凭涂,不會規(guī)范管理,都會是代碼難以閱讀厉熟。

為了提升效率导盅,減輕負(fù)擔(dān),我強烈推薦clap庫揍瑟。

介紹

clap是一個簡單易用白翻,功能強大的命令行參數(shù)解析庫。

使用

clap 允許多中方式指定我們的命令行绢片。支持常規(guī)的 Rust 方法調(diào)用滤馍、宏或者YAML配置。

常規(guī)調(diào)用模式

首先介紹的是Rust代碼控制命令行底循。

extern crate clap;

use clap::{Arg, App};

fn main() {
    let matches = App::new("MayApp")
        .version("0.1")
        .author("kayryu")
        .about("Learn use Rust Crate!")
        .arg(Arg::with_name("verbose")
            .short("v")
            .multiple(true)
            .help("verbosity level"))
        .args_from_usage("-p, --path=[FILE] 'Target file you want to change'")
        .get_matches();

    if let Some(f) = matches.value_of("path") {
        println!("path : {}", f);
    }
}

我們使用version()巢株,author()about()方法,提供程序的的一般信息熙涤。clap會自動添加兩個參數(shù):--help和--version(或他們的簡短形式-h和-V)阁苞。

運行你的可執(zhí)行文件,并在跟隨--help參數(shù)祠挫∧遣郏控制臺輸出:

MayApp 0.1
kayryu
Learn use Rust Crate!

USAGE:
    u-clap.exe [FLAGS] [OPTIONS]

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information
    -v               verbosity level

OPTIONS:
    -p, --path <FILE>    Target file you want to change

通過Arg::with_name()調(diào)用創(chuàng)建一個簡單的命名參數(shù)。此結(jié)構(gòu)有一些有用的方法等舔,例如:

  • short(): 提供一個簡短的單字母表格
  • required(): 指示參數(shù)是可選的還是必需的
  • takes_value()default_value()--option=foo類似的參數(shù)讀取值骚灸。
  • multiple() 允許重復(fù)發(fā)生;

在參數(shù)中傳入-v,獲得詳細(xì)的輸出慌植,或者-vv更加詳細(xì)甚牲。

cargo run --bin u-clap --
zero

cargo run --bin u-clap -- -vv
more

Arg::with_name()方式創(chuàng)建命令行參數(shù)顯得啰嗦,也可以用args_from_usage函數(shù)直接從文本信息中解析蝶柿。參考代碼中的Path例子丈钙。

clap也支持命令分級,如下例子(來源于clap提供的例子):

//
//            Top Level App (git)                         TOP
//                           |
//    -----------------------------------------
//   /             |                \          \
// clone          push              add       commit      LEVEL 1
//   |           /    \            /    \       |
//  url      origin   remote    ref    name   message     LEVEL 2
//           /                  /\
//        path            remote  local                   LEVEL 3
//

接下去我們在前面代碼的基礎(chǔ)上動手使用子命令交汤。

extern crate clap;

use clap::{Arg, App, SubCommand};

fn main() {
    let matches = App::new("MayApp")
        .version("0.1")
        .author("kayryu")
        .about("Learn use Rust Crate!")
        .arg(Arg::with_name("verbose")
            .short("v")
            .multiple(true)
            .help("verbosity level"))
        .args_from_usage("-p, --path=[FILE] 'Target file you want to change'")
        .subcommand(SubCommand::with_name("test")
                        .about("does testing things")
                        .arg_from_usage("-l, --list 'lists test values'"))
        .get_matches();
        
    if let Some(f) = matches.value_of("path") {
        println!("path : {}", f);
    }
    
    if let Some(matches) = matches.subcommand_matches("test") {
        if matches.is_present("list") {
            println!("Printing testing lists...");
        } else {
            println!("Not printing testing lists...");
        }
    }
}

通過.subcommand()方法傳入SubCommand對象著恩。 子命令的參數(shù)構(gòu)造方式和主命令一致。構(gòu)造好參數(shù)后通過.subcommand_matches()來獲取匹配的子參數(shù)蜻展。進(jìn)一步,我們按照相同的方式創(chuàng)建多層級的命令行邀摆。

宏模式

如果覺得上述構(gòu)建命令行的方式還不夠簡潔纵顾,clap還提供了宏構(gòu)建。

#[macro_use]
extern crate clap;

let matches = clap_app!(myapp =>
        (version: "1.0")
        (author: "Kayryu")
        (about: "Learn use Rust Crate!")
        (@arg CONFIG: -c --config +takes_value "Sets a custom config file")
        (@arg debug: -d ... "Sets the level of debugging information")
        (@subcommand test =>
            (about: "controls testing features")
            (@arg verbose: -v --verbose "Print test information verbosely")
        )
    ).get_matches();

    let config = matches.value_of("CONFIG").unwrap_or("default.conf");
    println!("Value for config: {}", config);

    if let Some(matches) = matches.subcommand_matches("test") {
        if matches.is_present("verbose") {
            println!("Printing verbosely...");
        } else {
            println!("Printing normally...");
        }
    }

yaml配置模式

如果你覺得這部分命令行配置住在代碼中顯示影響了代碼閱讀栋盹,clap也支持YAML讀取施逾,就是把命令行配置放在單獨文件中管理。
在使用它前,需要在依賴中開啟yaml特性汉额。

[dependencies]
clap = { version = "2.32.0", features = ["yaml"] }

編寫命令行配置文件yaml.yml:

name: MyApp
version: "1.0"
about: Learn use Rust Crate!
author: Kayryu

args:
    - verbose:
        help: verbosity level
        short: v
        multiple: true
    - path:
        help: Target file you want to change
        short: p
        takes_value: true

subcommands:
    - test:
        about: does testing things
        args:
            - list:
                help: lists test values
                short: l

調(diào)用代碼:

let yml = load_yaml!("yaml.yml");
let matches = App::from_yaml(yml).get_matches();

let _ = match matches.occurrences_of("verbose") {
    0 => println!("zero"),
    1 => println!("one"),
    _ => println!("more")
};

if let Some(matches) = matches.subcommand_matches("test") {
    if matches.is_present("list") {
        println!("Printing testing lists...");
    } else {
        println!("Not printing testing lists...");
    }
}

通過load_yaml!宏導(dǎo)入先前配置好的yaml文件曹仗,該文件和測試代碼在同一目錄。

錯誤提示

在使用中難免會輸錯參數(shù)蠕搜,但你不用擔(dān)心怎茫,clap會友好地提示你正確的命令用例。如果僅是命令行的個別字母打錯了妓灌,它還能做到關(guān)聯(lián)提示轨蛤,這點庫做得實在貼心。

>>>>>>
cargo run --bin u-clap test

>>>>>>
error: The subcommand 'testt' wasn't recognized
        Did you mean 'test'?

If you believe you received this message in error, try re-running with 'u-clap.exe -- testt'

USAGE:
    u-clap.exe [FLAGS] [OPTIONS] [SUBCOMMAND]

For more information try --help

資料

24-days-rust-clap

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末虫埂,一起剝皮案震驚了整個濱河市祥山,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌掉伏,老刑警劉巖缝呕,帶你破解...
    沈念sama閱讀 212,080評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異斧散,居然都是意外死亡供常,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,422評論 3 385
  • 文/潘曉璐 我一進(jìn)店門颅湘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來话侧,“玉大人,你說我怎么就攤上這事闯参≌芭簦” “怎么了?”我有些...
    開封第一講書人閱讀 157,630評論 0 348
  • 文/不壞的土叔 我叫張陵鹿寨,是天一觀的道長新博。 經(jīng)常有香客問我,道長脚草,這世上最難降的妖魔是什么赫悄? 我笑而不...
    開封第一講書人閱讀 56,554評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮馏慨,結(jié)果婚禮上埂淮,老公的妹妹穿的比我還像新娘。我一直安慰自己写隶,他們只是感情好倔撞,可當(dāng)我...
    茶點故事閱讀 65,662評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著慕趴,像睡著了一般痪蝇。 火紅的嫁衣襯著肌膚如雪鄙陡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,856評論 1 290
  • 那天躏啰,我揣著相機(jī)與錄音趁矾,去河邊找鬼。 笑死给僵,一個胖子當(dāng)著我的面吹牛毫捣,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播想际,決...
    沈念sama閱讀 39,014評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼培漏,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了胡本?” 一聲冷哼從身側(cè)響起牌柄,我...
    開封第一講書人閱讀 37,752評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎侧甫,沒想到半個月后珊佣,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,212評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡披粟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,541評論 2 327
  • 正文 我和宋清朗相戀三年咒锻,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片守屉。...
    茶點故事閱讀 38,687評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡惑艇,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出拇泛,到底是詐尸還是另有隱情滨巴,我是刑警寧澤,帶...
    沈念sama閱讀 34,347評論 4 331
  • 正文 年R本政府宣布俺叭,位于F島的核電站恭取,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏熄守。R本人自食惡果不足惜蜈垮,卻給世界環(huán)境...
    茶點故事閱讀 39,973評論 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望裕照。 院中可真熱鬧攒发,春花似錦、人聲如沸晋南。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,777評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽搬俊。三九已至紊扬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間唉擂,已是汗流浹背餐屎。 一陣腳步聲響...
    開封第一講書人閱讀 32,006評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留玩祟,地道東北人腹缩。 一個月前我還...
    沈念sama閱讀 46,406評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像空扎,于是被迫代替她去往敵國和親藏鹊。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,576評論 2 349