win-cli成長之Commander.js學習

前言

應公司要求準備弄一個cli,那就暫定爲win-cli吧~
然而發現有不少不了解的東西,學習的東西也挺多的,那就慢慢啃吧(慢慢吭是不闊能的...)~哈哈
首先就是commander了。node

什麼是commander

關於github上的介紹,這是一個node命令行接口的解決方案,那確定是和node相關的東東啦。
咱們就按照github上的英文文檔來吧!!(英文菜雞一個...而後發現有中文的README,哈哈),仍是手敲一遍增強記憶吧。git

安裝

npm install commander

聲明program變量

Commander爲了方便快捷編程導出一個全局對象。github

const program = require('commander')
program.version('0.0.1')

對於可能以多種方式使用commander的大型程序,包括單元測試,最好建立一個本地commander對象來使用。npm

const commander = require('commander')
const program = new commander.Command()
program.version('0.0.1')

選項

.option()方法用來定義帶有選項的commander,同時也用於這些選項的文檔。每一個選項能夠有一個短標識(單個字符)和一個長名字,它們之間用逗號或者空格分開。編程

選項(第二個參數)會被放到commander對象的屬性上,多詞選項如「--template-engine」會被轉爲駝峯法"program.templateEngine"。多個短標識能夠組合爲一個參數,如「-a -b -c」等價於「-abc」。數組

program.option('選項命令','描述', '選項處理函數', '默認值')

經常使用選項類型,boolean和值

最經常使用的兩個選項類型是boolean(選項後面不跟值)和選項跟一個值(用尖括號聲明)。除非在命令行中指定,否者二者都是undefinedapp

const program = require('commander')
program
    .option('-d, --debug', 'output extra debugging')
    .option('-s --small', 'small pizza size')
    .option('-p, --pizza-type <type>', 'flavour of pizza')
program.parse(process.argv)

if(program.debug) console.log(program.opts())
console.log('pizza details:');
if (program.small) console.log('- small pizza size');
if (program.pizzaType) console.log(`- ${program.pizzaType}`);

默認選項值

能夠爲選項設置一個默認值。函數

const program = require('commander')

program
    .option('-c, --cheese<type>', 'add the specified type of cheese', 'blue')
    
program.parse(process.argv)
console.log(`cheese:${program.cheese}`)

program.parse(arguments)會處理參數,沒有被使用的選項會被存放在program.args數組中。工具

$ pizza-options
cheese: blue
$ pizza-options --cheese stilton
cheese: stilton

其餘選項類型,可忽略的布爾值和標誌值

選項的值偉boolean類型時,能夠在其加長名字前加no-規定這個選項值偉false。單獨定義一樣使選項默認爲真。
若是你先定義了--foo,再加上--no--foo並不會改變它原本的默認值。你能夠爲Boolean類型的標識指定一個默認的布爾值,從命令行裏能夠重寫它的值。單元測試

const program = require('commander');

program
  .option('--no-sauce', 'Remove sauce')
  .option('--cheese <flavour>', 'cheese flavour', 'mozzarella')
  .option('--no-cheese', 'plain with no cheese')
  .parse(process.argv);

const sauceStr = program.sauce ? 'sauce' : 'no sauce';
const cheeseStr = (program.cheese === false) ? 'no cheese' : `${program.cheese} cheese`;
console.log(`You ordered a pizza with ${sauceStr} and ${cheeseStr}`);

你能夠指定一個用做標誌的選項,它能夠接受值(使用方括號聲明,即傳值不是必須的)

const program = require('commander')

program
    .option('-c, --cheese [type]', 'ADD CHEESE WITH OPTIONAL TYPE')
program.parse(process.argv)

if(program.cheese === undefined) console.log('NO CHEESE');
else if(program.cheese === true) conosle.log('ADD CHEESE');
else console.log(`ADD CHEESE TYPE ${program.cheese}`)

自定義選項處理

你能夠指定一個函數來處理選項的值,接受兩個參數:用戶傳的值,上一個值(previous value),它會返回新的選項值。

版本選項

version方法會處理現實版本命令,默認選項標識爲-V--version,當存在時會打印版本號並退出。

program.version('0.0.1')

你能夠自定義標識,經過給version方法再傳遞一個參數,語法與option方法一致。版本標識名字能夠是任意的,可是必需要有長名字。

program.version('0.0.1', '-v, --version', 'output the current version')

Commands

你可使用.command爲你的最高層命令指定子命令。這裏咱們有兩種方法能夠實現:

  • 爲命令綁定一個操做處理程序(action handler)
  • 將命令單獨寫成一個可執行文件。

.command的第一個參數你能夠指定命令的名字以任何參數。參數能夠是<required>必須或者[optional]可選,而且最後一個參數也能夠是variadic...可變

//經過綁定操做處理程序實現,這裏description的定義和.command是分開的
//返回新生成的命令,即該子命令,以供繼續配置
program
    .command('clone <source> [destination]')
    .description('clone a repository into a newly created directory')
    .action((source, detination) => {
        console.log('cloen command called')
    })
    
