颜色控制
实现原理
这个比较简单,写过 c 的应该知道控制命令行颜色,只需要 颜色宏定义 + 字体内容 拼接即可。这就是 chalk.js 的实现原理。
举个例子,对于\e[31;44;4;1m
来说,意义如下:
\e
代表开始ANSI Escape code
。就是ESC的转义符。在nodejs中,请用它的16进制码0x1B
[
代表转义序列开始符 CSI,Control Sequence Introducer31;44;4;1
代表以; 分隔的文本样式控制符,其中 31 代表文本前景色为红色,44代表背景为蓝色,4代表下划线,1代表加粗。m
代表结束控制符序列
在shell中,直接输入:echo -e "\e[37;44;4;1mLEO\e[0m"
;或者在nodejs中,输入:
process.stdout.write('\x1B[37;44;4;1mLEO\x1B[0m')
chalk.js 使用
相比于直接去拼写颜色宏定义,它提供更语义化的 api 将文本处理成拼接后的结果,然后交给控制台输出。
import chalk from 'chalk'
const print = console.log;
print(chalk.blue("Hello") + " World" + chalk.red("!"));
print(chalk.blue.bgRed.bold("Hello World!"));
进度控制
实现原理
「回车」不等于「换行」:
\r
回车,回到当前行的行首,而不会换到下一行,如果接着输出的话,本行以前的内容会被逐一覆盖\n
换行,换到当前位置的下一行,而不会回到行首
所以命令行的进度条,就是定时输出,每次输出的时候,最前面都带上\r
。这样就达到了清空当前行输出的目的。
这个就是 ora.js 的原理。
ora.js 使用
import ora from 'ora';
const spinner = ora({
text: "链接网络中"
}).start(); // 开始状态 => 加载状态
setTimeout(() => {
spinner.color = "yellow";
spinner.text = "网速有点慢";
}, 1000); // 还是 加载状态, 更新文案和颜色
setTimeout(() => {
spinner.succeed("下载成功"); // 加载状态 => 成功状态
}, 2000);
参数读取
实现原理
通过 process.argv
可以读取命令行参数。默认第一个是执行脚本,第二个是当前JS脚本文件的绝对路径。
比如 chalk.js 实现如下:
process.argv.forEach((val, index) => {
console.log(index, val)
})
通过命令行执行 node chalk.js -L abc --list=abc list=abc
,输出如下:
0 /usr/local/bin/node
1 /Users/0x98k/work/outside/stack-hugo/tmp/2022-04-11-nodejs-shell/chalk.js
2 -L
3 abc
4 --list=abc
5 list=abc
先读取命令后面的参数,然后依次解析,就是 commander.js 的实现原理。
commander.js 使用
方法一:注入 Options 以及对应的执行逻辑
import program from 'commander'
program
.version("0.0.1")
.option("-t, --types [type]", "test options")
// option这句话必须加
.parse(process.argv);
方法二:注入 Command 以及对应的执行逻辑
import program from 'commander'
// Commands 操作
program
// 命令与参数: <> 必填; [] 选填
.command("exec <cmd> [env]")
// 别名
.alias("ex")
// 帮助信息
.description("execute the given remote cmd")
// 没用,option和command是冲突的
// .option("-e, --exec_mode <mode>", "Which exec mode to use")
// 执行的操作
.action((cmd, env, options) => {
// 参数可以拿到
console.log(`env is ${env}`);
console.log('exec "%s" using %s mode', cmd, options.exec_mode);
})
// 自定义help信息
.on("--help", function() {
console.log("自定义help信息");
});
// 参数长度不够, 打印帮助信息
if (!process.argv.slice(2).length) {
program.outputHelp();
}
// 解析命令行参数
program.parse(process.argv);
交互验证
实现原理
- 利用前面的 chalk.js 实现不同样式字体的输出。
- 监听用户键盘输入,比如上/下/左/右
- 利用 ora.js 的原理,可以在用户输入上下左右的时候,重新刷新输出,从而实现命令行下的列表上下选择。
inquirer.js 使用
可以快速地实现选择列表、输入框等逻辑。
import inquirer from 'inquirer'
const promps = [];
// type: input
promps.push({
type: "input",
name: "moduleName",
message: "请输入模块名称",
validate: function(input) {
if (!input) {
return "输入不能为空";
}
return true;
}
});
// type: list
promps.push({
type: "list",
name: "cssPretreatment",
message: "想用什么css预处理器呢",
choices: [
{
name: "Sass",
value: "sass"
},
{
name: "Less",
value: "less"
}
]
});
inquirer.prompt(promps).then(function(answers) {
console.log("answers are", answers);
});
交互效果: