命令行工具開發(fā):如何快速實現(xiàn)命令行提示?

阿里妹導讀:對于稍微復雜一些的命令行工具篇亭,命令行的提示功能必不可少缠捌。那么對于不同語言的開發(fā)者,有沒有一種簡單快捷的實現(xiàn)方式呢译蒂?本文分享一種快速實現(xiàn)的方法曼月,使用YAML文件定義命令行工具的使用規(guī)范,再通過工具自動生成各種shell的命令行提示腳本柔昼,最后分享一些至關(guān)重要的命令行解析器哑芹。

文末福利:云開發(fā)體驗——Linux指令入門。

不少同學喜歡開發(fā)命令行工具捕透,主要是開發(fā)快捷聪姿,而且和其他命令行工具配合,借助腳本激率,非常容易實現(xiàn)一些任務的自動化咳燕。命令行工具開發(fā)比較簡單,以Java舉一個例子乒躺,通常我們只需要一個命令行參數(shù)解析器招盲,如Java,就有args4j嘉冒, jopt曹货,picocli等咆繁,轉(zhuǎn)換為結(jié)構(gòu)化的對象,根據(jù)輸入的參數(shù)進行相關(guān)的邏輯判斷顶籽,完成對應的邏輯玩般。其他如Node.js, Deno, Python等,也是一樣的流程礼饱,都有命令行參數(shù)解析器坏为,然后基于命令行輸入執(zhí)行對應的邏輯。

一? 命令行提示

如果命令行工具稍微復雜一些镊绪,那么必須要提供對應的命令行提示匀伏,不然開發(fā)者幾乎沒法使用。舉一個例子蝴韭,阿里云有對應的命令行工具aliyun-cli[1]够颠,下載安裝后就可以使用aliyun命令行工具了。執(zhí)行?aliyun --help榄鉴,會發(fā)現(xiàn)非常多的子命令履磨,如果沒有命令行工具提示,開發(fā)者使用這個工具就非常復雜庆尘,要去查文檔剃诅,或者通過命令行的help來輸入命令。

aliyun的命令行工具也提供了對應的代碼提示驶忌,如下所示:

這個命令行提示還不錯综苔,你只需要選擇對應的子命令然后再進行提示就可以了。

大多數(shù)開發(fā)者喜歡帶描述的命令行提示位岔。并不是所有的子命令和命令參數(shù)都命名得非常好,如aliyun命令行給出的live子命令提示堡牡,大家可能完全不知道這個live是什么(當然抒抬,作為阿里云的同學,我還是知道的晤柄, live是視頻直播)擦剑。而像如下包括描述的命令行提示就直觀很多:

二? 生成命令行提示

這里不再介紹bash,zsh芥颈,fish等各種shell的命令行提示的機制惠勒,沒有人會手動編寫這些命令行提示腳本,大家都會使用框架生成對應shell的命令行提示腳本爬坑。

我找了一些命令行解析框架纠屋,并且能自動生成命令行提示的,如Java的picocli盾计,Node.js的commander.js售担,Python的argparse赁遗,以及Rust的clap-rs等。我都嘗試了一下族铆,最終發(fā)現(xiàn)還是clap-rs生成的命令行提示比較好岩四,就是我說的那種帶描述,而且還有文件名和目錄自動提示哥攘,枚舉值的提示等剖煌,關(guān)鍵是也非常簡單。如果有同學有更好的命令行解析框架逝淹,希望能留言分享一下耕姊。

那么如何讓其他語言,如Node.js创橄,Java箩做,Python這些語言編寫的命令行工具也能實現(xiàn)和clap-rs的命令行提示一樣的效果呢?

三? clap-rs的命令行YAML文件

clap-rs包含了一個命令行工具的YAML規(guī)范妥畏。我們都知道命令行工具交互比較簡單邦邦,主要就兩個部分:參數(shù)和子命令。你看到類似?--conf xxx.yaml?這些帶參數(shù)名的都屬于參數(shù)醉蚁,也可以省略參數(shù)名燃辖,如?convert a.jpg a.png?其中的a.jpg和a.png也都是參數(shù)。子命令就比較容易理解了网棍,我們每天使用的git就是大量使用子命令的黔龟,如?git add xxx.jpg?這些。當子命令還可以繼續(xù)套用子命令滥玷,子命令同時也擁有自己的參數(shù)氏身。

基于命令行這樣的特性,我們完全可以將命令行工具的使用規(guī)范通過YAML描述出來惑畴,現(xiàn)在一切皆可YAML蛋欣。

這里我給出一個阿里云命令行工具的YAML定義,當然只是demo如贷。如下:

