前端架构: 脚手架命令行交互核心实现之inquirer和readline的应用教程

news2025/1/21 1:02:15

命令行交互核心实现

  • 核心目标:实现命令行行交互,如List
  • 命令行的交互呢比命令行的渲难度要更大,因为它涉及的技术点会会更多
  • 它涉及以下技术点
    • 键盘输入的一个监听 (这里通过 readline来实现)
    • 计算命令行窗口的尺寸
    • 清屏
    • 光标的移动
    • 输出流的静默 (我们输出的内容, 不让它去输出到当前的这个终端中)
    • 借助输入输出流,引出输入输出流的一个监听以及事件库 events
    • ansi escaped code 转义字符
  • 命行交互其实是有一定复杂度的, 在这个过程中,最重点的库和命行交互最重点库是两个 readlineinquirer

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
效果实例
  • 另外,比较常用的还有
    • 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中已做了详细说明,这里不再赘述
效果实例
  • 使用示例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
        }
      });
    
效果实例
  • 使用示例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
        }
      });
    
效果实例
  • 使用示例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
效果实例
  • 使用示例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 反选的功能
    • 默认,上下箭来选择
效果实例
  • 使用示例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
        }
      });
    
效果实例
  • 使用示例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
        }
      });
    
效果实例
  • 上面中间的这个类似 vim 的界面,会在一个缓存文件中,输入完以后,缓存文件被删除掉
  • 我们输入的结果会被保留下来,如上图
  • 这样做的好处是在文本编辑器中输入复杂的内容

readline

  • readline,是 nodejs 当中的一个内置库,主要帮我们去管理数据流的
  • 命令行当中要交互的方式,一定是需要用户提供一些输入的
  • readline 就可以很好的帮我们去一次一次的读取这个输入流
  • 注意,这个输入不仅是指我们输入一些字符,还包含我们键盘上输入的一切,如上,下,空格,回车等
  • 基本使用
    import * as readLine from 'readline';
    
    const rl = readLine.createInterface({
    	input: process.stdin,
    	output: process.stdout,
    });
    
    rl.question('your name: ', (answer) => {
    	console.log(answer);
    	rl.close(); // 关闭读取流
    })
    
  • readline 主要用途是根据传入的输入流逐行读取信息
  • 回车的时候,会认为这行输入结束,并且把所有输入的内容传递到输出流中进行展示
  • 这是readline的核心用途
  • 如果调试 readline 源码,可知,它内部会强制将函数转换为构造函数
    if (!(this instanceof Interface)) {
      return new Interface(input, output, completer, terminal);
    }
    
  • 接着是对 StringDecoder的判断和赋值,这个也是node的一个内置库
    if (StringDecoder === undefined) {
      StringDecoder = require('string_decoder').StringDecoder;
    }
    
  • 再之后,定义了一些列的参数,调用了 EventEmitter
    EventEmitter.call(this)
    
    • 这个用途是使用 this 继承 EventEmitter, this内部就会生成一些列的属性信息,如 _events, _eventsCount
    • 让当前 Interface 实例具备事件驱动的能力,因为nodejs有单线程,非阻塞IO,事件驱动的特性
    • 也就是说事件驱动,在单线程的nodejs中是非常重要的
  • 再接着,定义一些参数, 对 input 进行判断,也就是分析 input 参数
    if (input && input.input) {
      // ....
    }
    
  • 再往后找,看readline是如何做事件监听的
    this.output = output; // output: WriteStream 系统输出流
    this.input = input; // input: ReadStream 系统输入流
    
    // ...
    
    emitKeypressEvents(input, this) // 这里就是监听用户在终端中的键盘输入
    
    • 在 emitKeypressEvents 函数内部,会调用一个 emitKeys 的方法
    • 这里是核心, 其原理和源码不在这里进行剖析

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1475215.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unity的相机跟随和第三人称视角

Unity相机跟随和第三人称视角 介绍镜头视角跟随人物方向进行旋转的镜头视角固定球和人的镜头视角 思路跟随人物方向进行旋转的镜头视角固定球和人的镜头视角 镜头旋转代码人物移动的参考代码注意 介绍 最近足球项目的镜头在做改动,观察了一下实况足球的视角&#x…

3-1openflow协议原理以及应用(packet包广播风暴)实践

在Mininet中,其自带的控制器是采用是OpenFlow 1.0版本。因此如果在开发中使用mininet内置的控制器(使用端口6653),即使拓扑构建和ovs自定义时声明使用openflow13,但是由于采用的控制器版本受限,ovs与控制器…

RV32/64 特权架构 - 特权模式与指令

RV32/64 特权架构 - 特权模式与指令 1 特权模式2 特权指令2.1 mret(从机器模式返回到先前的模式)2.2 sret(从监管模式返回到先前的模式)2.3 wfi(等待中断)2.4 sfence.vma(内存屏障) …

深度学习 精选笔记(5)多层感知机

