摘要:命令行教程本文先介绍原生的实现命令行交互,了解原生的然后通过和实现一个完整的交互命令行工具。它是一个流也就是双工流,除非指向一个文件,在这种情况下它是一个可读流。命令行界面的完整解决方案,受启发。
node 命令行教程
本文先介绍原生的node.js实现命令行交互,了解原生的api,然后通过commander.js和inquirer.js实现一个完整的交互命令行工具。
项目地址
process对象是一个全局变量,它提供了当前node.js进程的信息并对其控制。因为其是一个全局变量所以无需在文件中引入。
需要用到的几个api
process.argv
process.cwd()
process.stdin
process.stdout
process.stdin.resume()
process.argvprocess.argv属性返回一个数组。数组的第一个值是process.execPath,第二个是正在执行的JavaScript的文件路径,其余参数为其它命令参数,这是我们来自定义命令的关键。
示例新建argv.js
// argv.js console.log(process.argv)
执行node命令 node argv.js
node argv.js --name zhu ## 输出 [ "/usr/local/bin/node", ## 执行当前脚本的Node二进制文件的绝对路径 "/Users/zhuhuilong/Node/Book/argv.js", ## 文件的绝对路径 "--name", ## 其余参数 "zhu" ]
接收自定义的命令参数进行处理输出
// argv.js console.log(process.argv) let argvs = process.argv let param = argvs.splice(2) if(param[0] && param[0] == "--name"){ if(param[1]){ console.log(`hello ${param[1]}`) }else{ console.log("请输入name") } }
运行argv.js
node argv.js --name zhu ## 输出 [ "/usr/local/bin/node", "/Users/zhuhuilong/Node/Book/argv.js", "--name", "zhu" ] hello zhu param [ "--name", "zhu" ]process.stdin与process.stdout
process.stdin(标准输入)
process.stdin 属性返回连接到 stdin (fd 0) 的流。 它是一个 net.Socket 流(也就是双工流),除非 fd 0 指向一个文件,在这种情况下它是一个可读流。
process.stdout(标准输出)
process.stdout 属性返回连接到 stdout (fd 1) 的流。 它是一个 net.Socket 流(也就是双工流),除非 fd 1 指向一个文件,在这种情况下它是一个可写流。
process.stdin.resume()一个指向 标准输入流(stdin) 的可读流(Readable Stream)。标准输入流默认是暂停 (pause) 的,所以必须要调用 process.stdin.resume() 来恢复 (resume) 接收。
作为流,process.stdin可以在旧模式下使用。为了兼容node v0.10以前的版本。在旧模式喜爱使用stdin必须调用process.stdin.resume()。注意如果调用了process.stdin.resume() stdin将转为旧模式。
通俗来讲就是控制台等待我们输入内容不退出进程,对输入输出进行交互。
新建inputout.js
// inputout.js process.stdin.setEncoding("utf8") let argvs = process.argv let param = argvs.splice(2) if (param[0] && param[0] == "--name") { if (param[1]) { console.log(`hello ${param[1]}`) } else { process.stdout.write(`请输入name:`) process.stdin.resume() process.stdin.on("data", chunk => { if (!!chunk.replace(/[ ]/g, "")) { process.stdout.write(`你输入的name是: ${chunk}`) process.stdin.emit("end") } else { process.stdout.write(`请输入name:`) } }) } } process.stdin.on("end", () => { process.stdout.write("结束 ") })
>执行node inputout.js --name
在新版本node模式下可以使用process.stdin.on("readable",()=>{})代替process.stdin.resume()恢复输入流接收。
示例:
process.stdin.on("readable", () => { var chunk = process.stdin.read(); console.log(typeof(chunk)) if (chunk !==null) { process.stdout.write(`data: ${chunk}`); process.stdin.emit("end"); } }); process.stdin.on("end", () => { process.stdout.write("end"); });
从上面的示例我们可以拿到process.argv参数对其进行处理交互,但如果要实现更复杂的命令交互,使用上面的方法会很吃力。下面我们使用commander.js和inquirer来实现一个完整的node命令行工具(创建项目模版)。
commander.jsnode.js命令行界面的完整解决方案,受Ruby Commander启发。
commander.js的API简述program.version() 声明版本
const program = require("commander") const pkg = require("../package.json") program.version(pkg.version)
Options 解析
使用.option()方法定义commander的选项options,也可以作为选项的文档。
var program = require("commander"); program .version("0.1.0") .option("-p, --peppers", "Add peppers") .option("-P, --pineapple", "Add pineapple") .option("-b, --bbq-sauce", "Add bbq sauce") .option("-c, --cheese [type]", "Add the specified type of cheese [marble]", "marble") .parse(process.argv); console.log("you ordered a pizza with:"); if (program.peppers) console.log(" - peppers"); if (program.pineapple) console.log(" - pineapple"); if (program.bbqSauce) console.log(" - bbq"); console.log(" - %s cheese", program.cheese);
添加自定义命令program.command()
var program = require("commander"); program .command("rm") //<>必选参数,如果是[]则是可选参数 .option("-r, --recursive", "Remove recursively") .action(function (dir, cmd) { console.log("remove " + dir + (cmd.recursive ? " recursively" : "")) }) program.parse(process.argv) // command()可变参数 /** 命令command有且只有最后一个参数可变不固定的。 要使参数变量可变,必须将...附加到参数名称。**/ program .version("0.1.0") .command("rmdir [otherDirs...]") .action(function (dir, otherDirs) { console.log("rmdir %s", dir); if (otherDirs) { otherDirs.forEach(function (oDir) { console.log("rmdir %s", oDir); }); } }); program.parse(process.argv);
program.action() 定义命令的回调函数
var program = require("commander"); program .command("rminquirer.js") .option("-r, --recursive", "Remove recursively") .option("-f, --force", "remove force") .action(function(dir, cmd) { // cmd为option参数选项 //console.log("cmd",cmd) if (cmd.recursive) { console.log("remove " + dir + " recursively"); } if (cmd.force) { console.log("remove " + dir + " forcefully"); } }); program.parse(process.argv);
Inquirer.js使用NodeJs做的一个通用交互式命令行用户界面的集合。具有常用的控制台交互操作。
由于交互的问题种类不同,inquirer为每个问题提供很多参数:
type:表示提问的类型,包括:input, confirm, list, rawlist, expand, checkbox, password, editor;
name: 存储当前问题回答的变量;
message:问题的描述;
default:默认值;
choices:列表选项,在某些type下可用,并且包含一个分隔符(separator);
validate:对用户的回答进行校验;
filter:对用户的回答进行过滤处理,返回处理后的值;
transformer:对用户回答的显示效果进行处理(如:修改回答的字体或背景颜色),但不会影响最终的答案的内容;
when:根据前面问题的回答,判断当前问题是否需要被回答;
pageSize:修改某些type类型下的渲染行数;
prefix:修改message默认前缀;
suffix:修改message默认后缀。
创建cli.jsconst program = require("commander") const inquirer = require("inquirer") const fs = require("fs") const path = require("path") const pkg = require("../package.json") const CWD = process.cwd() const promptList = [ { type: "list", message: "请选择一种模版", name: "template", choices: ["vue", "angular", "webpack-m-pages"], filter: function(val) { return val.toLowerCase() } } ] program .version(pkg.version) .command("create") .description("create project template") .action(function(dir, cmd) { const TEMPLATE_PATH = path.join(CWD, dir) if (fs.existsSync(TEMPLATE_PATH)) { } else { fs.mkdirSync(TEMPLATE_PATH) } if (dir) { inquirer.prompt(promptList).then(anwsers => { console.log(anwsers) }) } }) program.parse(process.argv)
运行 node cli/cli.js create vue
已经可以运行了,我们自定义一个命名替代每次都执行node
命令为:test-cli create
1、创建bin文件夹,在bin文件夹下创建index.js文件
#!/usr/bin/env node require("../cli/cli")
2、修改package.json文件
添加bin选项
"bin": { "test-cli": "./bin/index.js" },
3、执行npm link (如果没有权限,执行sudo npm link)
4、测试
5、发布 npm publish (如果未登录需先 npm login登录)
6、发布完毕,需npm unlink解除本地的命令映射
npm install -g XXX
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/109845.html
摘要:自阮大神的文章发布以来,有了一些改动,添加有很多有用的功能,特别是这个功能,对打造命令行工具集合非常有用,所以写一个新版本的教程还是有必要的。 前言 使用命令行程序对程序员来说很常见,就算是前端工程师或者开发gui的,也需要使用命令行来编译程序或者打包程序 熟练使用命令行工具能极大的提高开发效率,linux自带的命令行工具都非常的有用,但是这些工具都是按照通用需求开发出来的,如果有一些...
摘要:标准方法参数存在在中更多详情,可以参考官方链接。是一个包含命令行参数的数组。第一个元素是,第二个元素是文件的名称。接下来的元素将是任何附加的命令行参数。时间年月日前端教程打印将会输出以下结果时间年月日前端教程 标准方法参数存在在process.argv中 更多详情,可以参考官方链接。 process.argv 是一个包含命令行参数的数组。第一个元素是node,第二个元素是JavaScr...
摘要:是一种设计用于关系型数据库的查询语言。另一方面,数据库在最近十年变得相当流行。大多数数据库都有驱动程序可以用,它们在上也有库。我们已经完成了在中使用数据库所必须知道的所有基础知识。 本文转载自:众成翻译译者:网络埋伏纪事链接:http://www.zcfy.cc/article/1751原文:https://blog.risingstack.com/node-js-database-t...
摘要:项目环境搭建教程针对开发工具等一下载和下载链接中文官网下载好之后使用命令行再次确认查看顺便看看内置的版本如果是非安装包形式,安装的直接解压的,不是程序安装的形式,需要配置环境变量,必要时还需要配置要使用的版本出 ...
摘要:是将与以太坊交互的模块。在路由器内部我需要我的以太坊地址,我将发送我的交易地址,合约地址和合约。你可以通过以太坊钱包或搜索合约。我们为以太坊创建了我们的一个极小的后端。 注意:在本教程中我使用web3js 1.0版本 大家好,我将解释如何从NodeJS后端发送交易。我将使用rinkeby testnet并将创建一个路由器,还添加一些节点模块并使用infura http接口来完成教程...
阅读 954·2019-08-30 15:55
阅读 549·2019-08-26 13:56
阅读 2077·2019-08-26 12:23
阅读 3294·2019-08-26 10:29
阅读 598·2019-08-26 10:17
阅读 2866·2019-08-23 16:53
阅读 694·2019-08-23 15:55
阅读 2811·2019-08-23 14:25