命令行工具開發:如何快速實現命令行提示?

2020-12-12 阿里技術

阿里妹導讀:對於稍微複雜一些的命令行工具,命令行的提示功能必不可少。那麼對於不同語言的開發者,有沒有一種簡單快捷的實現方式呢?本文分享一種快速實現的方法,使用YAML文件定義命令行工具的使用規範,再通過工具自動生成各種shell的命令行提示腳本,最後分享一些至關重要的命令行解析器。

文末福利:雲開發體驗——Linux指令入門。

不少同學喜歡開發命令行工具,主要是開發快捷,而且和其他命令行工具配合,藉助腳本,非常容易實現一些任務的自動化。命令行工具開發比較簡單,以Java舉一個例子,通常我們只需要一個命令行參數解析器,如Java,就有args4j, jopt,picocli等,轉換為結構化的對象,根據輸入的參數進行相關的邏輯判斷,完成對應的邏輯。其他如Node.js, Deno, Python等,也是一樣的流程,都有命令行參數解析器,然後基於命令行輸入執行對應的邏輯。

一 命令行提示

如果命令行工具稍微複雜一些,那麼必須要提供對應的命令行提示,不然開發者幾乎沒法使用。舉一個例子,阿里雲有對應的命令行工具aliyun-cli[1],下載安裝後就可以使用aliyun命令行工具了。執行 aliyun --help,會發現非常多的子命令,如果沒有命令行工具提示,開發者使用這個工具就非常複雜,要去查文檔,或者通過命令行的help來輸入命令。

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

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

大多數開發者喜歡帶描述的命令行提示。並不是所有的子命令和命令參數都命名得非常好,如aliyun命令行給出的live子命令提示,大家可能完全不知道這個live是什麼(當然,作為阿里雲的同學,我還是知道的, live是視頻直播)。而像如下包括描述的命令行提示就直觀很多:

二 生成命令行提示

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

我找了一些命令行解析框架,並且能自動生成命令行提示的,如Java的picocli,Node.js的commander.js,Python的argparse,以及Rust的clap-rs等。我都嘗試了一下,最終發現還是clap-rs生成的命令行提示比較好,就是我說的那種帶描述,而且還有文件名和目錄自動提示,枚舉值的提示等,關鍵是也非常簡單。如果有同學有更好的命令行解析框架,希望能留言分享一下。

那麼如何讓其他語言,如Node.js,Java,Python這些語言編寫的命令行工具也能實現和clap-rs的命令行提示一樣的效果呢?

三 clap-rs的命令行YAML文件

clap-rs包含了一個命令行工具的YAML規範。我們都知道命令行工具交互比較簡單,主要就兩個部分:參數和子命令。你看到類似 --conf xxx.yaml 這些帶參數名的都屬於參數,也可以省略參數名,如 convert a.jpg a.png 其中的a.jpg和a.png也都是參數。子命令就比較容易理解了,我們每天使用的git就是大量使用子命令的,如 git add xxx.jpg 這些。當子命令還可以繼續套用子命令,子命令同時也擁有自己的參數。

基於命令行這樣的特性,我們完全可以將命令行工具的使用規範通過YAML描述出來,現在一切皆可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這個參數,這樣我就可以使用cat來查看oss上文本文件的內容。

有了這個命令行工具YAML規範定義後,我就可以調用clap-rs提供的命令行工具接口,生成對應的shell的提示腳本。效果如下:

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

四 為所有命令行工具寫YAML

講到這裡,相信大家都明白了。無論這個工具是Java,Python,Node.js還是Rust編寫的,首先定義好該工具的YAML規範,接下來開發人員根據該規範去編寫代碼,他可以選擇他喜歡的語言,他喜歡的命令行解析器,然後實現對應的功能即可。沒有代碼提升,編寫YAML文件不出錯是非常難的,所以我做了一個JSON Schema[2]文件,在編寫YAML文件時可以進行代碼提示,做到編寫命令行YAML規範文件更加簡單。JSON Schema的使用方法如下:

