成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

用一次就會(huì)愛上的cli工具開發(fā)

caikeal / 3164人閱讀

摘要:拷貝成功在任意文件夾打開輸入執(zhí)行成功,目錄中多出了目錄加速初始其實(shí)中有一款工具包可以快速開發(fā)命令行工具,它就是。

寫在前面

最近接手任務(wù)——使用nodejs開發(fā)一個(gè)公司內(nèi)部使用的cli工具,簡而言之就是輸入一行命令快速搭建好項(xiàng)目結(jié)構(gòu),也可以通過不同的命令引入不同的文件。

了解

首先要基于node環(huán)境,然后我們需要知道cli是什么?cli是command-line interface的縮寫,即命令行工具,常用的vue-cli, create-react-app,express-generator 等都是cli工具。

回顧

創(chuàng)建一個(gè)exercise-cli目錄,并使用cmd進(jìn)入該目錄:

mkdir exercise-cli && cd exercise-cli

在該目錄下新建index.js:

//index.js
console.log("謝邀,人在美國,剛下飛機(jī)。");

使用node運(yùn)行index.js:

這是node的基本用法,那么如何使用自定義命令行輸出這句話呢?

點(diǎn)火

使用npm init創(chuàng)建package.json,一路回車,當(dāng)然你也可以配置相關(guān)信息,有興趣可自己選擇:

現(xiàn)在目錄中自動(dòng)生成一個(gè)package.json文件:

{
  "name": "exercise-cli",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

現(xiàn)在在package.json中添加字段bin,用來存放一個(gè)可執(zhí)行的文件,我們此處的可執(zhí)行文件就是index.js,因此配置如下:

"bin":{
    "exercise-cli":"./index.js"
},

此時(shí)我們配置exercise-cli命令來執(zhí)行index.js文件,需要在index.js文件頭部添加#!/usr/bin/env node, 讓系統(tǒng)自己去找node的執(zhí)行程序。至于這玩意具體什么,百度出這么個(gè)東西,可自行參考。

//index.js
#!/usr/bin/env node
console.log("謝邀,人在美國,剛下飛機(jī)。");

然后在cmd輸入npn linknpm install -g將當(dāng)前項(xiàng)目安裝到全局環(huán)境,這樣就可以直接使用exercise-cli來運(yùn)行文件了:

再學(xué)一點(diǎn),在package.json的scripts字段里添加腳本名:

"scripts": {
    "test": "echo "Error: no test specified" && exit 1",
    "exercise":"exercise-cli"
 }

命令行輸入npm run exercise,同樣輸出了index.js里的內(nèi)容,聯(lián)想起vue-clinpm run dev、npm run build等會(huì)不會(huì)若有所思呢?

起飛

有點(diǎn)樣子了,接下來讓我們看看它是如何生成項(xiàng)目模板的,一個(gè)思路是用一個(gè)templates文件夾保存項(xiàng)目模板,然后通過fs.mkdir()來創(chuàng)建項(xiàng)目目錄,最后把文件從templates文件夾拷貝到項(xiàng)目中去。本地templates目錄如下圖所示:

1.拷貝文件

模擬場景:將本地templates中的vue.min.js拷貝到新生成的項(xiàng)目模板中。在新生成的項(xiàng)目模板中新建public目錄,該目錄下新建js目錄,將vue.min.js通過copyTemplate()方法從templates里拷貝到新建的js目錄下面:

//index.js
#!/usr/bin/env node

var fs = require("fs");
var path = require("path");

// 復(fù)制文件
function copyTemplate (from, to) {
  from = path.join(__dirname, "templates", from);
  console.log(from);
  write(to, fs.readFileSync(from, "utf-8"))
}
function write (path, str, mode) {
  fs.writeFileSync(path, str)
}
// 新建目錄
function mkdir (path, fn) {
  fs.mkdir(path, function (err) {
    fn && fn()
  })
}

var PATH = ".";
mkdir(PATH+"/public",function(){
	mkdir(PATH + "/public/js",function () {
		copyTemplate("/js/vue.min.js", PATH + "/public/js/vue.min.js");
	})
})

用cmd打開任意文件夾輸入exercise-cli,該文件夾下會(huì)publicjsvue.min.js:

2.拷貝文件夾

我們學(xué)會(huì)了拷貝文件,那么如何拷貝整個(gè)文件夾呢,例如我想將templates下的整個(gè)js目錄全部拷貝到新生成的項(xiàng)目模板中,又該如何?有需求就有方案,我們可以遍歷整個(gè)文件夾,對(duì)遍歷到的path進(jìn)行判斷,如果是文件則直接拷貝,如果是文件夾則遞歸:

//index.js
// 復(fù)制目錄
var copy=function(src,dst){
    let paths = fs.readdirSync(src); //同步讀取當(dāng)前目錄(只能讀取絕對(duì)路徑,相對(duì)路徑無法獲取)
    paths.forEach(function(path){
        var _src=src+"/"+path;
        var _dst=dst+"/"+path;
        fs.stat(_src,function(err,stats){  //stats  該對(duì)象 包含文件屬性
            if(err)throw err;
            if(stats.isFile()){ //如果是個(gè)文件則拷貝 
                let  readable=fs.createReadStream(_src);//創(chuàng)建讀取流
                let  writable=fs.createWriteStream(_dst);//創(chuàng)建寫入流
                readable.pipe(writable);
            }else if(stats.isDirectory()){ //是目錄則 遞歸 
                checkDirectory(_src,_dst,copy);
            }
        });
    });
}
var checkDirectory=function(src,dst,callback){
    fs.access(dst, fs.constants.F_OK, (err) => {
        if(err){
            fs.mkdirSync(dst);
            callback(src,dst);
        }else{
            callback(src,dst);
        }
      });
};

mkdir(PATH+"/public",function(){
	mkdir(PATH + "/public/js",function () {
		checkDirectory("C:/Users/Administrator/Desktop/vue-3.0/nodeTest/exercise/templates/js",PATH+"/public/js",copy);
	})
})

依然在找一個(gè)文件夾打開cmd輸入exercise-cli,該文件夾下會(huì)生成public目錄,該目錄下面會(huì)生成templates下的整個(gè)js文件:

3.接收命令行參數(shù)

平常我們使用命令行工具時(shí)都會(huì)用到參數(shù),如webpack -p, express -e 等,在此我們?yōu)?b>exercise-cli配置-l,當(dāng)使用exercise-cli -l時(shí),添加layerJS。

