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

 更新时间:2022年08月02日 09:00:11   作者:JYeontu  
这篇文章主要介绍了JavaScript基于inquirer封装一个控制台文件选择器,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以参考一下

前言

我们在用脚手架初始化项目的时候,往往会进行一些命令交互,用过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封装内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JavaScript实现五种不同烟花特效

    JavaScript实现五种不同烟花特效

    这篇文章主要给大家带来五个好看的基于 HTML+CSS+JS 的烟花特效,文中的示例代码讲解详细,对我们学习JavaScript有一定的帮助,需要的可以参考一下
    2022-01-01
  • html代码调试脚本

    html代码调试脚本

    html代码调试脚本...
    2006-07-07
  • 判断是否安装flash player及当前版本的JS代码

    判断是否安装flash player及当前版本的JS代码

    本文为大家讲述下如何使用jsJS判断是否安装flash player及版本,下面的处理代码或许对大家有所帮助,感兴趣的朋友可以参考下,希望对大家有所帮助
    2013-08-08
  • js中的深浅拷贝问题简析

    js中的深浅拷贝问题简析

    这篇文章主要给大家介绍了关于js中的深浅拷贝问题的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用js具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-05-05
  • 原生js实现购物车逻辑和功能

    原生js实现购物车逻辑和功能

    这篇文章主要为大家详细介绍了原生js实现购物车逻辑和功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • 微信小程序提交form操作示例

    微信小程序提交form操作示例

    这篇文章主要介绍了微信小程序提交form操作,结合实例形式分析了微信小程序开发中使用form组件实现数据提交与数据处理相关操作技巧,需要的朋友可以参考下
    2018-12-12
  • JavaScript中的concat()方法的用法详解

    JavaScript中的concat()方法的用法详解

    在 JavaScript 中,数组和字符串都是常用的数据结构,在实际开发中,操作数组和字符串是非常频繁的任务,concat() 方法就是用于合并数组或字符串的一种常见方法,在本文中,我们将详细探讨 concat() 方法的用法和示例,需要的朋友可以参考下
    2024-11-11
  • JS/HTML5游戏常用算法之路径搜索算法 随机迷宫算法详解【普里姆算法】

    JS/HTML5游戏常用算法之路径搜索算法 随机迷宫算法详解【普里姆算法】

    这篇文章主要介绍了JS/HTML5游戏常用算法之路径搜索算法 随机迷宫算法,结合实例形式详细分析了针对迷宫游戏路径搜索算法的普里姆算法相关原理、实现方法及操作注意事项,需要的朋友可以参考下
    2018-12-12
  • js封装可使用的构造函数继承用法分析

    js封装可使用的构造函数继承用法分析

    这篇文章主要介绍了js封装可使用的构造函数继承用法,实例分析了使用属性拷贝来实现拷贝继承的技巧,需要的朋友可以参考下
    2015-01-01
  • JS常见错误(Error)及处理方案详解

    JS常见错误(Error)及处理方案详解

    这篇文章主要介绍了JS常见错误(Error)及处理方案详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07

最新评论