Nodejs 製做命令行工具

wcj

github倉庫源碼下載 html

這不只是一篇教程,仍是經過命令行輸出我本身簡歷的一個工具O(∩_∩)O哈哈哈~,頗有趣的樣子哦。node

圖片描述

# 全局安裝,安裝報錯是須要前面加上sudo
$ sudo npm install -g wcj 

# 輸出幫助
$ wcj -h
  Usage: wcj 這裏是我私人玩耍的命令哦![options] <package>


  Commands:

    resume|rs [options] [cmd]    這裏是個人簡歷詳情!

  Options:

    -h, --help     output usage information
    -V, --version  output the version number

# 輸出子命令幫助
$ wcj rs -h

  Usage: resume|rs [options] [cmd]

    這裏是個人簡歷詳情!

  Options:

    -h, --help              output usage information
    -b, --basicinfo [type]  基本信息
    -e, --education [type]  教育經歷

  basicinfo 說明:

    preview 預覽簡歷

    -b, --basicinfo 基本信息
       name : 名字
       height : 身高
       dateOfBirth : 出生日期
       workExperience : 工做經驗
       mobile : 手機號碼
       telephone : 電話號碼
       email : 郵箱地址
       residency : 居住地點
       currentSituation : 現狀
       currentCity : 當前城市
       nation : 國家
       region : 地區
       postalCode : 郵編地址
       ID : 身份證ID
       website : 我的網賺
       maritalStatus : 婚姻情況
       politicalStatus : 政治面貌
    -e, --education 教育經歷

在使用 Nodejs 過程當中,有不少包都支持全局安裝,提供一個命令,而後在命令行咱們就能夠完成一些任務。有時候咱們也須要開發這樣的命令工具。在Node.js 中發現弄個命令行工具特別輕鬆,我來學習如何使用 Node.js 生成本身的command命令,在將來的項目中方便本身。python

  • 先弄個小實例感覺一下命令行的魅力git

  • 再用命令行實現輸出本身的簡歷(我以爲這個可能頗有趣)github

  • 經常使用的命令加入進來web

    • ls 查看當前目錄shell

    • ls -a 包括隱藏文件數據庫

    • 打開當前目錄npm

  • 就先這麼計劃着吧。json

小實例

開始編寫以前須要確認的一件事情是你已經安裝了Node.js。你能夠在命令行中運行 which node 來確認是否已經安裝,或者運行 node -v 查看 node 的版本 。若是你已經安裝了node,你能夠看到相似於下面的輸出結果,通常狀況安裝了node.js 順帶npm工具自動安裝了。

$ which node
/usr/local/bin/node  

$ node -v
v0.10.36

建立目錄

首先任意建立一個文件夾,初始化 package.json 文件,在該文件夾下建立bin目錄:

$ mkdir wcj #建立一個文件夾
$ cd wcj && mkdir bin
$ npm init #初始化 `package.json` 文件

編寫命令行

cd到 bin 目錄下,新建一個 wcj.js 文件(名字自取),編寫以下代碼,在js文件頂部加上 #!/usr/bin/env node 這段代碼:

#!/usr/bin/env node  
var fs = require("fs"),
    path = process.cwd();

var run= function (obj) {
    if(obj[0] === '-v'){
        console.log('version is 1.0.0');
    }else if(obj[0] === '-h'){
        console.log('Useage:');
        console.log('  -v --version [show version]');
    }else{
        fs.readdir(path, function(err, files){
            if(err){
                return console.log(err);
            }
            for(var i = 0; i < files.length; i += 1){
                console.log(files[i]);
            }
        });
    }
};
//獲取除第一個命令之後的參數,使用空格拆分
run(process.argv.slice(2));

上面的 #!/usr/bin/env node 被成爲 shebang ,表示用後面的路徑所示的程序來執行當前文件夾。還須要一個 package.json 文件

{
  "name": "wcj",
  "version": "1.0.0",
  "description": "wcj ---",
  "repository": {
    "type": "git",
    "url": "https://github.com/jaywcjlove/wcj.git"
  },
  "main": "index.js",
  "bin": { "wcj": "bin/wcj.js" },
  "author": "kenny wang <wowohoo@qq.com> ",
  "license": "MIT"
}

運行 node bin/wcj.js 會顯示當前文件夾下的因此文件和文件夾名。這個玩意兒真的跑起來了。更多npm link的信息請查看

package.json 文件中 bin 裏面的內容表示這個字段將 wcj 命令映射到了你的 bin/wcj.js 腳本。bin參考

此工具採用 npm版本號採用的 semver 規則

"bin": { "wcj": "bin/wcj.js" }

列子源碼

全局運行命令調試