我們可以使用process.argv來獲取命令行參數(shù),process.argv是一個(gè)參數(shù)數(shù)組,第一項(xiàng)為node.exe的絕對(duì)路徑,第二項(xiàng)為執(zhí)行該js的絕對(duì)路徑,使用process.argv.slice(2)即可獲取輸入的參數(shù)數(shù)組。

//index.js
console.log(process.argv);

通過遍歷參數(shù)數(shù)組來檢查命令中輸入了哪些參數(shù)。如果輸入了預(yù)設(shè)的參數(shù),就為config對(duì)象添加對(duì)應(yīng)的屬性,在生成文件時(shí)根據(jù)config判斷是否將模板文件拷貝到項(xiàng)目中。

var config = {};
process.argv.slice(2).forEach(item=>{
	if(item=="-l"){
		config.layer = true;
	}
})
var PATH = ".";
mkdir(PATH+"/public",function(){
	mkdir(PATH + "/public/js",function () {
		// copyTemplate("/js/vue.min.js", PATH + "/public/js/vue.min.js");
		checkDirectory("C:/Users/Administrator/Desktop/vue-3.0/nodeTest/exercise/templates/js",PATH+"/public/js",copy);
		if(config.layer){
			checkDirectory("C:/Users/Administrator/Desktop/exercise-cli/templates/layer",PATH+"/public/js",copy);
			//此處注意layerJS存放在templates中的路徑。
		}
	})
})
console.log("拷貝成功");

在任意文件夾打開cmd輸入exercise-cli -l,執(zhí)行成功,js目錄中多出了layerJS目錄:

加速 初始commander.js

其實(shí)node中有一款工具包可以快速開發(fā)命令行工具,它就是commander.js。

首先全局安裝一下:

npm install commander -g

看個(gè)例子:

var program = require("commander");
program
    .version("1.0.0","-v, --version")
    .command("check [checkname]")
    .alias("c")
    .description("yo yo check now")
    .option("-a, --name [moduleName]", "模塊名稱")
    .action((checkname,option) => {
        console.log("指令 install 后面跟的參數(shù)值 checkname: " + checkname);
        console.log(option);
        // 獲得了參數(shù),可以在這里做響應(yīng)的業(yè)務(wù)處理
    })
    	//自定義幫助信息
    .on("--help", function() {
        console.log("  下面我隨便說兩句:")
        console.log("")
        console.log("$ 人有多大膽,母豬多大產(chǎn),i love xx")
        console.log("$ 廣闊天地,大有所為,呱~")
    })
program.parse(process.argv)

命令行執(zhí)行:

看完輸出一臉懵逼,別急,這就帶您瞧瞧這都是些什么東西:

version - 定義命令程序的版本號(hào),.version("0.0.1", "-v, --version"),第一個(gè)參數(shù)版本號(hào)必須,第二個(gè)參數(shù)可省略,默認(rèn)為 -V 和 --version

command – 定義命令行指令,后面可跟上一個(gè)name,用空格隔開,如 .command("app [name]")

alias – 定義一個(gè)更短的命令行指令 ,如執(zhí)行命令$ exercise-cli c 與之是等價(jià)的

