您现在的位置是:网站首页> 编程资料编程资料
node实现shell命令管理工具及commander.js学习_node.js_
2023-05-24
911人已围观
简介 node实现shell命令管理工具及commander.js学习_node.js_
背景、
github 地址: https://github.com/lulu-up/record-shell
你有没有经历过忘记某个shell命令怎么拼写? 或是懒得打一长串命令的经历? 比如我的mac笔记本的tachbar偶尔会'卡死', 这时我就要输入 killall ControlStrip 命令重启tachbar, 你也看到了这个命令真心懒得打。
还有新建react项目我每次都要输入npx create-react-app 项目名 --template typescript, 在公司的日常开发中我习惯每次写新需求都单独clone项目并创建新的分支进行开发, 此时就需要去gitlab上复制项目地址然后在本地git clone xxxxxxxxxx 新的项目名, 理论上这些操作真的很重复。
首先本次要带你用node一起动手做一款记录shell命令的小插件, 当然网上类似插件也是有的, 但我这次做了一个最简单粗暴的版本, 自己用着也爽的版本, 并且也想趁机温习一遍命令行相关知识。
一、用法演示
先一起看看这个'库'是否真的方便:
1: 安装
npm install record-shell -g
安装完毕你的全局会多出 rs命令:

2: 添加
rs add
起名随意, 甚至全用汉语更舒服, 这里先演示输入简单命令:

3: 查看 + 使用'
rs ls

命令是可选择的, 这里我先多加几个凑所的命令用来演示:

可以按上下键移动选择, 回车即可执行命令:

当然也可以查看命令详情, 只需-a参数:
rs ls -a

4: 移除
rs rm


5: add有变量的命令
我们的命令当然不会都是写'死'的模式啦, 比如命令 echo 内容 > a.txt, 这里的意思是我要把内容写入目标文件:

6: 使用变量
使用命令时会引导我们填入变量, 所以定义时写汉语就行:



二、初始化自己的node项目
接下来一起从零开始做出这个库, 考虑到一些新手同学可能没做过这种全局的node包, 我这里就讲的详细一些。
初始化项目没啥好说的, 随便起名:
npm init
改造package.json文件:
"bin": { "rs": "./bin/www" },这里在 bin内指明, 当运行 rs 命令的时候, 访问"./bin/www"。

#! /usr/bin/env node require('../src/index.js')#!这个符号通常在Unix系统的基本中第一行开头中出现,用于指明这个脚本文件的解释程序。/usr/bin/env因为可能大家会把node安装到不同的目录下, 这里直接告诉系统可以在PATH目录中查找, 这样就兼容了不同的node安装路径。node这个自不必说, 就是去查找咱们的node命令。
三、初始化命令 + 全局安装
这里讲一下如何将我们的命令挂在到全局, 使你可以在任何地方都能使用全局的rs命令:
// cd 我们的项目 npm install . -g
这里比较好理解吧, 相当于直接把项目安装在了全局, 我们平时install xxx -g 是去远端拉取, 这个命令是拉当前目录。
此时那你向index.js文件内写入console.log('全局执行'), 再全局执行 rs 并看到如下效果就是成功了:

四、commander.js (node命令行解决方案)
先安装再聊:
npm install commander
commander的可以帮我们非常规范的处理用户的命令, 比如用户在命令行输入rs ls -a, 原生node的情况下我可以先将输入的args进行拆解, 拆解出 ls 与 -a, 然后再写一堆if判断如果是ls并且后面有-a则如何去做, 但显然这样写不规范, 代码也难以维护, commander就是来帮我们规范这些写法的:
将下面的代码放进 index.js文件中:
const fs = require("fs"); const path = require("path"); const program = require('commander'); const packagePath = path.join(__dirname, "../package.json") const packageData = JSON.parse(fs.readFileSync(packagePath, 'utf-8')); program.version(packageData.version) program .command('ls [-type]') .description('description') .action((value) => { console.log('你输入的是:', value) }) program.parse(process.argv)在命令行输入:
rs ls 123456

逐句解释一下代码:
const program = require('commander')这里很明显引入了commander。program.version(packageData.version)此处是定义了当前库的版本, 当你输入rs -V时会展示program.version方法获取到的值, 此处直接使用了package.json里面的version字段。program.command('ls')定义了名为ls的参数, 当我们输入rs ls时才会触发我们后面的处理方法, 我之所以写成program.command('ls [-type]')是因为加上[-type]后commander才会认为ls命令后面可以跟其他参数, 当然你叫[xxxxx]也可以, 让使用者能看懂即可。
.description('description')顾名思义这里是简介描述, 当我们输入rs -h的时候会出现:

.action方法就是commander检测到当前命令触发时的处理函数, 第一个参数是用户传入的参数, 第二个参数是Command对象, 后续我们会在这里弹出选择列表。process.argv这里要先知道process是node中的全局变量, 其中argv是启动命令行时的所有参数。program.parse(process.argv)看完上面这里就好理解了, 将命令行参数传递给commander开始执行。
番外
如果你配置program.option('ls', 'ls的介绍'), 则当用户输入rs -h时会出现, 但我感觉加了有点乱, 咱们的插件追求简单所以就没加。
五、inquirer.js(node命令行交互插件)
npm install inquirer
inquirer可以帮我们生成各种命令行问答功能, 就像vue-cli差不多的效果, 大家可以输入下面代码试一试'单选模式':
program .command('ls [-type]') .description('description') .action(async (value) => { const answer = await inquirer.prompt([{ name: "key", type: "rawlist", message: "message1", choices: [ { name: 'name1', value: 'value1' }, { name: 'name2', value: 'value2' } ] }]) console.log(answer) })

逐句解释一下代码:
- 首先这里是一个
async与awite的模式。 inquirer.prompt参数是一个数组, 因为它可以连续操作, 比如进行两次单选列表操作。name就是最终的key, 比如name为xxxx用户选择了1, 则最终返回结果就是{xxxx:1}。type指定交互类型rawlist单选列表、input输入、checkbox多选列表等。message就是提示语, 我们让用户选择之前总要告诉他这里在做啥吧。choices选项的数组,name选项名,value选项值。
六、添加命令: add
正式开始做第一个命令, 我新建了一个名为env提示:
本文由神整理自网络,如有侵权请联系本站删除!
本站声明:
1、本站所有资源均来源于互联网,不保证100%完整、不提供任何技术支持;
2、本站所发布的文章以及附件仅限用于学习和研究目的;不得将用于商业或者非法用途;否则由此产生的法律后果,本站概不负责!
