0、 指令行工具
當全局安裝子產品之後,我們可以在控制台下執行指定的指令來運作操作,如果npm一樣。我把這樣的子產品稱之為指令行工具子產品(如了解有偏頗,歡迎指正)
1、用Node編寫指令行工具
在Node中,我們很容易就能實作一個指令行工具。通過借助npm install -g安裝,就能直接調用指令行工具了。
1.1、建立項目
首先,指令行也是一個node程式,那麼首先通過npm init初始化一個Node項目。
json // package.json { "name": "newkit-cli", "version": "0.0.1", "description": "Newkit Management Tools", "main": "index.js", "scripts": { "test": "test" }, "author": "Jay", "license": "MIT" }
1.2、建立可執行代碼
在項目目錄下,建立src目錄,并在其中建立index.js檔案
javascript //src/index.js檔案内容 console.log('cli');
通過
node src/index
就可以執行到段代碼了,那如何用自定義指令來執行呢?
1.3、在package.json中配置自定義指令
在package.json中可以配置bin節點,當全局安裝的時候,該節點内容将會被注冊為自定義指令。
json { "name": "newkit-cli", "version": "0.0.1", "description": "Newkit Management Tools", "main": "index.js", "bin": { "nc": "./src/index.js" }, "scripts": { "test": "test" }, "author": "Jay", "license": "MIT" }
1.4、測試指令
假設我們已經寫好了指令行工具了,那我們應該如何測試呢?
我們可以通過
npm install -g
将目前子產品安裝到全局子產品中。然後再執行nc指令來測試。
通過如上步驟,我們發現并不能執行我們的index.js,這是為什麼呢?
因為我們并沒有指定用什麼工具來執行這條指令,是以應該怎麼做呢?打開index.js,然後加上一句代碼:
```javascript
!/usr/bin/env node
console.log('cli'); ``` 這句代碼什麼意思呢?這句代碼告訴系統,使用node來啟動我們的指令。此時再安裝,然後執行nc,你會發現,控制台會列印出cli。也就是我們index中代碼的執行結果。
至此,我們的一個最簡單的指令行執行就開發成功了。
2、處理指令行參數
單純的執行一個指令,似乎不滿足我們的實際運用場景,大部分時候我們會使用
nc version
、
nc xxx -a --b
之類的方式來使用指令。那應該如何擷取這些指令呢?
2.1、使用process來擷取控制台參數
将index.js代碼修改一下,如下: ```javascript
console.log('cli'); console.log(process.argv); ``` 安裝之後,再次執行
nc xxx -a --b true
,會看到如下的輸出:
cli [ 'C:\\Program Files\\nodejs\\node.exe', 'C:\\Users\\jh3r\\AppData\\Roaming\\npm\\node_modules\\newkit-cli\\src\\index.js', 'xxx', '-a', '--b', 'true' ]
從結果可以看到,我們所使用所有參數都會傳遞到程式中去,這個時候,我們就可以解析這些參數,來實作不同的輸出了。
2.2、使用Commander來開發指令行工具
從上面的輸出也可以看到,我們要手動去解析參數的話,還是一個比較複雜的操作。既然身處Node社群,那麼完全使用社群流行的包來幫我們簡化代碼。
Commander 是一款重量輕,表現力和強大的指令行架構。提供了使用者指令行輸入和參數解析強大功能。
Commander的友善之處在于:自記錄代碼、自動生成幫助、合并短參數(“ABC”==“-A-B-C”)、預設選項、強制選項、指令解析、提示符
我們可以在https://github.com/tj/commander.js/找到Commander。
繼續改造index.js檔案,修改内容為: ```javascript
var program = require('commander');
program .version('0.0.2') //提供指令行工具的版本号,可以通過-V擷取到 // 使用option方法注冊指令 .option('-i, --init [type]', 'Initial Newkit in current folder', (type) => { console.log('process', type, program.init); }, true) .option('-u| --update ', 'Update module.', (moduleName) => { //使用program.update 來擷取預設值,如果有指令行參數,那麼會作為回調函數的參數 console.log(moduleName, program.update); }, 'app-common')
.parse(process.argv); ``` 注意:以上代碼有較多注意的點
- option方法參數是四個,第一個是指令,第二個是描述,第三個是回調,第四個是指令的預設值
- 第一個參數中的-i和-u是短指令,--init和--update是長指令。長短指令之間的分隔符可以是
和|
,如果使用逗号分隔,那麼可以通過program.init來擷取預設值。,
- 在代碼中我們在指令中,注意到有
[type]
兩種,前者是可選參數,後者的必選參數。<module>
除此之外,還可以使用command方法來實作Git風格的子指令,代碼如下:
javascript program .command('update <module>') .action((module, options) => { console.log(module); });
更多功能,請自行測試
2.3、使用yargs來開發指令行工具
具體代碼如下:
var argv = require('yargs') .option('i', { alias : 'init', demand: true, default: '', describe: 'Project Init', type: 'string' }) .usage('Usage: nc init') .example('nc init', 'Initial newkit project') .help('h') .alias('h', 'help') .epilog('copyright 2015') .argv;
//根據不同的參數來做處理
``` yargs更多資訊請參閱:https://github.com/yargs/yargs
3、注意事項
- 根據Unix的傳統,程式執行成功傳回0,否則傳回1
javascript if(err){ return process.exit(1); } process.exit(0);
2. 系統信号
javascript process.on('SIGINT', function () { console.log('Got a SIGINT'); process.exit(0); }); //發送系統信号:$ kill -s SIGINT [process_id]