——————————☆☆☆——————————
Node 系列相应地址:
- 代码仓库:https://github.com/LiangJunro...
- 文章仓库:https://github.com/LiangJunro...系列-前端材料/Node
——————————☆☆☆——————————
commander.js
—— 残缺的 Node.js
命令行解决方案。
本篇文章解说如何通过 commander.js
溜达 Node.js 命令行。
一 前言
当一个 Node.js
程序运行时,会有许多存在内存中的全局变量。
其中 process
作为过程对象,它有一个 argv
属性,能够查看到指令。
咱们轻易建一个 index.js
举例,终端执行命令:node index.js --name jsliang
index.js
console.log(process.argv);/* [ 'C:\\Program Files\\nodejs\\node.exe', 'F:\\jsliang\\index.js', '--name', 'jsliang' ]*/
看打印的数据:
Node
地位:C:\\Program Files\\nodejs\\node.exe
- 以后代码门路:
F:\\jsliang\\index.js
- 参数 1:
--name
- 参数 2:
jsliang
所以,在咱们写命令行程序的时候,只须要对 process.argv
这个数组的第三个元素及其之后的参数进行解析即可。
如果不嫌麻烦,齐全能够写出很多判断分支来做。
然而,有现成的为啥还要本人写,能偷懒就偷懒啊~
二 commander.js
commander.js
是 tj
写的一个工具包,作用是让 Node
命令行程序的制作更加简略:
- GitHub:commander
懂你,中文 README 奉上:https://github.com/tj/command...
上面咱们开始操作:
初始化
package.json
:npm init --yes
- !!【注】如果是依照 Node 系列程序学习的,这个步骤能够省略
- !!【注】上面代码能够建一个
test
空文件夹来耍耍
- 安装包:
npm i commander
- 编写指令文件:
index.js
const program = require('commander');program .version('0.0.1') .description('小工具指令清单') .option('-s, --sort <path>', '排序功能', '')program.parse(process.argv);
package.json(主动生成)
{ "name": "test", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "commander": "^7.2.0" }}
这份代码的逻辑是:
- 援用
commander
- 形容
commander
的version
等参数 - 用
commander
掌控process.argv
重点看看在这份代码中第 2 段的参数:
参数什么的看起来很焦躁,然而不理解又不晓得还能够怎么用
version
:版本- 用法:
.version('x.y.z')
- 用法:
description
:形容- 用法:
.description('小工具指令清单')
- 用法:
option
:选项- 用法:
.option('-n, --name <name>', 'your name', 'jsliang')
- 第一个参数是选项定义,能够用
|
,,
和' '
空格连贯 - 第二个参数为选项形容
- 第三个参数为选项参数默认值(可选)
- 用法:
所以上面咱们能够查看到一些信息。
- 执行命令:
node index.js -h
失去上面后果:
Usage: index [options]小工具指令清单Options: -V, --version output the version number -s, --sort <path> 排序功能 (default: "") -h, --help display help for command
这样咱们就实现了一些小指令,那么怎么操作呢?
- 排序:
node index.js -s "jsliang"
当然,这样感觉太怪了,能不能像日常开发一样,能够 npm run dev
、npm run xxx
的形式执行?
当然是能够的!
三 实际:文件重排性能
讲了那么多,做个小实际吧!
对于 Markdown 编写的文档库来说,如果你不设置文档程序,那么它就会依照零碎的规定来读取目录:
- 1.文章 1
- 10.文章 10
- 2.文章 2
- ……
当一个文件夹内容过多的时候,咱们心愿依照本人的程序让用户浏览,所以不能找零碎的来,因而须要用 Node 写个小工具,读取的时候依照心愿的排序来读取,这就是咱们开发小工具的初衷。
当然,还有个很重要的性能,就是当咱们心愿在第 1 篇和第 2 篇文章两头插入一篇文章的时候,例如:
- 1.文章 1
- 1-1.文章 1-1
- 2.文章 2
- ……
咱们还须要将这个目录构造进行从新排序,让新文章插入到指定地位。
3.1 实际目录
此时咱们的目录为:
+ docs + 3.目录c - 1.目录c1.md - 1-1.目录c2.md - 2.目录c3.md - 1.文章a.md - 2.文章b.md - 10.文章d.md+ src - config.ts - index.ts【已有】 - sortCatalog.ts- .eslintrc.js【已有】- package.json【已有】- tsconfig.json【已有】
该目录的 .eslintrc.js
、package-lock.json
、package.json
和 tsconfig.json
是主动创立的,TypeScript 的配置看前置文章,这里不做累述。
docs
目录下创立几个空 Markdown 文件,文件名照抄即可。
为了防止小伙伴误操作,还是截个图吧
3.2 编写 commander
退出 commonder
只须要往 package.json
和 index.ts
上配置即可。
- 初始化
package.json
:npm init --yes
(之前已配置) - 装置
commander
:npm i commander
package.json
{ "name": "jsliang", "version": "1.0.0", "description": "FE-util", "main": "index.js", "scripts": { "sort": "ts-node ./src/index.ts sort" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "@types/node": "^15.0.2", "@typescript-eslint/eslint-plugin": "^4.23.0", "@typescript-eslint/parser": "^4.23.0", "eslint": "^7.26.0", "ts-node": "^9.1.1", "typescript": "^4.2.4" }, "dependencies": { "commander": "^7.2.0" }}
留神 scripts
扭转了,记得复制过来
而后简略写写 index.ts
外面内容
src/index.ts
import program from 'commander';import { sortCatalog } from './sortCatalog';program .version('0.0.1') .description('工具库')program .command('sort <path>') .description('文件排序功能。示例:npm run sort "docs" 或者 npm run sort " C:/code/jsliang/src/docs"') .action((path: string) => { sortCatalog(`../${path}`); // 为了更便捷,先退一层到外边 });program.parse(process.argv);
3.3 编写排序功能
筹备好根底配置之后,只须要往 sortCatalog.ts
外面增加内容即可:
src/sortCatalog.ts
/** * @name 文件排序功能 * @time 2021-05-22 16:08:06 * @description 规定 1. 零碎程序 1/10/2/21/3,心愿排序 1/2/3/10/21 2. 插入文件 1/2/1-1,心愿排序 1/2/3(将 1-1 变成 2,2 变成 3)*/import fs from 'fs';import path from 'path';import { IGNORE_PATH } from './config';const recursion = (filePath: string, level = 0) => { const files = fs.readdirSync(filePath); files .filter((item => !IGNORE_PATH.includes(item))) // 过滤疏忽文件/文件夹 .sort((a, b) => Number((a.split('.')[0]).replace('-', '.')) - Number((b.split('.')[0]).replace('-', '.')) ) // 排序文件夹 .forEach((item, index) => { // 遍历文件夹 // 设置旧文件名称和新文件名称 const oldFileName = item; const newFileName = `${index + 1}.${oldFileName.slice(oldFileName.indexOf('.') + 1)}`; // 设置旧文件门路和新文件门路 const oldPath = `${filePath}/${oldFileName}`; const newPath = `${filePath}/${newFileName}`; // 判断文件格式 const stat = fs.statSync(oldPath); // 判断是文件夹还是文件 if (stat.isFile()) { fs.renameSync(oldPath, newPath); // 重命名文件 } else if (stat.isDirectory()) { fs.renameSync(oldPath, newPath); // 重命名文件夹 recursion(newPath, level + 1); // 递归文件夹 } });};export const sortCatalog = (filePath: string): boolean => { // 绝对路径 if (path.isAbsolute(filePath)) { recursion(filePath); } else { // 相对路径 recursion(path.join(__dirname, filePath)); } return true;};
有小伙伴看完必定好奇 config.ts
是什么,其实就是全局配置而已:
/** * @name 默认的全局配置 * @time 2021-05-22 16:12:21 */import path from 'path';// 根底目录export const BASE_PATH = path.join(__dirname, './docs');// 疏忽目录export const IGNORE_PATH = [ '.vscode', 'node_modules',];
当咱们没有配置的时候,就给默认的配置。
3.4 运行内容
OK,筹备结束,就能够耍起来了。
以后 docs
下目录构造为:
- 1.文章a.md- 10.文章d.md- 2.文章b.md- 3.目录c - 1-1.目录c2.md - 1.目录c1.md - 2.目录c3.md
而咱们运行 npm run sort "docs"
后,新目录列表变成了:
- 1.文章a.md- 2.文章b.md- 3.目录c - 1.目录c1.md - 2.目录c2.md - 3.目录c3.md- 4.文章d.md
这样,咱们简略的案例就做好啦!是不是非常简单!
四 罕用 commander 配置
上面例举下咱们十分不想看,然而失常应用又常见的 commander
配置:
version
:版本。用来设置命令程序的版本号- 用法:
.version('x.y.z')
- 用法:
description
:形容。用来设置命令的形容- 用法:
.description('小工具指令清单')
- 用法:
option
:选项。- 用法:
.option('-n, --name <name>', 'your name', 'jsliang')
- 第一个参数是选项定义,能够用
|
,,
和' '
空格连贯,参数能够用<>
(必填)或者[]
(选填)润饰 - 第二个参数为选项形容
- 第三个参数为选项参数默认值(可选)
- 用法:
command
:命令- 用法:
.command('init <path>', 'description')
command
用法略微简单,原则上承受 3 个参数,第一个为命令定义,第二个命令形容,第三个为命令辅助润饰对象- 第一个参数能够应用
<>
或者[]
润饰命令参数 第二个参数可选
- 当没有第二个参数时,
commander.js
将返回Command
对象 - 当带有第二个参数,将返回原型对象,并且没有显示调用
action(fn)
时,将会应用子命令模式 - 子命令模式:
./pm
、./pm-install
、./pm-search
等,这些子命令跟主命令在不同的文件中
- 当没有第二个参数时,
- 第三个参数个别不同,他能够设置是否显示应用的子命令模式
- 用法:
action
:动作。用来设置命令执行的相干回调- 用法:
.action(fn)
fn
能够接受命令的参数为函数形参,程序与command()
中定义的程序统一
- 用法:
parse
:解析process.argv
- 用法:
program.parse(process.argv)
- 这个 API 个别在最初调用,用来解析
process.argv
- 用法:
OK,commander
的简略介绍到此结束,咱们下期见!
五 参考文献
- Github:commander
- W3CSchool:应用commander.js做一个Nodejs命令行程序
jsliang 的文档库由 梁峻荣 采纳 常识共享 署名-非商业性应用-雷同形式共享 4.0 国内 许可协定 进行许可。<br/>基于 https://github.com/LiangJunrong/document-library 上的作品创作。<br/>本许可协定受权之外的应用权限能够从 https://creativecommons.org/licenses/by-nc-sa/2.5/cn/ 处取得。