学习参考: 动手学深度学习2.0Deep-Learning-with-TensorFlow-bookpytorchlightning ①如有冒犯、请联系侵删。 ②已写完的笔记文章会不定时一直修订修改(删、改、增),以达到集多方教程的精华于一文的目的。 ③非常推荐上面(学习参考&#x…

在Ubuntu22.04 LTS上搭建Kubernetes集群

文章目录 准备工作系统准备软件包准备主机和IP地址准备 安装步骤安装前准备关闭防火墙设置服务器时区关闭 swap 分区关闭SELinux配置hosts配置文件转发 IPv4 并让 iptables 看到桥接流量 安装容器运行时安装Kubernetes配置并安装apt包初始化集群 安装calico网络插件部署应用 本…

iSH使用与优化全网整合教程【持续更新】【精华】

【最后一次更新:2023.4.​​​​​22】 请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,作者不为此承担任何责任~ iSH介绍与换源【已安装并已完成…

香港紧缺13个专业人才有哪些?香港优才计划人才清单解读!

香港紧缺13个专业人才有哪些?香港优才计划人才清单解读! 香港优才计划是香港的一项人才引进政策,目的是吸纳优秀人才来港发展定居,提高香港的国际竞争力。因此,香港优才跟香港紧缺行业息息相关。 如果是从事香港紧缺行…

Docker 常用操作命令备忘

Docker 一旦设置好了环境,日常就只要使用简单命令就可以运行和停止。 于是,我每次用的时候,都想不起来一些关键性的命令到底怎么用,特此记录。 一、镜像管理 从公有仓库拉取镜像 (对于使用苹果电脑 M1/M2/M3 芯片的 …

Rust调用同级目录中的rs文件和调用下级目录中的rs文件

一、Rust调用同级目录中的rs文件 Rust新建工程demo02,src文件夹下面新建test.rs文件,这样main.rs文件与它属于同级目录中。 关键点:导入test文件和test文件中的Ellipse模块 mod test;//导入test模块(文件) use test…

Java学习--学生管理系统(残破版)

代码 Main.java import java.util.ArrayList; import java.util.Scanner;public class Main {public static void main(String[] args) {ArrayList<Student> list new ArrayList<>();loop:while (true) {System.out.println("-----欢迎来到阿宝院校学生管理系…

一拎即走的轻薄云台投影,极米投影仪Z7X让生活幸福加倍

随着家用智能投影性能的不断升级&#xff0c;拥有便携、易用、护眼以及大屏等优势的智能投影仪已经逐步取代传统电视机&#xff0c;成为越来越多年轻人在租房、装修新家购置新电器时的第一选择。市面上的投影仪产品多如牛毛&#xff0c;对于刚接触投影仪的新手来说&#xff0c;…

iMazing2024汉化免费版苹果设备管理软件功能详解

一、软件简介 iMazing&#xff0c;被誉为Mac和PC上最佳的iOS设备管理软件&#xff0c;以其全面而细致的功能&#xff0c;赢得了全球苹果用户的喜爱。无论是备份恢复、文件传输还是设备管理&#xff0c;iMazing都能提供高效、安全、便捷的服务体验。 iMazing3Mac-最新绿色安装包…

全面升级!Apache HugeGraph 1.2.0版本发布

图数据库以独特的数据管理和分析能力&#xff0c;在企业数智化转型的过程中正在成为数据治理的核心&#xff0c;根据IDC调研显示&#xff0c;95%的企业认为图数据库是重要的数据管理工具&#xff0c;超过65%的厂商认为在业务上图数据库优于其他选择&#xff0c;尤其是在金融风控…

2024 值得推荐的免费开源 WAF

WAF 是 Web Application Firewall 的缩写&#xff0c;也被称为 Web 应用防火墙。区别于传统防火墙&#xff0c;WAF 工作在应用层&#xff0c;对基于 HTTP/HTTPS 协议的 Web 系统有着更好的防护效果&#xff0c;使其免于受到黑客的攻击。 开源 WAF 和商用 WAF&#xff08;奇安信…

气体反应瓶适用光伏光电半导体坚固耐用PFA缓冲瓶

PFA冲击瓶&#xff0c;别名特氟龙缓冲瓶、可溶性聚四氟乙烯气体反应瓶。用于气体、固体或液体间的反应实验&#xff0c;广泛应用于光电、新材料、新能源、半导体、地矿、冶金、核工业等行业。 PFA冲击瓶相对于其他材质的反应瓶&#xff0c;不易碎&#xff0c;使用更加安全&…

星瑞格新篇:SinoDB V16.8启幕,技术盛宴

喜讯传来&#xff0c;令人心悦&#xff01;SinoDB V16.8版&#xff0c;如春风之翩翩&#xff0c;向众用户及开发者扬帆起航。此版相关技术&#xff0c;均于星瑞格社区(https://forum.sinoregal.cn/ )说明&#xff0c;社区之主页&#xff0c;设“试用活动”栏&#xff0c;以聚众…

【亚马逊云】跨AWS账号创建复制规则同步S3存储桶中的数据

文章目录 注意事项一、创建存储桶【创建方&接收方完成操作】二、上传数据至bucket-transmit待同步测试三、创建复制规则【创建方完成操作】四、接收复制的对象【接收方完成操作】五、创建复制任务【创建方操作】六、运行批处理操作【创建方完成操作】七、检查是否完成跨账号…

使用ffmpeg压缩视频

一、到ffmpeg官网下载文件包&#xff1a; Download FFmpeg 下载后找到 bin 下的3个exe文件&#xff0c;复制到自己本机的某个目录下, 如&#xff1a; 二、使用命令行压缩&#xff1a; ffmpeg -i input.mp4 -c:v libx265 -crf 28 -y output.mp4 这条命令使用 FFmpeg 工具对输…

【Pytorch深度学习开发实践学习】Pytorch实现LeNet神经网络(1)

1.model.py import torch.nn as nn import torch.nn.functional as F引入pytorch的两个模块 关于这两个模块的作用&#xff0c;可以参考下面 Pytorch官方文档 torch.nn包含了构成计算图的基本模块 torch,nn.function包括了计算图中的各种主要函数&#xff0c;包括&#…

等保2.0高风险项全解析:判定标准与应对方法

引言 所谓高风险项&#xff0c;就是等保测评时可以一票否决的整改项&#xff0c;如果不改&#xff0c;无论你多少分都会被定为不合格。全文共58页&#xff0c;写得比较细了&#xff0c;但是想到大家基本不会有耐心去仔细看的&#xff08;凭直觉&#xff09;。这几天挑里边相对…