description – 描述,它會(huì)在help里面展示

option – 定義參數(shù)。它接受四個(gè)參數(shù),在第一個(gè)參數(shù)中,它可輸入短名字 -a和長名字–name ,使用 | 或者,分隔,在命令行里使用時(shí),這兩個(gè)是等價(jià)的,區(qū)別是后者可以在程序里通過回調(diào)獲取到;第二個(gè)為描述, 會(huì)在 help 信息里展示出來;第三個(gè)參數(shù)為回調(diào)函數(shù),他接收的參數(shù)為一個(gè)string,有時(shí)候我們需要一個(gè)命令行創(chuàng)建多個(gè)模塊,就需要一個(gè)回調(diào)來處理;第四個(gè)參數(shù)為默認(rèn)值

action – 注冊(cè)一個(gè)callback函數(shù),這里需注意目前回調(diào)不支持let聲明變量

parse – 用于解析process.argv,設(shè)置options以及觸發(fā)commands,用法示例:.parse(process.argv)

看到這,多多少少對(duì)如何編寫命令行工具有個(gè)大體的認(rèn)知了,光說不練嘴把式,自我實(shí)踐:用commander.js完成上個(gè)段落3.接收命令行參數(shù)中的例子。


分割線(以下深入和淺出部分于2019.4.30 更)

深入inquirer.js

創(chuàng)建腳手架的時(shí)候我們會(huì)發(fā)現(xiàn)很多腳手架都需要我們和命令行頻繁交互,就像我們開始使用npm init的時(shí)候一樣,那么是如何實(shí)現(xiàn)和命令行交互的呢?此時(shí)inquirer.js閃亮登場。

//命令行安裝
npm install inquirer
//index.js引入
var inquirer = require("inquirer");

    基本語法

var inquirer = require("inquirer");
inquirer.prompt([/* Pass your questions in here */]).then(function (answers) {
    // Use user feedback for... whatever!! 
})

    參數(shù)詳解

type:表示提問的類型,包括:input, confirm, list, rawlist, expand, checkbox, password, editor;

name: 存儲(chǔ)當(dāng)前問題回答的變量;

message:問題的描述;

default:默認(rèn)值;

choices:列表選項(xiàng),在某些type下可用,并且包含一個(gè)分隔符(separator);

validate:對(duì)用戶的回答進(jìn)行校驗(yàn);

filter:對(duì)用戶的回答進(jìn)行過濾處理,返回處理后的值;

transformer:對(duì)用戶回答的顯示效果進(jìn)行處理(如:修改回答的字體或背景顏色),但不會(huì)影響最終的答案的內(nèi)容;

when:根據(jù)前面問題的回答,判斷當(dāng)前問題是否需要被回答;

pageSize:修改某些type類型下的渲染行數(shù);

prefix:修改message默認(rèn)前綴;

suffix:修改message默認(rèn)后綴。

    實(shí)例分析

.action的回調(diào)函數(shù)里輸入以下內(nèi)容:

// 獲得了參數(shù),可以在這里做響應(yīng)的業(yè)務(wù)處理
var prompList = [
	{
		type:"input",
		message:"姓名",
		name:"name"
	},{
		type:"input",
		message:"手機(jī)號(hào)",
		name:"phone",
		validate:val=>{
			if(val.match(/d{11}/g)){
				return true
			}
			return "請(qǐng)輸入11位數(shù)字"
		}
	},{
		type:"confirm",
		message:"是否參加本次考核?",
		name:"assess",
		prefix:"前綴"
	},{
		type:"confirm",
		message:"是否同意本次考核須知?",
		name:"notice",
		suffix:"后綴",
		when:answers=>{
			return answers.assess
		}
	},{
		type:"list",
		message:"歡迎來到本次考核,請(qǐng)選擇學(xué)歷:",
		name:"eductionBg",
		choices:[
			"大專",
			"本科",
			"本科以上"
		],
		filter:val=>{//將選擇的內(nèi)容后面加學(xué)歷
			return val+"學(xué)歷"
		}
	},{
		type:"rawlist",
		message:"請(qǐng)選擇你愛玩的游戲:",
		name:"game",
		choices:[
			"LOL",
			"DOTA",
			"PUBG"
		]
	},{
		type:"expand",
			message:"請(qǐng)選擇你喜歡的水果:",
			name:"fruit",
			choices: [
			{
				key: "a",
				name: "Apple",
				value: "apple"
			},
			{
				key: "O",
				name: "Orange",
				value: "orange"
			},
			{
				key: "p",
				name: "Pear",
				value: "pear"
			}
		]
	},{
		type:"checkbox",
		message:"請(qǐng)選擇你喜歡的顏色:",
		name:"color",
		choices:[
			{
				name: "red"
			},
			new inquirer.Separator(), // 添加分隔符
			{
				name: "blur",
				checked: true // 默認(rèn)選中
			},
			{
				name: "green"
			},
			new inquirer.Separator("--- 分隔符 ---"), // 自定義分隔符
			{
				name: "yellow"
			}
		]
	},{
		type:"password",
		message:"請(qǐng)輸入你的游戲密碼:",
		name:"pwd"
	}
	
]
inquirer.prompt(prompList).then(answers=>{
	console.log(answers);
})

