前言
每次看到一些庫npm -g install xx
然后,執行xx
就可以跑起來,這不就是一個shell工具了嗎,那么我不就可以不用學習shell語法,直接用js寫命令行腳本了嗎!
什么是REPL應用
所謂的repl應用就是一個終端命令行工具,如果使用linux對於命令行工具例如curl,awk,grep,find,這些肯定不陌生,而現在,我們就是用node去寫類似這樣的程序
讀取-求值-輸出
對於第一次動手寫repl應用,我們首先,了解一些知識點.
Process api
process 對象在node里面是全局對象,不需要用require引入,直接使用
console.log(process)
我們就可以在終端里面看到process都有些什么內容了.對於,開發一個repl應用,我們對於process對象只需要了解以下下幾點就行
- process.argv //這次輸入值集合
- process.stdout.* //終端輸出方法
- process.stdin.* //終端輸入方法
- process.exit(); // 退出
對於process的了解這幾點大部分repl應用都可以開發了,接下來,我們說說,如何讓命令行工具讀取參數.
讀取
對於repl而言,值讀取的常見的一般有兩種:
配置值
1 2 3 4 5 6 7 8 9 10 |
#!/usr/bin/env node if(process.argv[2] === '-w'){ var args = process.argv.slice(3); var output = ''; args.forEach(function (item){ output += item + ' '; }) console.log(output); process.exit(); } |
node repl.js -w Hello world!
Hello world!
交互式
1 2 3 4 5 6 7 8 9 10 11 12 |
#!/usr/bin/env node function read(prompt) { process.stdout.write(prompt + ':'); process.stdin.resume(); process.stdin.setEncoding('utf-8'); process.stdin.on('data', function(chunk) { process.stdout.write('output: ' + chunk); process.exit(); }); } read('input') |
node repl.js
input: Hello world!
output: Hello world!
repl 應用本質其實就是一個shell腳本,現在我們要用node來寫,所以,對於*nix環境我們必須在第一行說明我們的文件需要在什么環境下運行.
#!/usr/bin/env node
process.argv
我們主要從命令行輸入值都是從process.argv
里面讀取,這個對象,保存了我們所有命令行的輸入,我們可以打印出來看看
console.log(`process.argv)
1 2 3 4 [ 'node', 'E:\\ProjectGitHub\\node.js\\repl.js', '-w', 'Helloworld!' ]
從這個輸出我們就可以很明了的知道我們為什么要用process.argv.slice(3);
來獲取值了.
process.stdout && process.stdin
這兩個方法用於對終端輸出和輸入的操作,上面的例子應該很好演示這個使用了,這里就不再贅述了.
求值 & 輸出
實戰演練
現在要講的這個repl應用就是簡單的在終端中顯示前端亂燉的專欄列表.效果如下(PS:綠色那些是debug輸出,你自動忽略吧...):
輸入
htmljs article
輸入htmljs article -p 1
內容准備
這里用到了request
,cheerio
對前端亂燉頁面進行解析,這塊的討論已經超出了本文的討論范圍,以后放在介紹cheerio
的時候再說這塊的實現.
用命令行看前端亂燉專欄列表:
利用Commander處理輸入
對於如何在終端輸入參數,在上面的讀取篇已經全部介紹完畢,用原生process
處理輸入異常的繁瑣,對於這點,TJ大神寫了一個模塊commander
用來處理.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#!/usr/bin/env node var program = require('commander'), htmljscli = require('../index'), libInfo = require('../package'); program .version(libInfo.version) program .command('article') .description('show article list') .option('-p, --page [page]', 'article list') .action(function(options){ htmljscli.listArticle(options.page) }); program.parse(process.argv); // 這行必須是結尾 |
不到20行代碼就可以解決了原本需要各種處理process.argv
情況,而且還很貼心了幫我們自動生成help介紹
htmljs article -h
使用commander
我們只需要了解一下幾點就可以了
- commander.option()
用於將對象值對象化, 例如上文定義的
commander .option('-p, --page [page]', 'article list')
我們輸入的時候-p
的時候,就可以用options.page
獲取我們的參數
- commander.command().option().action()
用於配置子命令
發布
有時候,一些庫會要求我們
npm -g install cnpm
然后很神奇的發現可以
cnpm install xx
這類的操作,那我們發布的包怎么實現這個神奇的魔法呢.原理非常簡單,我們只需要在我們的package.json
加入以下幾句就行
1 2 3 4 5 |
{ "bin": { "htmljs": "./bin/htmljscli" } } |
用npm
安裝的時候就會自動與當前系統環境進行綁定.
接下來我們只需要
npm -g install html-js-cli
運行
htmljs article
就可以在終端看到專欄列表了
值得注意的時候,在windows
發布你寫node repl應用,*nix
用戶安裝的時候,命令並不會起作用,所以,要用npm
發布repl應用的時候請使用*nix
系統