JavaScript基于inquirer封装一个控制台文件选择器

目录
  • 前言
  • 插件效果
  • 插件实现
    • Inquirer.js
    • inquirer原有参数
    • 二次封装
    • 新增参数
  • 代码实现
    • 获取指定路径下的文件列表
    • 获取指定路径下的目录列表
    • 交互类型响应控制
    • 选择文件
    • 选择目录
    • 基本类型调用Inquirer处理
  • 插件使用
    • 1、安装依赖
    • 2、在代码中引用
    • 3、示例代码

前言

我们在用脚手架初始化项目的时候,往往会进行一些命令交互,用过vue或者react的用脚手架新建项目的应该都进行过命令交互,vue创建的时候会让你选择vue2还是vue3,也有多选要什么配置,也有输入y或者n选择是否用history路由等,这些简单的交互其实用inquire这个包都能实现,但是最近自己在做一个小工具的时候,想要进行文件和文件夹的选择,这时我发现inquire里并没有这个交互功能,所以便自己尝试去在inquire这个库的基础上实现文件选择和文件夹选择这两种类型的交互。

插件效果

通过该插件,我们可以在控制台通过方向键来选择文件和文件夹,具体效果如下: 

插件实现

Inquirer.js

Inquirer.js试图为NodeJs做一个可嵌入式的美观的命令行界面。

如下图:

inquirer原有参数

  • type

表示提问的类型,包括:input、confirm、 list、rawlist、expand、checkbox、password、editor。

  • name

存储当前输入的值。

  • message

问题的描述。

  • default

默认值。

  • choices

列表选项,在某些type下可用,并且包含一个分隔符(separator);

  • validate

对用户的回答进行校验。

  • filter

对用户的回答进行过滤处理,返回处理后的值。

  • when

根据前面问题的回答,判断当前问题是否需要被回答。

  • pageSize

修改某些type类型下的渲染行数。

  • prefix

修改message默认前缀。

  • suffix

修改message默认后缀。

二次封装

基于inquirer原有功能及参数,增加一些扩展功能及参数

新增参数

  • notNull

是否不能为空,默认为false,设置为true后该参数不能输入空,并且会有不能为空的提示,必须输入字符后才可以回车确认并进行下一步,如下图:

{
    type:"input",
    message:"请输入你的姓名:",
    name:"name",
    notNull:true
}

  • type

在原有类型中新增两种类型:file、folder,分别为文件选择器和目录选择器,效果如下图:

{
    type:"file",
    message:"请选择文件:",
    name:"fileName",
    default:"",
},
{
    type:"folder",
    message:"请选择文件夹:",
    name:"folderName",
    default:"",
    pathType:'absolute'
},

  • pathType

此项为新增配置,设置目录和文件选择器选中路径输出的格式,默认为相对路径,可以设置为absolute,此时会输出绝对路径,效果如下图:

{
    type:"file",
    message:"请选择文件:",
    name:"fileName",
    default:"",
},
{
    type:"folder",
    message:"请选择文件夹:",
    name:"folderName",
    default:"",
    pathType:'absolute'
},

代码实现

获取指定路径下的文件列表

使用fs中的readdirSync方法可以获取指定目录下的文件列表,具体代码如下:

getFileList = (dirPath)=>{
    const list = fs.readdirSync(dirPath);
    return ['../(返回上一级)',...list];
}

获取指定路径下的目录列表

使用fs中的readdirSync方法可以获取指定目录下的文件列表,通过isDirectory方法可以判断文件是否为目录文件,具体代码如下:

getFolderList = (dirPath)=>{
    const list = fs.readdirSync(dirPath);
    let resList = [];
    list.map(item=>{
        const fullPath = path.join(dirPath,item);
        if(fs.statSync(fullPath).isDirectory()){
            resList.push(item + '(进入文件夹)');
            resList.push(item + '(选择文件夹)');
        }
    });
    return ['../(返回上一级)',...resList];
}

交互类型响应控制

新增的filefolder类型使用自己重新封装的方法,其他依旧使用Inquirer中的响应方法,具体代码如下:

run(option){
    if(option.type === 'file'){
        return this.chooseFile(option);
    }else if(option.type === 'folder'){
        return this.chooseFolder(option);
    }else{
        if(option.notNull){
            const flag = option.message.slice(-1);
            if([":",":"].includes(flag)){
                option.message = option.message.slice(0,-1) + '(不能为空)' + flag;
            }
        }
        return this.defaultType(option);
    }
}

