必知必会的Node-CLI开发基础
栏目: JavaScript · 发布时间: 6年前
内容简介:在NodeJS中可以通过以下代码获取命令行中传递的参数:但是这对于构建一个CLI工具远远不够,首先需要考虑参数输入的各种风格:这里可以通过正则表达式对process.argv进行加工:
在NodeJS中可以通过以下代码获取命令行中传递的参数:
process.argv.slice(2) 复制代码
但是这对于构建一个CLI工具远远不够,首先需要考虑参数输入的各种风格:
- Unix参数风格:前面加-,不过后面跟的是单个字符,例如-abc解析为['a', 'b', 'c']。
- GNU参数风格:前面加--,例如npm中的命令,npm --save-dev webpack。
- BSD参数风格:前面不加修饰符。
这里可以通过正则表达式对process.argv进行加工:
/** * 解析Unix、BSD和GNU参数风格 * @param {Array} argv 命令行参数数组 * @returns */ function parseArgv (argv) { const max = argv.length const result = { _: [] } for (let i = 0; i < max; i++) { const arg = argv[i] const next = argv[i + 1] if (/^--.+/.test(arg)) { // GNU风格 const key = arg.match(/^--(.+)/)[1] if (next != null && !/^-.+/.test(next)) { result[key] = next i++ } else { result[key] = true } } else if (/^-[^-]+/.test(arg)) { // Unix风格 const items = arg.match(/^-([^-]+)/)[1].split('') for (let j = 0, max = items.length; j < max; j++) { const item = items[j] // 非字母不解析 if (!/[a-zA-Z]/.test(item)) { continue } if (next != null && !/^-.+/.test(next) && j === max - 1) { result[item] = next i++ } else { result[item] = true } } } else { // BSD风格 result._.push(arg) } } return result } 复制代码
通过以上的方法可以得到如下结果:
node example1.js --save-dev -age 20 some // => 结果 { _: ['some'], 'save-dev': true, a: true, g: true, e: 20 } 复制代码
上面这个示例不仅仅为了展示解析的结果,而且还强调了Unix参数风格只解析单个字母,所以这种风格的参数可能表达的意思不太明确并且数量有限,那么就需要在正确的场景中使用这种风格的参数:
npm --save-dev webpack npm -D webpack 复制代码
npm中采用Unix参数风格表示简写,这就是一种很恰当的方式,那么前面示例中的-age按照语义应该改为--age更加合理一点。
二、命令行界面
NodeJS中的readline模块提供question和prompt方法构建命令行界面,下面是一个简单的问答式的交互界面:
const readline = require('readline'); const question = ['请输入您的姓名', '请输入您的年龄'] const result = [] const rl = readline.createInterface({ input: process.stdin, output: process.stdout, prompt: `?${question[0]} ` }); rl.prompt(); rl.on('line', (line) => { result.push(line.trim()) const max = result.length if (max === question.length) { rl.close() } rl.setPrompt(`?${question[max]} `) rl.prompt(); }).on('close', () => { console.log(`谢谢参与问答 *** 姓名: ${result[0]} 年龄: ${result[1]}`); process.exit(0); }); 复制代码
当然交互界面的元素并不只有这一种,在使用各类CLI工具时,你应该会遇到诸如:单项选择、下载进度条...
下面可以尝试实现一个单项选择交互界面:
const readline = require('readline') let selected = 0 const choices = ['javascript', 'css', 'html'] let lineCount = 0 const rl = readline.createInterface(process.stdin, process.stdout) function reader () { let str = '' for (let i = 0; i < choices.length; i++) { lineCount++ str += `${selected === i ? '[X]' : '[ ]'} ${choices[i]}\r\n` } process.stdout.write(str) } reader() process.stdin.on('keypress', (s, key) => { const name = key.name const max = choices.length if (name === 'up' && selected > 0) { selected-- } else if (name === 'down' && selected < max - 1) { selected++ } else if (name === 'down' && selected === max - 1) { selected = 0 } else if (name === 'up' && selected === 0) { selected = max - 1 } else { return true } // 移动光标,并且删除光标右边的内容 readline.moveCursor(process.stdout, 0, -lineCount) readline.clearLine(process.stdout, -1) lineCount -= choices.length reader() }) rl.on('line', () => { console.log(`you choose ${choices[selected]}`) process.exit(0) }).on('close', () => { rl.close() }) 复制代码
三、定制样式
为了有效的区别命令行界面中信息的差异性,我们可以为这里输出信息添加适当的样式。
这里介绍一下字符串添加样式的语法:
\x1b[背景颜色编号;字体颜色编号m 复制代码
每条样式都要以\x1b[开头:
// \x1b[0m 清除样式 process.stdout.write('\x1b[44;37m OK \x1b[0m just do it\n') 复制代码
四、自定义Node命令
接下来就是自定义Node命令,首先需要创建一个命令执行的文件:
// hello.js 首行需要指定脚本的解释程序 #!/usr/bin/env node console.log('hello') 复制代码
再利用package.json中的bin配置:
{ "bin": { "hello": "./hello.js" }, } 复制代码
执行npm的link命令:
npm link # 输入自定义命令 hello # 输出 hello 复制代码
五、总结
上面介绍了开发Node-CLI时所需要的一些基本知识,但是对于用过诸如webpack-cli、vue-cli工具的你可能会发现这些优秀的CLI工具还具有:
- git风格的子命令;
- 自动化的帮助信息;
- ....
那么下面这些成熟的框架会给你很大的帮助:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- springmvc教程--注解开发基础详解
- C++开发EOS基础指南
- flume 1.8.0 开发基础
- 移动端开发基础知识扫盲
- 业务开发转基础开发,这三种 “高可用” 架构你会么?
- Python开发【第二章】入门基础
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。