接下來我們會基於該YAML文件,為各種shell生成對應的命令行提示腳本,如bash,zsh,fish和powershell,這樣分開後,開發人員也不需要去處理那些他不清楚的命令行提示,或者找該程式語言對應的SDK來做命令行代碼提示。如果沒有怎麼辦?即便有了,生成的提示非常簡單怎麼辦?畢竟命令行工具提示非常重要。

相信Node.js的開發者也不希望還要學習一下Rust和clap-rs,這樣就太不高效了。因此我又編寫了一個工具cli-completion[3], 其主要目的根據上面說的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可以為任何命令提供命令行提示。也就是說,以後,你只要編寫命令行邏輯,關於命令行提示的問題,全部交給cli-completion幫你生成即可。當然考慮到用戶體驗,你可能需要在命令行工具中,將cli-completion生成的腳本,通過某一子命令,快速同步到客戶端環境。

命令行的開發流程:YAML規範編寫,命令行提示自動生成,開發人員下班前完成功能實現。

有同學可能會問,我能否基於YAML文件,並結合某一命令行解析框架,自動完成整個應用的骨架生成,這完全可以,開發人員只要實現一些函數即可,開發會更簡單。我個人認為使用PicoCli這些框架自動生成代碼,是完全沒有問題的。

五 將cli-completion FaaS化

這個功能大家一年都未必用上兩次,費時安裝也挺麻煩的。現在不是到處都是FaaS,我們也可以嘗試一下。首先cli-completion是用Rust編寫的,所以可以用傳統的方式編寫Rust Cloud Lambda,然後部署到雲服務上,另外也可以寫一個Rust Web應用,如用actix-web,也非常簡單。

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

創建一個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

然後調用cli-completion的FaaS服務,就可以得到對應的命令行提示腳本代碼。命令如下:

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

對比傳統的cloud lambda或者cloud function,這種方式FaaS響應速度最快,這種服務調用次數非常少,基本就是每次請求都是冷啟動,而WebAssembly這方面就非常有優勢。

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

題外話探討一下cloudflare的WebAssmebly的實現,純技術討論,代碼如下:

asyncfunctionhandleRequest(request) {const { greet } = wasm_bindgenawait wasm_bindgen(wasm)const greeting = greet()returnnew Response(greeting, {status: 200})}

上述代碼中,wasm是一個WebAssembly.Module對象,它是從外部注入的,而不是開發者寫的,是FaaS生成的。接下來就是從wasm_bindgen這個函數中獲取wasm的導出函數,然後調用 wasm_bindgen(wasm) 將greet函數和wasm module中的export函數進行關聯,然後調用greet就會轉到wasm module的調用。如果是這樣的話,WebAssembly.Module其實是可以外部管理的,當有請求時,再和JavaScript的函數進行關聯,這樣就可以保證WebAssembly的快速響應。

六 總結

以後大家在寫命令行工具時,不用再擔心代碼提示的問題了。在動手開發工具前,寫一下YAML文件,整理和釐清一下你的思路,有哪些子命令,有哪些參數等,然後再基於該YAML文件進行開發,使用什麼語言都沒有關係,最後配合cli-completion完成命令行提示,你的命令行工具算是相當專業的了,至少從面子上看起來是的 :)

最後列出一些命令行應用涉及的至關重要的命令行解析器,方便大家後續參考:

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

整理的不全,歡迎大家補充 :)

相關連結[1]https://github.com/aliyun/aliyun-cli[2]https://github.com/linux-china/cli-completion/blob/master/cli-schema.json[3]https://crates.io/crates/cli-completion[4]https://www.npmjs.com/search?q=args%20parser

雲開發體驗

Linux指令入門——文件與權限

阿里雲開發者成長計劃來啦!基於真實的雲環境和業務場景,幫助開發者深入學習體驗雲上技術。本場景將提供一臺配置了Aliyun Linux 2的ECS實例(雲伺服器),介紹Linux系統中常用的文件目錄管理和文件權限管理命令。

