交互式命令行编程和原理

交互式命令行编程和原理

Tags
命令行编程
CreatedTime
Aug 15, 2022 06:26 AM
Slug
2022-04-11-nodejs-shell
UpdatedTime
Last updated August 15, 2022

颜色控制

实现原理

这个比较简单,写过 c 的应该知道控制命令行颜色,只需要 颜色宏定义 + 字体内容 拼接即可。这就是 chalk.js 的实现原理。
举个例子,对于\\e[31;44;4;1m来说,意义如下:
  • \\e 代表开始 ANSI Escape code。就是ESC的转义符。在nodejs中,请用它的16进制码0x1B
  • [ 代表转义序列开始符 CSI,Control Sequence Introducer
  • 31;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!"));
notion image

进度控制

实现原理

「回车」不等于「换行」:
  • \\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);

交互验证

实现原理

  1. 利用前面的 chalk.js 实现不同样式字体的输出。
  1. 监听用户键盘输入,比如上/下/左/右
  1. 利用 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); });
交互效果:
notion image

参考链接