確保你在 package.json 文件中添加了 bin 節點。而後打開命令了工具進入 wcj 目錄

install

若是在項目目錄下運行沒有問題,能夠將當前目錄模塊安裝到全局,也能夠採用此方法來更新你的命令行工具

sudo npm install . -g

link

或者目錄輸入 npm link 會自動添加全局的 symbolic link ,而後就可使用本身的命令了。

$ wcj
#README.md
#bin
#package.json

$ cmd -v
# version is 1.0.0

$ cmd -h 
#Useage:
#  -v --version [show version]

錯誤處理

在運行 sudo npm install . -g 會有一堆警告能夠忽視

若是你已經 npm link 搞了一遍你再 link 一遍,會報以下錯誤。即便你 npm unlink 也會報以下錯誤:

npm link
npm ERR! Darwin 14.3.0
npm ERR! argv "node" "/usr/local/bin/npm" "link"
npm ERR! node v0.10.36
npm ERR! npm  v2.7.1
npm ERR! path /usr/local/bin/wcj
npm ERR! code EEXIST

npm ERR! Refusing to delete: /usr/local/bin/wcj not in /Applications/XAMPP/xamppfiles/htdocs/git/github.com/myJS/wcj
File exists: /usr/local/bin/wcj
Move it away, and try again.

讓你刪除 /usr/local/bin/wcjnpm link , 刪除此目錄運行 rm -rf /usr/local/bin/wcj

發佈安裝

發佈到npm中

發佈必須註冊 npm 帳號,還有 github 帳號,具體怎麼玩兒問 谷歌大嬸吧。在JSLite.io 中也有教程哦。

npm publish

安裝

前提你發佈到了npm中,你就能夠運行下面的命令了。

sudo npm install -g wcj

例子下載:v1.0.1

Commander

依賴 nodejs 原生開發命令工具比較麻煩,Commander.js 能夠幫助咱們簡化命令行開發。Commander 是一款重量輕,表現力和強大的命令行框架。提供了用戶命令行輸入和參數解析強大功能。Commander 源自一個同名的Ruby項目。Commander.jsTJ 寫的一個幫助快速開發Nodejs命令行工具的package。TJ這貨是Nodejs社區裏很是知名的高產做者。方便的定義option(包括option的描述和其回調函數)和子命令。

特性

Commander的方便之處在於:

自記錄代碼、自動生成幫助、合併短參數(「ABC」==「-A-B-C」)、默認選項、強制選項​​、命令解析、提示符

API

Option(): 初始化自定義參數對象,設置「關鍵字」和「描述」
Command(): 初始化命令行參數對象,直接得到命令行輸入
Command#command(): 定義一個命令名字
Command#action(): 註冊一個callback函數
Command#option(): 定義參數,須要設置「關鍵字」和「描述」,關鍵字包括「簡寫」和「全寫」兩部分,以」,」,」|」,」空格」作分隔。
Command#parse(): 解析命令行參數argv
Command#description(): 設置description值
Command#usage(): 設置usage值

參考:官方文檔例子

安裝

安裝commander

sudo npm install commander

Option

內置選項Built-in option,Commander 會爲程序提供給一個默認的 -h option。

program
  .version('0.0.1')
  .option('-r, --resume', '簡歷');
program.parse(process.argv);

其中parse函數是處理定義的option和sub-command, 解析命令行參數並觸發相應的回調(下文會說)。

./bin/wcj.js -h
## 輸出下面內容
  Usage: wcj [options]

  Options:

    -h, --help     output usage information
    -V, --version  output the version number
    -r, --resume   簡歷

能夠看到默認就有個 -h 參數,傳入後會輸出 wcj 命令的幫助信息。

Custom option

wcj 命令增長一個 option,展現說明是個人簡歷。

program
  .version('0.0.1')
  .option('-r| --resume', '簡歷');
program.parse(process.argv);

if (program.resume) {
    console.log('簡歷 - '
        + '這個是個人簡歷!'
    );
}

option() 接收四個參數

  • 第一個參數中,-rshort option--resume爲對應的long option, 兩者的分割符是|或者,。在命令行裏使用時,這兩個是等價的。 區別是後者能夠在程序裏經過 program.resume 的方式取到該 option 的值,此處 option 的值爲 bool,也能夠爲字符串。

  • 第二個爲 option 描述, 會在 help 信息裏展現出來

  • 第三個參數爲回調函數

  • 第四個參數爲默認值

Unknown option

當接收到未定義的option時,程序會自動拋出錯誤

./bin/wcj.js -h

## 輸出下面內容
error: unknown option '--res'

Commander同時提供了api來取消這個自動報錯機制, .allowUnknownOption()

