命令行交互核心实现
- 核心目标:实现命令行行交互,如List
- 命令行的交互呢比命令行的渲难度要更大,因为它涉及的技术点会会更多
- 它涉及以下技术点
- 键盘输入的一个监听 (这里通过
readline
来实现) - 计算命令行窗口的尺寸
- 清屏
- 光标的移动
- 输出流的静默 (我们输出的内容, 不让它去输出到当前的这个终端中)
- 借助输入输出流,引出输入输出流的一个监听以及事件库
events
- ansi escaped code 转义字符
- 键盘输入的一个监听 (这里通过
- 命行交互其实是有一定复杂度的, 在这个过程中,最重点的库和命行交互最重点库是两个
readline
和inquirer
inquirer
- inquirer 是一个命令行交互常用的库,Weekly Downloads 30,375,340 (动态数据)
- 作为一个命令行交互的库能做到这个程度,可以说是非常的不简单,而且一直在持续的进行维护,目前已经达到9.2.15版本了
- 安装 $
npm i -S inquirer
- 使用示例1:input类型演示
import inquirer from 'inquirer'; inquirer .prompt([ { type: 'input', name: 'yourName', message: 'your name:', } ]) .then((answers) => { console.log(answers); }) .catch((error) => { if (error.isTtyError) { // Prompt couldn't be rendered in the current environment } else { // Something else went wrong } });
- 这里根据文档上的框架结构
- 通过 type, name, message 三个字段即可完成初始化创建
- 更多,参考文档:https://www.npmjs.com/package/inquirer#question
![](https://img-blog.csdnimg.cn/direct/0ccb022a36ab488596f07cbbfaa457eb.jpeg)
效果实例
- 另外,比较常用的还有
- default 默认值字段
- validate 字段是一个回调
- 用于对字段的校验,只有校验返回 true的时候校验才会结束
- transformer 字段用于处理信息展示的回调
- 也就是这个函数内部返回的值是展示的值
- 返回的值还是之前的 name 字段
- 更多的像是表单中的 placeholder 仅作为展示
- filter 字段是一个回调
- 它会最终改变 answers 最终的结果
- 会最终改变 name 字段
- 其他: choice 在匹配 List 列表的时候会用到
- 注意,
prompt
方法内部接受的是一个数组,可以写多个对象来收集数据 - 使用示例2: 多字段演示
import inquirer from 'inquirer'; inquirer .prompt([ { type: 'input', name: 'yourName', message: 'your name:', default: 'Lee', validate: function(v) { return v === 'Wang' }, transformer: function(v) { return 'your input name: ' + v // 仅作为展示 }, filter: function(v) { return v; // return v + '123' // 改变最终值 } }, { type: 'number', // 这种,在没有 validate 的情况下,如果输入的是非数字, 会变成 NaN name: 'num', message: 'your number', }, // ... ]) .then((answers) => { console.log(answers); // 最终打印的是一个对象,多个字段 }) .catch((error) => { if (error.isTtyError) { // Prompt couldn't be rendered in the current environment } else { // Something else went wrong } });
- 在示例1中已做了详细说明,这里不再赘述
![](https://img-blog.csdnimg.cn/direct/63abf06125dc4a5296ec348dcf0df4cb.jpeg)
效果实例
- 使用示例3: confirm 类型演示
import inquirer from 'inquirer'; inquirer .prompt([ { type: 'confirm', // 二选一功能 name: 'choice', message: 'your choice:', default: false, }, ]) .then((answers) => { console.log(answers); }) .catch((error) => { if (error.isTtyError) { // Prompt couldn't be rendered in the current environment } else { // Something else went wrong } });
![](https://img-blog.csdnimg.cn/direct/0d0ea6cbf164416f81cb91d460c576a3.jpeg)
效果实例
- 使用示例4: list 类型演示
import inquirer from 'inquirer'; inquirer .prompt([ { type: 'list', // 列表单选 name: 'choice', message: 'your choice:', default: 0, // 这里 default 是 下面choices 的索引 choices: [ {value: 1, name: 'LiLy'}, {value: 2, name: 'Lucy'}, {value: 3, name: 'Lee'}, ] }, ]) .then((answers) => { console.log(answers); }) .catch((error) => { if (error.isTtyError) { // Prompt couldn't be rendered in the current environment } else { // Something else went wrong } });
![](https://img-blog.csdnimg.cn/direct/f8cec7fc2dc4414bb72e0673def91b58.jpeg)
![](https://img-blog.csdnimg.cn/direct/f5d41b02906d428781293ecf92b8b41a.jpeg)
效果实例
- 使用示例5: expend 类型演示
import inquirer from 'inquirer'; inquirer .prompt([ { type: 'expand', // 简写选择 name: 'choice', message: 'your choice:', default: 'red', choices: [ {value: 'red', key: 'R'}, {value: 'green', key: 'G'}, {value: 'blue', key: 'B'}, ] }, ]) .then((answers) => { console.log(answers); }) .catch((error) => { if (error.isTtyError) { // Prompt couldn't be rendered in the current environment } else { // Something else went wrong } });
- 简写选择功能,除了 Rgb 还有一个 h
- 输入 h 回车,会得到 help 提示,列出了所有选项
- 输入 r 回车,会得到 red, 输入 g 回车,会得到 green
![](https://img-blog.csdnimg.cn/direct/fd908422ebd945b897af3e363fd8654c.jpeg)
![](https://img-blog.csdnimg.cn/direct/897701d8f756486c82bfdd973a2267e2.jpeg)
效果实例
- 使用示例6: checkbox 类型演示
import inquirer from 'inquirer'; inquirer .prompt([ { type: 'checkbox', // 复选框 name: 'choice', message: 'your choice:', default: 0, choices: [ {value: 1, name: 'Lily'}, {value: 2, name: 'Lucy'}, {value: 3, name: 'Lee'}, ] }, ]) .then((answers) => { console.log(answers); }) .catch((error) => { if (error.isTtyError) { // Prompt couldn't be rendered in the current environment } else { // Something else went wrong } });
- 这里提供 a 全选,空格键 选中,i 反选的功能
- 默认,上下箭来选择
![](https://img-blog.csdnimg.cn/direct/ea5e753b45384b34b4b45266f46f3032.jpeg)
![](https://img-blog.csdnimg.cn/direct/7493bdc919cb4cd6b699052e74b6d06b.jpeg)
效果实例
- 使用示例7: password 类型演示
import inquirer from 'inquirer'; inquirer .prompt([ { type: 'password', // 密码框 name: 'password', message: 'your password:', }, ]) .then((answers) => { console.log(answers); }) .catch((error) => { if (error.isTtyError) { // Prompt couldn't be rendered in the current environment } else { // Something else went wrong } });
![](https://img-blog.csdnimg.cn/direct/1493005159814676b987200a89fefce9.jpeg)
效果实例
- 使用示例8: editor 类型演示
import inquirer from 'inquirer'; inquirer .prompt([ { type: 'editor', // 编辑器 name: 'editor', message: 'your editor text:', }, ]) .then((answers) => { console.log(answers); }) .catch((error) => { if (error.isTtyError) { // Prompt couldn't be rendered in the current environment } else { // Something else went wrong } });
![](https://img-blog.csdnimg.cn/direct/1a6e02d6043d4719b57b7ca384511c90.jpeg)
![](https://img-blog.csdnimg.cn/direct/d1ecc80144534edb8f626a54e0ac2d17.jpeg)
![](https://img-blog.csdnimg.cn/direct/f885452ff5aa4350a1d5b421c0e288c6.jpeg)
效果实例
- 上面中间的这个类似 vim 的界面,会在一个缓存文件中,输入完以后,缓存文件被删除掉
- 我们输入的结果会被保留下来,如上图
- 这样做的好处是在文本编辑器中输入复杂的内容