命令行交互如下:

淺出chalk.js

最后我們引入chalk這個(gè)美化命令行的模塊,它具有輕量級(jí)、高性能、學(xué)習(xí)成本低等特點(diǎn)。繼續(xù)在以上例子中引入chalk進(jìn)行輸出:

//命令行安裝
npm install chalk
//index.js引入
var chalk = require("chalk");

在inquirer里打印如下:

inquirer.prompt(prompList).then(answers=>{
	console.log(answers);
	console.log(chalk.green("考核完成"))//字體綠色
	console.log(chalk.blue("你最棒了"))//字體藍(lán)色
	console.log(chalk.blue.bgRed("五一放假嘍")) //支持設(shè)置背景
	console.log(chalk.blue(answers))
})

命令行最終顯示如下:

感興趣的話還是自己敲一下吧。

著陸

想讓別人來安裝你的cli工具,你需要把它發(fā)布到npm上,先在npm官網(wǎng)創(chuàng)個(gè)賬號(hào)(注意需要郵件驗(yàn)證),在命令行輸入npm adduser,依次填上你注冊(cè)的username、password、email。接著輸入npm publish即可:

輸入npm install -g exercise-clinpm install exercise-cli安裝一下你的cli感受它的魅力吧。

代碼已上傳至我的GitHub,歡迎Fork。

感謝

跟著老司機(jī)玩轉(zhuǎn)命令行

用node編寫cli工具

用commander.js構(gòu)建自己的腳手架工具

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/7346.html

相關(guān)文章

  • 玩轉(zhuǎn) Dcoker:Hello World, 開發(fā)環(huán)境和你應(yīng)用

    摘要:關(guān)于本文是一個(gè)開源的應(yīng)用容器引擎,讓開發(fā)者可以打包他們的應(yīng)用以及依賴包到一個(gè)可移植的容器中,然后發(fā)布到任何流行的機(jī)器上。比如說,通過堆棧來開發(fā)應(yīng)用的每個(gè)部分。開發(fā)環(huán)境之前提到的,能夠很容易的引入文件并且使用它們。 關(guān)于本文Docker 是一個(gè)開源的應(yīng)用容器引擎,讓開發(fā)者可以打包他們的應(yīng)用以及依賴包到一個(gè)可移植的容器中,然后發(fā)布到任何流行的 Linux 機(jī)器上。幾乎沒有性能開銷,可以很容...

    SillyMonkey 評(píng)論0 收藏0
  • 一個(gè)看一次就永遠(yuǎn)不會(huì)忘windows環(huán)境開發(fā)小技巧

    摘要:現(xiàn)實(shí)情況公司也不可能再給我配幾個(gè)屏幕,辛虧自開始可以在屏幕中實(shí)現(xiàn)分屏了。 前言:本人前端開發(fā),在日常開發(fā)中需要打開多個(gè)窗口進(jìn)行開發(fā),如:本地服務(wù)窗口,ide工具,設(shè)計(jì)圖,prd文檔,瀏覽器,瀏覽器調(diào)試工具; 如此多的窗口同時(shí)打開并且時(shí)常需要查看的情況下,遺憾的是,即使我是雙屏開發(fā)也有一種力不從心的感覺。現(xiàn)實(shí)情況公司也不可能再給我配幾個(gè)屏幕,辛虧自windows7開始可以在屏幕中實(shí)現(xiàn)分屏...

    DevWiki 評(píng)論0 收藏0
  • 一個(gè)看一次就永遠(yuǎn)不會(huì)忘windows環(huán)境開發(fā)小技巧

    摘要:現(xiàn)實(shí)情況公司也不可能再給我配幾個(gè)屏幕,辛虧自開始可以在屏幕中實(shí)現(xiàn)分屏了。 前言:本人前端開發(fā),在日常開發(fā)中需要打開多個(gè)窗口進(jìn)行開發(fā),如:本地服務(wù)窗口,ide工具,設(shè)計(jì)圖,prd文檔,瀏覽器,瀏覽器調(diào)試工具; 如此多的窗口同時(shí)打開并且時(shí)常需要查看的情況下,遺憾的是,即使我是雙屏開發(fā)也有一種力不從心的感覺?,F(xiàn)實(shí)情況公司也不可能再給我配幾個(gè)屏幕,辛虧自windows7開始可以在屏幕中實(shí)現(xiàn)分屏...

    idealcn 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<