#!/usr/bin/env node
program
    .allowUnknownOption()
    .version('0.0.1')
    .option('-r, --resume', '簡歷');

program.parse(process.argv);
//省略一些細節...

Option types

Command支持如下兩種類型的option: requiredoptionalbool

required 和 optional

在option的第一個參數裏, 除了shortlong option,還能夠指定option類型,分隔符也是|, 其中

  • <lang> required參數,使用時後邊必須跟參數值, 不然程序會報錯

  • [db] optional參數,後面能夠選擇是否跟參數值

#!/usr/bin/env node  
var program = require('commander');
program
    .allowUnknownOption()
    .version('0.0.1')
    .option('-r, --resume', '簡歷')
    .option('-l, --language <lang>', '這個語言是我擅長的語言。')
    .parse(process.argv);

if (program.resume) {
    console.log('簡歷'
        + '-'
        + '這個是個人簡歷!'
    );
}

if (program.language) console.log('language: 我擅長的語言`' + program.language + '`');
if (program.database) console.log('db: 我擅長的語言`' + program.database + '`');

看下效果

./bin/wcj.js -l python
## 輸出
language: 我擅長的語言`python`
db: 我擅長的語言`MySQL`

./bin/wcj.js -l
## 輸出
  error: option '-l, --language <lang>' argument missing

bool

選項值爲布爾型, 像上面的--date, 默認是false,當使用此參數時,program.datetrue, 不然爲false

booloption有個變種,當long option定義爲no-*時默認值爲true, 將

var program = require('commander');
program
  .option('-d, --no-date', 'don‘t display current date')
  .parse(process.argv);

var dt = new Date();
if (program.date) {
    console.log(dt.getFullYear()
        + '-'
        + (dt.getMonth() + 1)
        + '-'
        + dt.getDate()
    );
}

不帶-d 參數時, 參數的默認值爲true

Automated --help

Commander會根據配置的option,sub-command等信息,自動生成help信息。

Custom help

能夠經過監聽--help事件來輸出額外的幫助信息,以下面給fe命令添加了一些examples

// must be before .parse() since node's emit() is immediate
program.on('--help', function () {
    console.log('  自定義的例子:')
    console.log('')
    console.log('    輸出命令  wcj -d')
    console.log('    輸出命令  wcj -l python')
    console.log('')
})

program.parse(process.argv);

效果以下:

./bin/wcj.js -h

  Usage: wcj [options]

  Options:

    -h, --help             output usage information
    -d, --no-date          display current time
    -l, --language <lang>  這個語言是我擅長的語言。
    -b, --database [db]    該數據庫爲我最擅長數據庫

  自定義的例子:

    輸出命令  wcj -d
    輸出命令  wcj -l python

像git風格同樣的命令

列子源碼

#!/usr/bin/env node 
var program = require('commander');
var appInfo = require('./../package.json');

program
    .version(appInfo.version)
    .usage('這裏是我私人玩耍的命令哦![options] <package>')

//像git風格同樣的子命令
program
    //子命令
    .command('resume <cmd>')
    //短命令 - 簡寫方式
    .alias('rs')
    //說明
    .description('這裏是個人簡歷詳情!')
    //resume的子命令
    .option("-n, --name <mode>", "輸出個人名字")
    //註冊一個callback函數
    .action(function(cmd, options){
        var nm = typeof options.name=='string'?options.name:""

        console.log('resume "%s" 使用 %s 模式', cmd, nm);
    }).on('--help', function() {
        //這裏輸出子命令的幫助
        console.log('  Examples:');
        console.log('    運行方法:');
        console.log('    $ ./bin/wcj.js resume ss -n aaaaa');
        console.log('    $ ./bin/wcj.js resume ss');
        console.log();
    });

program.parse(process.argv);

上面實例運行輸出方式

$ ./bin/wcj.js resume ss -n aaaaa

#輸出:
resume "ss" 使用 aaaaa 模式

$ ./bin/wcj.js resume ss
#輸出:
resume "aa" 使用  模式

事件監聽

命名多少個命令就監聽多少命令,--help 爲默認監聽事件。

program.on('--help', function(argv,test){
    process.exit(1);
});

yargs

命令行框架 yargs 和你的程序實現交互 yargs for github

var argv = require('yargs').argv;
if (argv.l == 'zh-cn') {
    console.log('Chinese site!');
}else if(argv.l == 'en') {
    console.log('English website!');
}

使用

var argv = require('yargs').argv;
if (argv.l == 'zh-cn') {
    console.log('Chinese site!');
}else if(argv.l == 'en') {
    console.log('English website!');
}

閱讀參考

第一個小實例看了不少文章,記錄一下,感受很是簡單的樣子。

相關文章
相關標籤/搜索