//經過單獨分離的可執行文件實現命令(注意這裏description是做爲.command的第二個參數)
//返回最頂層的命令以供繼續添加子命令
program
    .command('start <service>', 'start named service')
    .command('stop [service]', 'stop named service, or all if no name supplied')

指定參數語法

你能夠經過.arguments來爲最頂級命令指定參數,對於子命令來講參數都包括在.command調用之中的。尖括號(e.g.<required>)意味着必須的輸入,而方括號(e.g.[optional])則表明了可選的輸入。

var program = require('command')

program
    .version('0.0.1')
    .arguments('<cmd> [env]')
    .action(fucntion(cmd, env) {
        cmdValue = cmd
        envValue = env
    })
program.parse(process.argv)

//使用
win 'cmd' 'env'

一個命令有且僅有最後一個參數是可變的,你須要在參數名後加上...來使他可變,例如:

var program = require('commander')

program
    .version('0.1.0')
    .command('rmdir <dir> [otherDirs...]')
    .action(function(dirm otherDirs){
        if(otherDirs) {
            otherDirs.forEach(function(oDir){
                console.log('rmdir %s', oDir)
            })
        }
    })
program.parse(process.argv)

操做處理程序(Action handler)(子)命令

你可使用操做處理程序爲一個命令增長選項options。操做處理程序會接收每個你聲明的參數的變量,和一個額外的參數--這個命令對象本身。這個命令的參數包括添加的命令特定選項的值。

var program = require('commander')

program
    .command('rm <dir>')
    .option('-r, --recursive', 'REMOVE RECURSIVELY')
    .action(function(dir, cmdObj) {
        console.log('remove ' + dir + (cmdObj.recursive ? ' recursively' : ''))
    })
program.parse(process.argv)

當一個命令在命令行上被使用時,它的選項必須是合法的。使用任何未知的選項會報錯。然而若是一個基於操做的命令沒有定義任何操做,那麼這些選項是不合法的。

定義配置選項能夠隨着調用 .command() 傳遞。 爲 opts.noHelp 指定 true 則該命令不會出現生成的幫助輸出裏。

Git風格的子命令

.command()帶有描述參數時,不能採用.action(callback)來處理子命令,不然會出錯。這告訴commander,你將採用單獨的可執行文件做爲子命令,就像git(1)和其餘流行的工具同樣。Commander將會嘗試在入口腳本(例如:./examples/pm)的目錄搜索program-command形式的可執行文件,例如pm-install, pm-search。你能夠是用配置選項executableFile來指定一個自定義的名字。

你能夠在可執行文件裏處理可執行子命令的選項,而沒必要在頂層聲明他們

// file: ./examples/pm
var program = require('commander');

program
  .version('0.1.0')
  .command('install [name]', 'install one or more packages')
  .command('search [query]', 'search with optional query')
  .command('update', 'update installed packages', {executableFile: 'myUpdateSubCommand'})
  .command('list', 'list packages installed', {isDefault: true})
  .parse(process.argv)

自動化幫助信息 --help

幫助信息是 commander 基於你的程序自動生成的,下面是 --help 生成的幫助信息:

Options:
  -V, --version        output the version number
  -p, --peppers        Add peppers
  -P, --pineapple      Add pineapple
  -b, --bbq            Add bbq sauce
  -c, --cheese <type>  Add the specified type of cheese (default: "marble")
  -C, --no-cheese      You do not want any cheese
  -h, --help           output usage information

自定義幫助

你能夠經過監聽 --help來控制-h, --help顯示任何信息。一旦調用完成,Commander將自動退出,你的程序的其他部分不會展現。
例如在下面的 「stuff」 將不會在執行 --help 時輸出。

var program = require('commander');

program
  .version('0.0.1')
  .option('-f, --foo', 'enable some foo')
  .option('-b, --bar', 'enable some bar')
  .option('-B, --baz', 'enable some baz');

// must be before .parse() since
// node's emit() is immediate

program.on('--help', function(){
  console.log('');
  console.log('Examples:');
  console.log('  $ custom-help --help');
  console.log('  $ custom-help -h');
});

program.parse(process.argv);

console.log('stuff');

.outputHelp(cb)

輸出幫助信息的同時不退出。可選的回調可在顯示幫助文本後處理。若是你想顯示默認的幫助。你可使用相似的東西。

var program = require('commander');
var colors = require('colors');

program
  .version('0.1.0')
  .command('getstream [url]', 'get stream URL')
  .parse(process.argv);

if (!process.argv.slice(2).length) {
  program.outputHelp(make_red);
}

function make_red(txt) {
  return colors.red(txt); //display the help text in red on the console
}

.helpOption(flag, description)

重寫覆蓋默認的幫助標識和描述

program
  .helpOption('-e, --HELP', 'read more information');

.help(cb)

輸出幫助信息並當即退出。 可選的回調可在顯示幫助文本後處理。

自定義事件監聽

你能夠經過監聽命令和選項來執行自定義函數。

// 當有選項verbose時會執行函數
program.on('option:verbose', function () {
  process.env.VERBOSE = this.verbose;
});

// 未知命令會報錯
program.on('command:*', function () {
  console.error('Invalid command: %s\nSee --help for a list of available commands.', program.args.join(' '));
  process.exit(1);
});
相關文章
相關標籤/搜索