[toc]
node 利用命令行交互生成相应模板
- 创建时间:2019-10-15
- 测试环境:win10 node-v10.16.1
受 vue-cli
初始化项目的启发,想探究其原理和自己实现一套类似方法,以便在项目中创建公用模板块。
这里采用三种方式实现
- node 自带的
readline
- 使用process实现
- 第三方包
inquirer
commander.js
用于创建 cli 设置程序版本 -v --version 等命令行 提供了用户命令行输入和参数解析
chalk
设置命令行样式颜色
所有实现方式的完整代码 github 链接
链接文件结构如下
|-- generatorTemplate.js (生成模板)
|-- readline.js (readline 方式完整代码)
|-- process.js (process 方式完整代码)
|-- inquirer.js (inquirer 方式完整代码)
创建的模板示例:根据用户输入的不同,返回不同结果,包括实现了生成一个文件夹,文件夹内容如下
|--template
|--css
|--images
|--js
|-- index.js
readline 实现
引入 node 自带的 readline
const readline = require('readline');
初始创建
const rl = readline.createInterface({
/* 监听可读流 */
input: process.stdin,
/* 读取写入的 可写流 */
output: process.stdout,
/* 提示信息 */
// prompt: '请输入:'
});
这里会一直监听用户的输入 当输入template时 创建模板
rl.on('line', function(input) {
if(input === 'template') {
/* 这里的generator方法参见下方 */
generatorTemplate.generator()
rl.close()
} else if (input === 'pause') {
rl.pause()
} else {
rl.write('please input right: ');
}
})
完整代码查看 readline.js
更多用法参考: 官方文档 readline
使用process实现
当用户输入的内容为template时,就生成模板
const processFn = () => {
const handleInput = (input) => {
if(input === 'student') {
process.stdout.write('there is student here: hew\n')
} else if(input === 'template') {
/* 这里的generator方法参见 */
generatorTemplate.generator()
process.stdin.emit('end');
} else {
process.stdout.write('some other input message\n')
process.stdin.emit('end');
}
}
process.stdin.setEncoding('utf-8')
process.stdin.on('readable', () => {
let chunk = null;
while ((chunk = process.stdin.read()) !== null) {
if (typeof chunk === 'string') {
chunk = chunk.slice(0, -2);
if(chunk) {
handleInput(chunk)
} else {
process.stdin.emit('end');
}
}
}
})
process.stdin.on('end', () => {
process.stdout.write('结束\n');
process.exit()
})
}
完整代码查看 process.js
更多用法参考: 官方文档 process
使用 inquirer
https://github.com/JohnApache/inquirer-usage-doc 文档说明
9以上版本 不能用 require 引入
expand 会把所有的 choice 的key 集合起来提示,然后用户输入对应的key,显示对应key的name值
inquirer
.prompt([
{
type: 'confirm',
name: 'toBeDelivered',
message: '是否生成模板?', // 这里的值可以用 chalk.blueBright(‘xxx’),
prefix: '|-', // 问题描述前置信息,可以设置以去掉开头显示的问号
suffix: ':', // 最终输出 |- 是否生成模板? :
default: false
},
{
type: "input",
name: "input",
message: '请输入',
prefix: '|-',
suffix: ':',
transformer(value) { // 修改用户的输入内容格式等,但不会修改实际的输入值,只影响显示
return chalk.cyan(value);
},
validate: function(value) {
if(/^a$/ig.test(value)) {
return true
} else {
/* 校验务必采用返回 error 不然不会有错误提示 */
return chalk.red(new Error('请输入正确'))
}
}
},
{
type: 'list',
name: 'configType',
message: '请选择配置操作',
when: h => h.configType === 0,// 当前面答案符合某个条件时,显示当前问题
choices: [
{ name: '1. 配置页面颜色', value: 0, },
{ name: '2. 配置按钮布局', value: 1, }
],
},
{
type: 'checkbox',
name: 'choices',
message: 'Is this for delivery?',
default: 'check',
choices: ['yes', 'no']
}
],
// {
// confirm: true // 这里放问题答案,如果在此配置,对应的问题将直接跳过,默认使用该答案
// }
)
.then(answers => {
console.log(answers);
/* 输出值为:{ toBeDelivered: true, choices: [ 'name' ] } */
if(answers.toBeDelivered && answers.choices[0] === 'yes') {
/* 这里的generator方法参见下方 */
generatorTemplate.generator();
} else {
console.log('不生成模板');
}
}).catch((error) => {
if (error.isTtyError) {
// Prompt couldn't be rendered in the current environment
console.log(error);
} else {
// Something else went wrong
console.log(error);
}
});
完整代码查看 inquirer.js
更多用法参考: 官方文档 inquirer
调用的生成模板方法 (generator 方法)
generator.js
const fs = require('fs');
const path = require('path');
const jsStr =
`const a = '';
const b = 1;
export default {
a: a,
b: b
}
`
function generator() {
fs.mkdirSync(path.join(__dirname, 'template'));
fs.mkdirSync(path.join(__dirname, 'template', 'css'));
fs.mkdirSync(path.join(__dirname, 'template', 'js'));
fs.mkdirSync(path.join(__dirname, 'template', 'images'));
fs.writeFileSync(path.join(__dirname, 'template', 'js', 'index.js'), jsStr, 'utf-8')
}
exports.generator = generator;
欢迎交流 Github