cli工具开发
战士上战场,不会写cli,怎么搭脚手架
介绍
什么是cli?全称就是command-line interface,即命令行工具,输入一行命令,通过一些交互操作,帮你搭建项目脚手架
环境准备
node环境
开始
创建目录并初始化
mkdir test-cli && cd test-cli
touch index.js // 添加代码console.log('我要放大招啦')
在这时执行:node index.js 就可以运行这个文件了
其他运行方式
用命令行来运行
运行npm init,会生成一个package.json文件,添加配置:
"bin":{
"test-cli":"./index.js"
},
然后在index.js中首行添加代码
#!/usr/bin/env node
这句话的意思其实就是用node来运行这个文件,当然同样可以把'node'换成'python'之类的
然后运行命令npm link
给当前项目创建一个软连接,这样就可以在任何目录下输入exercise-cli
来执行这个项目里的index.js文件了,删除软连接npm unlink exercise-cli
用npm来运行
在package.json文件中加如下代码:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"exercise":"test-cli"
}
这样就可以像我们平时运行项目一样通过npm run exercise
来运行了
直接运行
执行命令chown 755 index.js
将index.js设置为一个可执行文件,这样我们就可以直接在命令行中输入index.js
来运行这个文件了
拷贝项目模板
在项目根目录下创建如下文件, 就当是我们的项目模板了:
在index.js中加入代码:
const fse = require('fs-extra')
fse.copy(__dirname + '/templates', '.', (err) => {
if(err) throw err
console.log('项目模板拷贝成功')
})
新建一个项目目录,用来测试我们的exercise-cli
mkdir test-cli-project
cd test-cli-project
然后运行命令exercise-cli
,执行结果:
这样就将项目模板拷贝到我们的项目里了
提示:因为原生的fs模块很简陋,比如:只能复制文件,不能复制文件夹,目录必须存在等等,所以这里用了第三方包 fs-extra
传参
在index.js中输入代码
console.log(process.argv)
运行 exercise-cli name age
输出:
由此可知:第一个参数为node路径,第二个参数是当前项目的路径,第三个往后就是自己传入的参数了
修改index.js代码
let params = process.argv.slice(2)
if (params.includes('user')) {
console.log('收到参数"user",创建user文件')
fse.createFileSync('./user.js')
}
if (params.includes('utils')) {
console.log('收到参数"utils",创建utils文件')
fse.createFileSync('./lib/utils.js')
}
根据输入的参数来判断并执行相关的逻辑,输出结果:
上色
安装插件chalk并引入
//命令行安装
npm install chalk
//index.js引入
var chalk = require('chalk');
修改index.js代码:
if (params.includes('user')) {
console.log(`收到参数"${chalk.red('user')}",${chalk.blue.underline.bold('创建user文件')}`)
fse.createFileSync('./user.js')
}
if (params.includes('utils')) {
console.log(`收到参数"${chalk.red('utils')}",${chalk.blue.underline.bold('创建utils文件')}`)
fse.createFileSync('./lib/utils.js')
}
输出结果:
对话
安装并引入
npm i inquirer -s
// 引入
const inquirer = require('inquirer')
基本参数
- type:表示提问的类型,包括:input, confirm, list, rawlist, expand, checkbox, password, editor;
- name: 存储当前问题回答的变量;
- message:问题的描述;
- default:默认值;
- choices:列表选项,在某些type下可用,并且包含一个分隔符(separator);
- validate:对用户的回答进行校验;
- filter:对用户的回答进行过滤处理,返回处理后的值;
- transformer:对用户回答的显示效果进行处理(如:修改回答的字体或背景颜色),但不会影响最终的答案的内容;
- when:根据前面问题的回答,判断当前问题是否需要被回答;
- pageSize:修改某些type类型下的渲染行数;
- prefix:修改message默认前缀;
- suffix:修改message默认后缀。
使用
基本示例
const questions = [
{
type: 'input',
name: '姓名',
message: '请输入你的真实姓名',
default: '尼古拉斯'
}
]
inquirer.prompt(questions).then(answer => {
console.log(answer)
})
// async function test() {
// let answer = await inquirer.prompt(questions)
// console.log(answer)
// }
// test()
结果:
更多示例
const questions = [
{
type: 'input',
name: 'name',
message: '请输入你的真实姓名',
default: '尼古拉斯'
},
{
type: 'input',
name: 'phone',
message: '请输入11位手机号',
validate:val=>{
if(val.match(/\d{11}/g)){
return true
}
return '请输入11位数字'
}
},
{
type: 'confirm',
name: 'access',
message: '下班了吗?'
},
{
type: 'confirm',
name: 'access',
message: '确定要加班继续干吗?',
when: answers=>{
return answers.assess
}
},
{
type:'rawlist',
message:'要加班几小时?',
name:'eductionBg',
choices:[
"1小时",
"2小时",
"通宵"
],
filter:val=>{//将选择的内容后面加学历
return '今晚要加班' + val
}
},
{
type:'expand',
message:'夜宵吃啥?',
name:'fruit',
choices: [
{
key: "p",
name: "泡面",
value: "泡面"
},
new inquirer.Separator(),
{
key: "m",
name: "面包",
value: "面包"
},
new inquirer.Separator('------华丽的-------'),
{
key: "n",
name: "不吃了",
value: "不吃了"
},
]
},
{
type:'password',
message:'请输入你的银行卡密码:',
name:'pwd'
}
]
inquirer.prompt(questions).then(answer => {
console.log(answer)
})
结果:
登堂入室
在我们学前端时是先学HTML,js,css等,基础学会了真正写项目时会用jQuery,vue,react等框架之类的
这里也一样,cli的基本操作了解了,真正实战时用一些工具会更加效率, 下面介绍commander的简单使用
安装并引入commander
npm i commander -s
const { program } = require('commander')
基本使用
在index.js中写入
program.version('0.0.1') // 设置版本
program
.option('-e, --eat', '今晚吃饭吗') // 普通用法
.option('-w, --what-food <type>', '吃什么') // 带参数,key是两个单词
.option('-s, --small <size>', '大份还是小份', '小份') // 带参数,并且有默认值
program.parse(process.argv) // 解析参数
console.log('所有参数:', program.opts())
console.log('eat:', program.eat)
console.log('small:', program.small)
console.log('whatFood:', program.whatFood)
这里'.option'可以给program添加参数,经过解析后可以很方便的获取参数,看以下实验
命令行输入:exercise-cli -h
exercise-cli -V
exercise-cli
exercise-cli -ew 烧鸡
两个参数之间的-可以省略exercise-cli -e -s 大份 -w 烧鸡
多个参数自定义处理参数
在index.js中写入
function myParseInt(value) {
return parseInt(value);
}
program
.option('-i, --integer <num>', '会自动转换成int类型', myParseInt)
program.parse(process.argv) // 解析参数
if (program.integer) console.log('integer:', program.integer)
命令行输入:exercise-cli -i 1.2
自定义命令
program
.command('custom <name> [fileName]')
.description('自定义命令,可以接受参数')
.action((source, destination) => {
// 执行该命令的回调
console.log('执行回调')
console.log('参数:', source);
})
program.parse(process.argv)
命令行输入exercise-cli -h
可以看到多了一个命令,试一下:
exercise-cli custom user.js
结束
到这里cli工具开发就介绍完了,快去实战吧
参考文章:用一次就会爱上的cli工具开发