name:aliyun2version:"0.1.0"about:"cli for Alibaba Cloud"args:-version:short:vlong:versiontakes_value:falseabout:Display versionsubcommands:-oss:about:對象存儲subcommands:-cat:about:cat文本文件args:-file:takes_value:truerequired:trueabout:文件名稱-ls:about:list文件-ecs:about:云服務器subcommands:-SendFile:about:send file-AddTags:about:add tags

可以看出陷虎,我首先定義了兩個子命令:oss和ecs,然后oss子命令下我又定義了兩個子命令:cat和ls杠袱。對于oss的cat子命令尚猿,我又添加了file這個參數(shù),這樣我就可以使用cat來查看oss上文本文件的內(nèi)容楣富。

有了這個命令行工具YAML規(guī)范定義后凿掂,我就可以調(diào)用clap-rs提供的命令行工具接口,生成對應的shell的提示腳本菩彬。效果如下:

這個命令行提示的效果是不是比原先的要好多了缠劝?提示有了描述潮梯,選擇子命令和參數(shù)的時候就簡單多了。

四? 為所有命令行工具寫YAML

講到這里惨恭,相信大家都明白了秉馏。無論這個工具是Java,Python脱羡,Node.js還是Rust編寫的萝究,首先定義好該工具的YAML規(guī)范,接下來開發(fā)人員根據(jù)該規(guī)范去編寫代碼锉罐,他可以選擇他喜歡的語言帆竹,他喜歡的命令行解析器,然后實現(xiàn)對應的功能即可脓规。沒有代碼提升栽连,編寫YAML文件不出錯是非常難的,所以我做了一個JSON Schema[2]文件侨舆,在編寫YAML文件時可以進行代碼提示秒紧,做到編寫命令行YAML規(guī)范文件更加簡單。JSON Schema的使用方法如下:

接下來我們會基于該YAML文件挨下,為各種shell生成對應的命令行提示腳本熔恢,如bash,zsh臭笆,fish和powershell叙淌,這樣分開后,開發(fā)人員也不需要去處理那些他不清楚的命令行提示愁铺,或者找該編程語言對應的SDK來做命令行代碼提示鹰霍。如果沒有怎么辦?即便有了茵乱,生成的提示非常簡單怎么辦衅谷?畢竟命令行工具提示非常重要。

相信Node.js的開發(fā)者也不希望還要學習一下Rust和clap-rs似将,這樣就太不高效了。因此我又編寫了一個工具cli-completion[3], ?其主要目的根據(jù)上面說的YAML文件幫你自動生成各種shell的命令行提示腳本蚀苛。來看一下zsh的例子:

$ cli-completion --zsh commands/aliyun2.yaml >/usr/local/share/zsh/site-functions/_aliyun2$ autoload -U compinit && compinit

再看一下oh-my-zsh的例子:

$ mkdir ~/.oh-my-zsh/custom/plugins/aliyun2$ cli-completion --zsh aliyun2.yaml >? ~/.oh-my-zsh/custom/plugins/aliyun2/_aliyun2

通過這種方式在验,cli-completion可以為任何命令提供命令行提示。也就是說堵未,以后腋舌,你只要編寫命令行邏輯,關(guān)于命令行提示的問題渗蟹,全部交給cli-completion幫你生成即可块饺。當然考慮到用戶體驗赞辩,你可能需要在命令行工具中,將cli-completion生成的腳本授艰,通過某一子命令辨嗽,快速同步到客戶端環(huán)境。

命令行的開發(fā)流程:YAML規(guī)范編寫淮腾,命令行提示自動生成糟需,開發(fā)人員下班前完成功能實現(xiàn)。

有同學可能會問谷朝,我能否基于YAML文件洲押,并結(jié)合某一命令行解析框架,自動完成整個應用的骨架生成圆凰,這完全可以杈帐,開發(fā)人員只要實現(xiàn)一些函數(shù)即可,開發(fā)會更簡單专钉。我個人認為使用PicoCli這些框架自動生成代碼挑童,是完全沒有問題的。

五? 將cli-completion FaaS化

這個功能大家一年都未必用上兩次驶沼,費時安裝也挺麻煩的∨阢澹現(xiàn)在不是到處都是FaaS,我們也可以嘗試一下回怜。首先cli-completion是用Rust編寫的大年,所以可以用傳統(tǒng)的方式編寫Rust Cloud Lambda,然后部署到云服務上玉雾,另外也可以寫一個Rust Web應用翔试,如用actix-web,也非常簡單复旬。

這些都不夠時髦垦缅,我們打算將cli-completion的代碼WebAssembly化,然后以FaaS方式部署驹碍,這里我選擇CloudFlare作為FaaS的運行平臺壁涎。讓我們來看一下Demo。