相關焦點

  • JVM 常用命令行工具
    一、基礎故障處理工具Java 開發人員肯定都知道 JDK 的 bin 目錄下有許多小工具,這些小工具除了用於編譯和運行 Java 程序外,打包、部署、籤名、調試、監控、運維等各種場景都可能會見到它們的影子本文主要介紹的是用於監視虛擬機運行狀態和進行故障處理的工具,根據軟體可用性和授權的不同,可以分成三類:商業授權工具:主要是 JMC
  • GitHub 開源官方命令行工具登頂 TOP1,5 分鐘極速上手!
    我不得不承認,這個工具已經兌現了承諾。然而,最近 GitHub 一直為發布官方工具和產品做努力,而且他們的進展良好,這還要多虧了微軟收購帶來的巨額資金和方向調整。之前,GitHub 發布了一個帶有 GUI 的桌面應用程式,而且正式的命令行工具也提上了日程。如今,官方版的 GitHub CLI 終於問世了。
  • Nosqli:一款功能強大的NoSql注入命令行接口工具
    Nosqli:一款功能強大的NoSQL注入命令行接口工具 Nosqli是一款功能強大的NoSql注入命令行接口工具,本質上來說,它就是一款NoSQL掃描和注入工具。
  • 為什麼Linux用戶喜歡命令行?
    為什麼Linux用戶喜歡命令行? 當我開始自己的Linux之旅時,我堅決不碰終端窗口。好像命令行上有這種令人噁心的東西。好像命令行上有這種令人噁心的東西。"如果我無法使用GUI做到這一點,那麼我對這個發行版甚至都不感興趣!"我會固執地說。
  • 新購買的imx6ull開發板如何使用:下載qt程序,進入Linux命令行系統
    大家好,這裡是義縣遊學電子科技.今天帶給您的是如何使用新購買的imx6ull開發板.新購買的開發板上電後會直接進入原子的演示程序,那如何才能顯示我們自己編譯好的qt程序呢.如何進入Linux命令行終端呢?這就是我們今天的主題了.
  • 快速打開window命令行小技巧,你還在菜單欄搜索cmd嗎?
    快速打開window命令行小技巧,你還在菜單欄搜索cmd嗎?作為一名程序猿對於window命令行肯定不陌生了,但是每次都要在菜單欄裡搜索cmd是不是特別麻煩呢?而且還要CD到自己想要到的路徑,實在是十分不爽啊!
  • 高效辦公,從幾行批處理命令開始 | 原力計劃
    閒話少說,今天分享的文章,講解如何將平常頻繁的單調工作、操作,通過系統自帶的命令行,變得自動起來,不需要每件事都親力親為,節省時間,提高效率。關機與重啟如果你覺得每天手動關機太麻煩,給你一行命令,讓電腦每天定時自動關機。
  • 在命令行中如何解碼二次JSON編碼的字符串?
    如何在命令行中將這個結構展開呢?構造測試數據,如下是通過PHP命令行生成測試一個二次JSON encode的字符串php -r "echo json_encode(json_encode(['a' => ['b' => 1]]));"# "{\"a\":{\"b\":1}}"
  • Shell—正則表達式(grep命令、sed工具)
    一、正則表達式概述正則表達式定義正則表達式,又稱正規表達式、常規表達式使用字符串來描述、匹配一系列符合某個規則的字符串簡單來說,是一種匹配字符串的方法,通過一些特殊符號,實現快速查找、刪除、替換某個特定字符串。
  • Linux的介紹以及常用命令
    Linux的介紹:創始人**林納斯·託瓦茲**,最早是為了玩遊戲而開發出來的。Linux是一套免費使用和自由傳播的類Unix作業系統,是一個基於POSIX和UNIX的多用戶、多任務、支持多線程和多CPU的作業系統。它能運行主要的UNIX工具軟體、應用程式和網絡協議。
  • youtube-dl 2021.01.08 發布,視頻下載命令行工具
    Youtube-dl 是一個開源的 Python 命令行工具,可用於下載上千個視頻網站的視頻內容,它可以保存視頻 MP4 和其他提供的格式,也可以僅提取音軌,用途十分廣泛。此前該項目曾因涉嫌違反美國版權法被美國唱片業協會 RIAA 投訴下架,在眾多開發者的爭取下,該項目倉庫最終得以恢復。
  • 網絡管理基礎,新手學習,華為命令行常用視圖介紹說明
    文/IT科技愛好者進入命令行視圖今天我們來介紹下進入和退出命令行視圖的方法。設備提供豐富的功能,相應的也提供了多樣的配置和查詢命令。為便於用戶使用這些命令,華為路由器按功能分類將命令分別註冊在不同的命令行視圖下。配置某一功能時,需首先進行對應的命令行視圖,然後執行相應的命令進行配置。設備提供的命令視圖有很多,下面提到的視圖是最常用的視圖。其他視圖的進入方式在具體的命令中都有說明。
  • 如何記憶Linux命令
    Linux是作業系統,作業系統提供進程、文件、網絡等管理功能特性決定了命令行的複雜性。Linux命令雖然多,但學習Linux命令可以換一種角度來學習。許多人記憶的過程是這樣的ls --> 列出目錄內容這樣的記憶就是簡單的映射,沒有構建起聯繫。
  • CAD命令使用技巧看看吧!
    1.Cad命令擇優使用  cad的繪圖命令有很多,但是常用到的命令不過十幾條,所以要總結自己常用的命令。畫圖時,同一個操作可以用不同的命令實現,要想選用最快的命令達到目的,就必須熟練掌握各種命令的功能、特點。
  • 使用命令行運行Manim,高效開發、測試,3種配置文件滿足需求
    代碼如下:命令行參數一般地,Manim通過下面格式的命令行運行:$ manim SceneName$ manim SceneName -ql這行渲染質量標示可以改變配置選項config.pixel_width, config.pixel_height, config.frame_rate和config.quality。
  • XPocket:笨神又出一款Java命令行性能分析工具
    封面:稻城亞丁近期我們為大家發布了一款免費的命令行性能分析工具下面整理了一下PerfMa為大家提供的幾款免費的性能調優工具,希望大家能用起來,也歡迎大家提建議,有任何性能,JVM相關的問題都可以到我們PerfMa社區(https://club.perfma.com)來提,有非常多的專家熱心的為大家服務,社區裡也積攢了非常多的性能案例,經典JVM問答,還有一些學習的課程。
  • 開源智能人工助手Betty:將英語句子轉為UNIX命令
    從圖形界面,到聲控,電腦命令行的角色不可替代。對開發者,系統管理員,硬核研究者們而言, 這個簡單但強大的界面是玩轉計算機的最好工具。不過,使用命令行不是件容易的事,需要記住一大堆命令。
  • 如何快速的在CAD軟體中用DIVIDE命令插入繪製好的圖塊
    接下來我們一起來學習一下使用定數等分命令插入繪製好的圖塊的操作吧! 1. 打開一個圖形文件,如下圖所示,可以看到上方有繪製好的名稱為「chair」的圖塊。 在命令行輸入DIVIDE並按回車鍵確認,根據命令行提示,選取地板的上表面作為定數等分的對象,接著輸入「B」,按回車鍵確認,選擇用塊來等分對象。
  • 實現Python數據化運營都需要哪些工具和組件?
    2.Python IDEPython自帶IDE,可以滿足一定的數據開發和測試需求,在交互型的開發和學習上,也有IPython可供選擇。但這裡建議大家選擇另外一個Python IDE工具——PyCharm。
  • AutoCAD基礎—常用繪圖命令
    步驟2根據命令行提示,將光標分別移至兩條直線和圓的合適位置,待出現圖3-6所示的「遞延切點」提示時單擊。此時,系統會自動繪製一個與這三個對象均相切的圓,如圖3-7所示。例如,要在圖3-15(a)所示矩形的兩條相鄰邊間繪製連接弧,可在「默認」選項卡的「修改」面板中單擊「圓角」按鈕  ,然後根據命令行提示輸入「T」並按【Enter】鍵,再次輸入「T」並按【Enter】鍵,以選擇「修剪」模式;輸入