JavaScript基于inquirer封裝一個控制臺文件選擇器
前言
我們在用腳手架初始化項目的時候,往往會進行一些命令交互,用過vue或者react的用腳手架新建項目的應該都進行過命令交互,vue創(chuàng)建的時候會讓你選擇vue2還是vue3,也有多選要什么配置,也有輸入y或者n選擇是否用history路由等,這些簡單的交互其實用inquire這個包都能實現(xiàn),但是最近自己在做一個小工具的時候,想要進行文件和文件夾的選擇,這時我發(fā)現(xiàn)inquire里并沒有這個交互功能,所以便自己嘗試去在inquire這個庫的基礎(chǔ)上實現(xiàn)文件選擇和文件夾選擇這兩種類型的交互。
插件效果
通過該插件,我們可以在控制臺通過方向鍵來選擇文件和文件夾,具體效果如下:
插件實現(xiàn)
Inquirer.js
Inquirer.js試圖為NodeJs做一個可嵌入式的美觀的命令行界面。
如下圖:
inquirer原有參數(shù)
- type
表示提問的類型,包括:input、confirm、 list、rawlist、expand、checkbox、password、editor。
- name
存儲當前輸入的值。
- message
問題的描述。
- default
默認值。
- choices
列表選項,在某些type下可用,并且包含一個分隔符(separator);
- validate
對用戶的回答進行校驗。
- filter
對用戶的回答進行過濾處理,返回處理后的值。
- when
根據(jù)前面問題的回答,判斷當前問題是否需要被回答。
- pageSize
修改某些type類型下的渲染行數(shù)。
- prefix
修改message默認前綴。
- suffix
修改message默認后綴。
二次封裝
基于inquirer原有功能及參數(shù),增加一些擴展功能及參數(shù)
新增參數(shù)
- notNull
是否不能為空,默認為false,設(shè)置為true后該參數(shù)不能輸入空,并且會有不能為空的提示,必須輸入字符后才可以回車確認并進行下一步,如下圖:
{ 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
此項為新增配置,設(shè)置目錄和文件選擇器選中路徑輸出的格式,默認為相對路徑,可以設(shè)置為absolute,此時會輸出絕對路徑,效果如下圖:
{ type:"file", message:"請選擇文件:", name:"fileName", default:"", }, { type:"folder", message:"請選擇文件夾:", name:"folderName", default:"", pathType:'absolute' },
代碼實現(xiàn)
獲取指定路徑下的文件列表
使用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]; }
交互類型響應控制
新增的file
和folder
類型使用自己重新封裝的方法,其他依舊使用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]);
- 選擇的是文件則返回選擇的文件路徑并結(jié)束操作:
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]); } } }
選擇目錄
如下圖,這里使用后綴說明來區(qū)分選擇文件夾和進入文件夾:
選擇的為返回上一級
,則將當前目錄回退一級:
this.clear(2); return this.chooseFile(option,path.join(dirPath,'/../'));
選擇的是進入文件夾,則進入該目錄,這里需要將加入用于區(qū)分的后綴去掉再返回:
return path.join(dirPath, answer[option.name].slice(0,-7));
- 選擇的是選擇文件夾則返回選擇的文件夾路徑并結(jié)束操作:
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]); } } }
基本類型調(diào)用Inquirer處理
這里增加了notNull
(是否不能為空)的參數(shù),代碼如下:
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之間的數(shù)字"; } 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); });
到此這篇關(guān)于JavaScript基于inquirer封裝一個控制臺文件選擇器的文章就介紹到這了,更多相關(guān)JS inquirer封裝內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JS設(shè)計模式之觀察者模式實現(xiàn)實時改變頁面中金額數(shù)的方法
這篇文章主要介紹了JS設(shè)計模式之觀察者模式實現(xiàn)實時改變頁面中金額數(shù)的方法,結(jié)合實例形式對比分析了javascript基于觀察者模式實時改變頁面金額數(shù)的相關(guān)操作技巧,需要的朋友可以參考下2018-02-02javascript將數(shù)字轉(zhuǎn)換整數(shù)金額大寫的方法
這篇文章主要介紹了javascript將數(shù)字轉(zhuǎn)換整數(shù)金額大寫的方法,通過自定義函數(shù)中的數(shù)組替換實現(xiàn)數(shù)字轉(zhuǎn)換整數(shù)金額大寫的功能,非常具有實用價值,需要的朋友可以參考下2015-01-01JS中‘hello’與new String(‘hello’)引出的問題詳解
這篇文章主要給大家介紹了關(guān)于JS中'hello'與new String('hello')引出的問題的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面隨著小編來一起學習學習吧2018-08-08Javascript中產(chǎn)生固定結(jié)果的函數(shù)優(yōu)化技巧
分享一個Javascript編寫函數(shù)的優(yōu)化技巧;適用的函數(shù)應該要滿足以下條件;產(chǎn)生固定結(jié)果;復雜或較耗時等等,感興趣的朋友可以了解下2013-01-01解析offsetHeight,clientHeight,scrollHeight之間的區(qū)別
這篇文章主要是對offsetHeight,clientHeight,scrollHeight之間的區(qū)別進行了詳細介紹,需要的朋友可以過來參考下,希望對大家有所幫助2013-11-11JavaScript實現(xiàn)向OL列表內(nèi)動態(tài)添加LI元素的方法
這篇文章主要介紹了JavaScript實現(xiàn)向OL列表內(nèi)動態(tài)添加LI元素的方法,實例分析了javascript操作html元素的技巧,需要的朋友可以參考下2015-03-03JS基于構(gòu)造函數(shù)實現(xiàn)的菜單滑動顯隱效果【測試可用】
這篇文章主要介紹了JS基于構(gòu)造函數(shù)實現(xiàn)的菜單滑動顯隱效果,可實現(xiàn)基本的菜單折疊與展開功能,涉及javascript響應鼠標事件動態(tài)操作頁面元素的相關(guān)技巧,需要的朋友可以參考下2016-06-06JavaScript 動態(tài)創(chuàng)建VML的方法
JavaScript 動態(tài)創(chuàng)建VML的方法,需要的朋友可以參考下。2009-10-10