創(chuàng)建一個cli.yaml文件志秃,如下:

name:cli1version:"0.1.0"about:"CLI completion for bash, zsh, fish and powershell."args:-help:short:hlong:helptakes_value:falseabout:Display this help

然后調(diào)用cli-completion的FaaS服務怔球,就可以得到對應的命令行提示腳本代碼。命令如下:

curl-H'Content-Type: application/x-yaml'--data-binary"@cli.yaml"https://cli-completion.linux-china.workers.dev/completion/zsh

對比傳統(tǒng)的cloud lambda或者cloud function浮还,這種方式FaaS響應速度最快竟坛,這種服務調(diào)用次數(shù)非常少,基本就是每次請求都是冷啟動,而WebAssembly這方面就非常有優(yōu)勢担汤。

當然還有一個最大的原因:就是WebAssembly方式的FaaS涎跨,它最便宜。

題外話探討一下cloudflare的WebAssmebly的實現(xiàn)崭歧,純技術(shù)討論隅很,代碼如下:

asyncfunctionhandleRequest(request){const{ greet } = wasm_bindgenawaitwasm_bindgen(wasm)constgreeting = greet()returnnewResponse(greeting, {status:200})}

上述代碼中,wasm是一個WebAssembly.Module對象驾荣,它是從外部注入的外构,而不是開發(fā)者寫的,是FaaS生成的播掷。接下來就是從wasm_bindgen這個函數(shù)中獲取wasm的導出函數(shù)审编,然后調(diào)用?wasm_bindgen(wasm)?將greet函數(shù)和wasm module中的export函數(shù)進行關(guān)聯(lián),然后調(diào)用greet就會轉(zhuǎn)到wasm module的調(diào)用歧匈。如果是這樣的話垒酬,WebAssembly.Module其實是可以外部管理的,當有請求時件炉,再和JavaScript的函數(shù)進行關(guān)聯(lián)勘究,這樣就可以保證WebAssembly的快速響應。

六? 總結(jié)

以后大家在寫命令行工具時斟冕,不用再擔心代碼提示的問題了口糕。在動手開發(fā)工具前,寫一下YAML文件磕蛇,整理和厘清一下你的思路景描,有哪些子命令,有哪些參數(shù)等秀撇,然后再基于該YAML文件進行開發(fā)愉择,使用什么語言都沒有關(guān)系大溜,最后配合cli-completion完成命令行提示吟策,你的命令行工具算是相當專業(yè)的了翠语,至少從面子上看起來是的 :)

最后列出一些命令行應用涉及的至關(guān)重要的命令行解析器,方便大家后續(xù)參考:

Java:Picocli, JCommander, JOpt, kotlinx-cli, JLine, args4j

Node.js:Commander.js,?clap.js,?minimist, yargs[4]

Deno:yargs

Python:argparse, docopt, cli-args, clap

Golang:argparse, flaggy

Rust:clap-rs, pico-args, paw

Ruby:cmdparse, commander, GLI

C++:gflags, cli, docopt.cpp

轉(zhuǎn)載:https://mp.weixin.qq.com/s/4LhcYk9x9qDkPHf-0jBqFA


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末再扭,一起剝皮案震驚了整個濱河市氧苍,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌泛范,老刑警劉巖候引,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異敦跌,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進店門柠傍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來麸俘,“玉大人,你說我怎么就攤上這事惧笛〈用模” “怎么了?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵患整,是天一觀的道長拜效。 經(jīng)常有香客問我,道長各谚,這世上最難降的妖魔是什么紧憾? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮昌渤,結(jié)果婚禮上赴穗,老公的妹妹穿的比我還像新娘。我一直安慰自己膀息,他們只是感情好般眉,可當我...
    茶點故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著潜支,像睡著了一般甸赃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上冗酿,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天埠对,我揣著相機與錄音,去河邊找鬼已烤。 笑死鸠窗,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的胯究。 我是一名探鬼主播稍计,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼裕循!你這毒婦竟也來了臣嚣?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤剥哑,失蹤者是張志新(化名)和其女友劉穎硅则,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體株婴,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡怎虫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年暑认,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片大审。...
    茶點故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡蘸际,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出徒扶,到底是詐尸還是另有隱情粮彤,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布姜骡,位于F島的核電站导坟,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏圈澈。R本人自食惡果不足惜惫周,卻給世界環(huán)境...
    茶點故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望士败。 院中可真熱鬧闯两,春花似錦、人聲如沸谅将。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽饥臂。三九已至逊躁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間隅熙,已是汗流浹背稽煤。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留囚戚,地道東北人酵熙。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像驰坊,于是被迫代替她去往敵國和親匾二。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,781評論 2 354

推薦閱讀更多精彩內(nèi)容