node js学习 [第四篇] cli commander chalk Inquirer【新手向】

1,512 阅读6分钟

这是我参与8月更文挑战的第13天,活动详情查看:8月更文挑战

什么是commander

node.js命令行界面的完整解决方案,受Ruby Commander启发。

commander可以开发下面这些类型的工具:

  1. GUI - Graphical User Interface : 图形用户界面\
  2. office、vscode、浏览器、播放器……\
  3. CLI - Command-Line Interface:命令行界面,也称为 CUI,字符用户界面\
  4. 虽然没有GUI操作直观,但是CLI更加节省计算机资源(所以一般用于服务器环境)\
  5. babel、tsc / webpack / vue-cli\
  6. Server - 服务提供(Web Server、IM……)\
  7. CLI\

基本使用

command [subCommand] [options] [arguments]
command:命令,比如 vue
[subCommand]:子命令,比如 vue create
[options]:选项,配置,同一个命令不同选项会有不一样的操作结果,比如 vue -h,vue -v
[arguments]:参数,某些命令需要使用的值,比如 vue create myApp
选项与参数的区别:选项是命令内置实现,用户进行选择,参数一般是用户决定传入的值
选项一般会有全拼与简写形式(具体看使用的命令帮助),比如 --version = -v
全拼:以 – 开头 / 简写:以 - 开头
选项也可以接受值,值写在选项之后,通过空格分隔
多个简写的选项可以连写,开头使用一个 - 即可,需要注意的是,如果有接受值的选项需要放在最后,比如:\

vue create -d -r <-r的值> myApp
vue create -dr <-r的值> myApp
commander
命令行开发工具
chalk
命令行样式风格控制器
inquirer
交互式命令行工具
.parse(argv: string[])
解析执行传入的 argv 命令字符串,通常改命令字符串来自用户在命令行的输入,process.argv
commander 同时会默认创建一个 -h, --help 的选项
.version(str, flags?)
设置版本信息,该方法会自动为命令注册一个 -V, --version 的 option
str:版本号
flags:指定的 option,默认为:”-V, --version”
.option(flags, description?, fn?, defaultValue?)
设置命令选项
flags:选项标记名称,”-v, --version”
description:选项使用说明
fn:默认值,函数返回值为defaultValue,优先级高于defaultValue
defaultValue:选项默认值,如果需要的话
选项属性
flags 中的格式可以接收参数
-n, --name [val]
-n, --name
[] 可选
<> 必填
设置成功以后,会在命令对象下增加一个与全局的同名的属性
.action(fn)
指定命令要执行的动作行为
该函数执行过程会接收到至少一个参数
如果命令中带有参数,则是对应的参数列表
参数的最后一个永远都是 commander 实例
.command(name, desc?, opts?)
name:命令的名称,也可以接受值
‘create [appName]’
desc:简介
opts:配置
.description(str)
命令描述
.alias(str)
设置命令别名
.usage(str)
设置或获取当前命令的使用说明

安装使用commander

npm i commander

下面调用一下commander:

const commander=require('commander')


//设置当前的命令的版本
// commander.version('1.0.1')
//设置当前命令行可以改大小写
commander.version('1.0.1','-v,--version')

//[]表示可选 <>表示必填
// commander.option('-n, --name <val>','打印名称','cccc')
commander.option('-n, --name[val]','打印名称',function(val){
  console.log(val,'000000')
  return val
})


//设置命令的动作
commander.action(()=>{
  //console.log(commander)
  console.log('hi '+commander.rawArgs.name)
})
//解析来自process.argv上的数据
commander.parse(process.argv)
// console.log(commander);

实现一个ls命令

ls是linux环境经常用的一个命令,用来查看系统的目录结构,文件树。

下面展示一下实现代码:

/**
 * ls  输出当前运行的目录文件
 * ls d:\
 * 我们可以指定目录
 * 
 */

//加载commander方法
const commander=require('commander');
const fs=require('fs')

//设置当前命令工具的版本
commander.version('v1.0.0','-v, --version')

//子命令没有名字,
// const subcommander=commander.command('<path>')
  
// subcommander.option('-n, --name','设置名字')
//实现命令具体逻辑
commander.action((path)=>{
  //这里的path参数就是命令中定义的path

 console.log(path);

  //当前命令指定的目录下的文件以及文件夹全部显示在控制台上

  try{
    const files=fs.readdirSync(path)
    console.log(files);
    
  }catch(e){
    console.log(e);
    
  }
 
  
})
if(process.argv.length<3){
    process.argv.push(__dirname)
}

//解析argv
commander.parse(process.argv)

我们看到这个代码实现主要是用来fs模块来扫描遍历文件系统。 然后扫描打印制定参数path(文件路径)下的文件列表。

更进一步,实现-l命令。

实现-l命令,linux的-l参数是展示更多文件状态信息。

所以下面实现需要用fs模块打印输出更多文件的状态系统,并输出到console来。

下面是具体的实现代码。

/**
 * ls  输出当前运行的目录文件
 * ls d:\
 * 我们可以指定目录
 * 
 */