选择文件

  • 选择的为返回上一级,则将当前目录回退一级:
this.clear(2);
return this.chooseFile(option,path.join(dirPath,'/../'));
  • 选择的是目录则进入选择的目录:
return path.join(dirPath, answer[option.name]);
  • 选择的是文件则返回选择的文件路径并结束操作:
this.clear(2);
return this.chooseFile(option,fullPath);

完整代码如下:

chooseFile(option,dirPath = './'){
    option.type = 'list';
    option.suffix = "(当前浏览目录:" + path.join(__dirname,dirPath) + ')';
    option.pageSize = fs.readdirSync('./').length + 1;
    option.choices = [...this.getFileList(dirPath)];
    const answer = await inquirer.prompt([
        option
    ]);
    if(answer[option.name] == '../(返回上一级)'){
        this.clear(2);
        return this.chooseFile(option,path.join(dirPath,'/../'));
    }else{
        const fullPath = path.join(dirPath, answer[option.name]);
        if(!fs.statSync(fullPath).isFile()){
            this.clear(2);
            return this.chooseFile(option,fullPath);
        }else{
            return path.join(dirPath, answer[option.name]);
        }
    }
}

选择目录

如下图,这里使用后缀说明来区分选择文件夹和进入文件夹: 

选择的为返回上一级,则将当前目录回退一级:

this.clear(2);
return this.chooseFile(option,path.join(dirPath,'/../'));

选择的是进入文件夹,则进入该目录,这里需要将加入用于区分的后缀去掉再返回:

return path.join(dirPath, answer[option.name].slice(0,-7));
  • 选择的是选择文件夹则返回选择的文件夹路径并结束操作:
this.clear(2);
return this.chooseFile(option,fullPath);

完整代码如下:

chooseFile(option,dirPath = './'){
    option.type = 'list';
    option.suffix = "(当前浏览目录:" + path.join(__dirname,dirPath) + ')';
    option.pageSize = fs.readdirSync('./').length + 1;
    option.choices = [...this.getFileList(dirPath)];
    const answer = await inquirer.prompt([
        option
    ]);
    if(answer[option.name] == '../(返回上一级)'){
        this.clear(2);
        return this.chooseFile(option,path.join(dirPath,'/../'));
    }else{
        const fullPath = path.join(dirPath, answer[option.name]);
        if(!fs.statSync(fullPath).isFile()){
            this.clear(2);
            return this.chooseFile(option,fullPath);
        }else{
            return path.join(dirPath, answer[option.name]);
        }
    }
}

基本类型调用Inquirer处理

这里增加了notNull(是否不能为空)的参数,代码如下:

defaultType(option){
    const answer = await inquirer.prompt([
        option
    ]);
    if(option.notNull && answer[option.name] === ''){
        this.clear(2);
        return this.defaultType(option);
    }
    return answer[option.name];
}

插件使用

1、安装依赖

npm install @jyeontu/j-inquirer

2、在代码中引用

const JInquirer = require('@jyeontu/j-inquirer');

3、示例代码

const JInquirer = require('@jyeontu/j-inquirer');
let options = [
    {
        type:"input",
        message:"请输入你的姓名:",
        name:"name",
        notNull:true
    },{
        type:"input",
        message:"请输入你的年龄:",
        name:"age",
        default:18,
        validate:(val)=>{
            if(val < 0 || val > 150){
                return "请输入0~150之间的数字";
            }
            return true;
        }
    },{
        type:"file",
        message:"请选择文件:",
        name:"fileName",
        default:"",
    },{
        type:"folder",
        message:"请选择文件夹:",
        name:"folderName",
        default:"",
        pathType:'absolute'
    },{
        type:"list",
        message:"请选择你喜欢的水果:",
        name:"fruit",
        default:"Apple",
        choices:[
            "Apple",
            "pear",
            "Banana"
        ],
    },{
        type:"expand",
        message:"请选择一个颜色:",
        name:"color",
        default:"red",
        choices:[
            {
                key : 'R',
                value : "red"
            },
            {
                key : 'B',
                value : "blue"
            },
            {
                key : 'G',
                value : "green"
            }
        ]
    },{
        type:"checkbox",
        message:"选择一至多种颜色:",
        name:"color2",
        choices:[
            "red",
            "blue",
            "green",
            "pink",
            "orange"
        ]
    },{
        type:"password",
        message:"请输入你的密码:",
        name:"pwd"
    },{
        type:"editor",
        message:"写下你想写的东西:",
        name:"editor"
    }
];
let j = new JInquirer(options);
let res = j.prompt().then(res=>{
    console.log(res);
});