//加载commander方法
const commander=require('commander');
const fs=require('fs')

//设置当前命令工具的版本
commander.version('v1.0.0','-v, --version')

commander.option('-p ,--path [path]','设置要显示的目录',__dirname)

//如果选项不接收用户输入的参数值,那么这个选项将以boolean的形式提供给后面的形式使用
commander.option('-l ,-list [path]','以列表的形式显示')
  

//实现命令具体逻辑
commander.action(()=>{
  //这里的path参数就是命令中定义的path

  //option中的变量会挂在当前commander对象的同名属性下
  try{
    const files=fs.readdirSync(commander.path)
    console.log(commander.List);
    
    if(commander.List){
      let output=files.map(file =>{
        let stat=fs.statSync(commander.path+'/'+file);
        //是否文件夹
        let type=stat.isDirectory()?'目录':'文件'
        
       return `[${type}] ${file} \r\n`
      }).join('');
      console.log(output);
      
    }else{
      console.log('00000000000000000000000000')

      console.log(files);
      
    }
    
  }catch(e){
    console.log(e);
    
  }
 
 //console.log(commander);
 
  
})
if(process.argv.length<3){
    process.argv.push(__dirname)
}

//解析argv
commander.parse(process.argv)

好了,下面我们让commander展示的更加美化

chalk让你的commander 更加酷炫

默认 node 在输出终端的文字都是黑白的,为了使输出不再单调,添加文字背景什么的,改变字体颜色什么的,我们可以使用 chalk.js 这个库。

效果如下:

在这里插入图片描述\

chalk的案例在ls里面运用到

chalk 处理颜色正确处理终端字符串样式

下面是一个chalk的示例代码,可以看到各种配置很详细。


chalk
  chalk.<style>[.<style>...](string, [string...])
 Styles
  Modifiers 文字修饰:
 bold Colors 文字颜色:red、green、yellow、blue、cyan
  Background colors 背景颜色:bgRed、bgGreen、bgYellow、bgBlue、bgCyan 
  chalk
  Colors
  .hex('#DEADED')
  .keyword('orange')
  .rgb(15, 100, 204)
  Background colors
  .hex('#DEADED')
  .keyword('orange')
  .rgb(15, 100, 204) 
   chalk

安装chalk

npm i chalk / yarn add chalk

使用

const chalk = require('chalk') 得到一个 chalk 对象,通过这个对象,我们就可以给控制台中的文字加上各种样式了,就像css一样

Inquirer 交互式的命令行

交互式命令,提问用户,收集用户输入数据\

安装 npm i inquirer

使用

require(‘inquirer’)
inquirer.prompt(questions).then(answers=>{

})

下面我写一个q.js进行终端交互,代码如下:

const inquirer=require('inquirer')

//提问用户,与用户进行命令行的交互
// prompt数组中存在一个指定格式的对象
/*
Inquirer
  questions
    type:提问类型,input, confirm, list, rawlist, expand, checkbox, password, editor
    name:问题名称,供程序后续使用
    message:问题文字,给用户看的
    default:默认值
    choices:选项
    validate:输入验证
    filter:数据过滤

*/
inquirer.prompt([
{
  type:'input',
  name:'username',
  message:'请输入姓名',
  default:'wanzi',
  validate(val){
    if(val.trim()==''){
      return '应用名称不能为空'
    }else{
      return true
    }
  },
  //对用户输入的数据或选择的数据进行过滤
  filter(val){
    return val.toLowerCase()
  }
},
{
  type:'confirm',
  name:'xingbie',
  message:'是否同性恋',
  default:false
},{
  type:'list',
  name:'gongzi',
  message:'你的工资范围',
  choices:[
    '100-1000',
    '1000-2000'
  ],
  default:1
},{
  type:'rawlist',
  name:'gongzi2',
  message:'你的工资范围',
  choices:[
    '100-1000',
    '1000-2000'
  ],
  default:1
},{
  type:'checkbox',
  name:'tools',
  message:'你感兴趣的话题',
  choices:[{
    name:'美妆',
    value:'meizhuang',
    checked:true
  },{
    name:'明星',
    value:'mingxing'
  },{
    name:'八卦',
    value:'bagua'
  }]
}
]).then(answers=>{
  console.log(answers);
  
})

这个交互式的脚本的功能就是,根据用户输入提示进行输入,然后命令行收集到内容,之后综合的进行展示。

主要是输入用户名子,是否同性恋(非异性恋),选择工资范围,感兴趣的话题内容。

把代码复制黏贴到终端,试试看,最后综合展示出来。比较实用简单啊。

总结

今天这篇展示了commander的各种开发技巧,以及参数的深度处理。

同时也展示chalk 丰富了commander类命令行的样式。

最后也运用了inquirer做了一个多选择的输入框展示了一个丰富的组合的获取用户输入的一个展示案例。

总体来看nodejs的commander终端做的非常流畅很棒!

希望读者们多多尝试,这样一定能够把技术学好。

今天就写到这里。

我是丸子,每天学会一个小知识。
一个前端开发
希望多多支持鼓励,感谢