到此这篇关于JavaScript基于inquirer封装一个控制台文件选择器的文章就介绍到这了,更多相关JS inquirer封装内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • JS实现一个文件选择组件详解

    目录 前言 插件安装 插件使用 参数说明 前言 花了点时间利用广度与深度优先搜索算法实现了一个文件选择插件,支持无限层次的文件夹嵌套,已开源并打包上传到了npm. 本文将跟大家分享一下这个插件,欢迎各位感兴趣的开发者阅读本文. 插件安装 yarn add file-folder-selector # or npm install file-folder-selector --save 插件使用 在你需要使用此插件的业务代码中导入插件. <script setup lang="ts"

  • JS点击某个图标或按钮弹出文件选择框的实现代码

    下面一段代码是基于js实现的点击某个图标或按钮弹出文件选择框的核心代码,代码比较简单,需要的朋友参考下 具体代码如下所示: <HTML> <head> <script type="text/javascript" src="script/jquery-1.6.2.min.js"></script> <script type='text/javascript'> function selectFile(){

  • JS点击图片弹出文件选择框并覆盖原图功能的实现代码

    简单说下原理,把显示的图片的<img>标签 和上传文件的 <input> 标签放在同一个div下,设置<img>的大小和<input>的大小一样,<input> 设置透明度为0,用定位和设置优先级把input浮动在<img>上方,这样点击图片就能选择上传图片,选择完图片后获取图片地址,替换掉原来的默认图片就能实现覆盖原图功能. js代码: <script type="text/javascript" src=

  • js实现上传文件添加和删除文件选择框

    本文这里给大家说个用javascript实现的很实用的功能,是在上传附件的时候,可以动态地添加和删除文件选择框,然后一次性上传. 从理论上看,实现起来比较容易,但实际工作的时候还是遇到两个难点,这些难点归结起来都是一个原因造成的,那就是浏览器的兼容性.在脚本中要用到两个函数:insertAdjacentHTML和removeChild,而恰好这两个函数在Firefox下都不能正常使用.几乎花费了一天的时候,在网上搜索着解决的方法,还好被找到了,也让我大松一口气. 具体两个函数是这样的: <scr

  • JavaScript基于inquirer封装一个控制台文件选择器

    目录 前言 插件效果 插件实现 Inquirer.js inquirer原有参数 二次封装 新增参数 代码实现 获取指定路径下的文件列表 获取指定路径下的目录列表 交互类型响应控制 选择文件 选择目录 基本类型调用Inquirer处理 插件使用 1.安装依赖 2.在代码中引用 3.示例代码 前言 我们在用脚手架初始化项目的时候,往往会进行一些命令交互,用过vue或者react的用脚手架新建项目的应该都进行过命令交互,vue创建的时候会让你选择vue2还是vue3,也有多选要什么配置,也有输入y或

  • 基于Element封装一个表格组件tableList的使用方法

    我们项目中使用的表格一般都比较类似,如果不进行封装的话,那么每个页面都可能有一些类似的代码.不仅浪费时间,而且由于开发人员不同的开发习惯.后期维护人员需要花费一点时间去看每个人的代码.所以我直接将表格做一个二次封装,只要一个人去维护这份代码即可.下面是我封装的内容 内容: 1.支持直接传入后台请求地址渲染列表,且参数修改之后自动刷新 2.支持自定义每一列的显示 3.支持根据内容自动撑开列宽 4.支持动态筛选表头 5.支持分页 6.防抖 7.列权限 ... 更多请自行尝试 以下是tableList

  • 你知道怎么基于 React 封装一个组件吗

    目录 antd 是如何封装组件的 仓库地址 divider 组件源代码 如何暴露组件属性 如何设置统一类名前缀 如何处理样式与类名 divider 组件样式源代码 总结 前言 很多小伙伴在第一次尝试封装组件时会和我一样碰到许多问题,比如人家的组件会有 color 属性,我们在使用组件时传入组件文档中说明的属性值如 primary ,那么这个组件的字体颜色会变为 primary 对应的颜色,这是如何做到的?还有别人封装的组件类名都有自己独特的前缀,这是如何处理的呢,难道是 css 类名全部加上前缀

  • 基于PyQt5制作一个PDF文件合并器

    操作说明:选择多个PDF文件,执行完合并后会生成一个新的PDF文件,这个新的PDF文件包含所有源PDF文件的页面. 将相关的三方模块导入到代码块中... from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.QtCore import * import sys import os import PyPDF2 # PDF操作库 QThread是PyQt5的子线程应用,之前已经使用过比较多的次数了.一般使用时通过创建一个

  • 封装一个Vue文件上传组件案例详情

    目录 前言 1. 子组件 2 父组件使用 3.效果 4.总结 前言 在面向特定用户的项目中,引 其他ui组件库导致打包体积过大,首屏加载缓慢,还需要根据UI设计师设计的样式,重写大量的样式覆盖引入的组件库的样式.因此尝试自己封装一个自己的组件,代码参考了好多前辈的文章 1. 子组件 <template> <div class="digital_upload"> <input style="display: none" @change=&

  • 基于vue-upload-component封装一个图片上传组件的示例

    需求分析 业务要求,需要一个图片上传控件,需满足 多图上传 点击预览 图片前端压缩 支持初始化数据 相关功能及资源分析 基本功能 先到https://www.npmjs.com/search?q=vue+upload上搜索有关上传的控件,没有完全满足需求的组件,过滤后找到 vue-upload-component 组件,功能基本都有,自定义也比较灵活,就以以此进行二次开发. 预览 因为项目是基于 vant 做的,本身就提供了 ImagePreview 的预览组件,使用起来也简单,如果业务需求需要

  • Android第三方文件选择器aFileChooser使用方法详解

    aFileChooser是android平台上的一个第三方文件选择器,其在github上的项目主页是:https://github.com/iPaulPro/aFileChooser aFileChooser实现了在Android平台上高度可定制化的文件选择功能,aFileChooser在自己的项目代码中使用也比较简单. 写一个简单例子加以说明. (1) 首先要配置Androidmanifest.xml文件: <activity android:name="com.ipaulpro.afi

  • Android 文件选择器详解及实例代码

    本文给大家讲解下Android文件选择器的使用.实际上就是获取用户在SD卡中选择的文件或文件夹的路径,这很像C#中的OpenFileDialog控件. 此实例的实现过程很简单,这样可以让大家快速的熟悉Android文件选择器,提高开发效率. 网上曾经见到过一个关于文件选择器的实例,很多人都看过,本实例是根据它修改而成的,但更容易理解,效率也更高,另外,本实例有自己的特点:   1.监听了用户按下Back键的事件,使其返回上一层目录.        2.针对不同的文件类型(文件vs文件夹 , 目标

  • 基于React封装组件的实现步骤

    目录 前言 antd 是如何封装组件的 divider 组件源代码 如何暴露组件属性 如何设置统一类名前缀 如何处理样式与类名 divider 组件样式源代码 前言 很多小伙伴在第一次尝试封装组件时会和我一样碰到许多问题,比如人家的组件会有 color 属性,我们在使用组件时传入组件文档中说明的属性值如 primary ,那么这个组件的字体颜色会变为 primary 对应的颜色,这是如何做到的?还有别人封装的组件类名都有自己独特的前缀,这是如何处理的呢,难道是 css 类名全部加上前缀吗,这也太

  • Javascript基于对象三大特性(封装性、继承性、多态性)

    Javascript基于对象的三大特征和C++,Java面向对象的三大特征一样,都是封装(encapsulation).继承(inheritance )和多态(polymorphism ).只不过实现的方式不同,其基本概念是差不多的.其实除三大特征之外,还有一个常见的特征叫做抽象(abstract),这也就是我们在一些书上有时候会看到面向对象四大特征的原因了. 一.封装性     封装就是把抽象出来的数据和对数据的操作封装在一起,数据被保护在内部,程序的其它部分只有通过被授权的操作(成员方法),

随机推荐