1 Chalk 命令行输出五颜六色的字体
mkdir node-command
cd node-command
touch chalk.js
chalk.js
console.log(1);
node chalk.js
控制台打印出了一个1,Chalk模块就是用来改变这里打印出来的字体颜色的。
npm install chalk --S
const chalk = require('chalk')
console.log(chalk.red(1));
执行,打印出红色的1
也可以使用rgb自定义颜色:
console.log(chalk.rgb(211, 188, 12)(1));
也可以增加背景色
console.log(chalk.rgb(211, 188, 12).bgRed('hello word'));
自定义背景色:
console.log(chalk.rgb(211, 188, 12).bgRgb(34, 55, 22)('hello word'));
2 ora模块:loading效果,图标
npm install ora
const chalk = require('chalk')
const ora = require('ora')
const spinner = ora('Hellor word').start()
执行,文字前面有一个转动的标:
也可以结合一起使用,字体颜色为红色:
const spinner = ora(chalk.red('Hellor word')).start()
改变标的颜色:
spinner.color = 'red'
停止旋转:
spinner.stop();
3 commander:定义命令,解析命令
option
index.js
#! /usr/bin/env node
const cm = require('commander');
const inquirer = require('inquirer')
const ora = require('ora')
const spinner = require('spinner')
cm.option('-p, --person', 'add person')
cm.parse(process.argv);
console.log(cm.person);
node index.js -p
短标志可以作为单个arg传递,例如-abc相当于-a -b -c。 比如“ --template-engine”之类的多词组成的选项会变成骆驼式的program.templateEngine。
请注意,以--no前缀开头的多词选项是其后选项的布尔值的反。 例如,--no-sauce将program.sauce的值设置为false。
const cm = require('commander');
cm.option('--no-person', 'remove person')
cm.parse(process.argv);
console.log(cm.person);
node index.js --no-person
你可以在命令上绑定选项
const cm = require('commander');
cm
.command('rm <dir>')
.option('-r, --recursive', 'Remove recursively')
.action(function(dir, cmd) {
console.log(dir, cmd.recursive)
console.log('remove ' + dir + (cmd.recursive ? ' recursively' : ''))
})
cm.parse(process.argv)
node rm ./aaa -r
还可以这么设置
const cm = require('commander');
cm
.command('rm <dir>')
.option('-r, --recursive <n>', 'Remove recursively', function(val) {
console.log(val)
return val
}, 0)
.action(function(dir, cmd) {
console.log(cmd.recursive)
})
cm.parse(process.argv)
可以拿到输入的值
可以是数组
const cm = require('commander');
cm
.command('rm <dir>')
.option('-r, --recursive <n>', 'Remove recursively', function(val) {
console.log(val)
return val
}, 0)
.option('-p, --list <list>', 'add list', function(val) {
console.log(val)
const aa = []
aa.push(val)
return aa
}, [])
.action(function(dir, cmd) {
console.log(cmd.list)
})
cm.parse(process.argv)
version
调用版本会默认将-V和--version选项添加到命令中。 当存在这些选项中的任何一个时,该命令将打印版本号并退出。
const cm = require('commander');
cm.version('0.0.1')
cm.parse(process.argv)
node -V
也可以自定义
const cm = require('commander');
cm.version('0.0.1', '-v, --version')
cm.parse(process.argv)
arguments
指定参数
var program = require('commander');
var cmdValue, envValue
program
.version('0.1.0')
.arguments('<cmd> [env]')
.action(function (cmd, env) {
cmdValue = cmd;
envValue = env;
});
program.parse(process.argv);
if (typeof cmdValue === 'undefined') {
console.error('no command given!');
process.exit(1);
}
console.log('command:', cmdValue);
console.log('environment:', envValue || "no environment given");
node index.js hello param
尖角括号<>(例如<cmd>)表示必需的输入。 方括号(例如[env])表示可选输入。
usage
const cm = require('commander')
cm
.name("my-command")
.usage("[global options] command")
.parse(process.argv)
node index.js -h
展示在帮助的第一行
4 inquirer用户与命令行交互的工具
注意:测试过程中,命令行的clitest init aaa 请执行node index.js文件
安装:
npm install inquirer
index.js文件
const inquirer = require('inquirer')
const promptList = []
inquirer.prompt(promptList).then((answers) => {
console.log(answers)
// cloneProject({ name, ...answers })
})
input
const promptList = [{
type: 'input',
message: '文件夹名字:',
name: 'fileName',
default: "my-project" // 默认值
}];
confirm
const promptList = [{
type: "confirm",
message: "是否使用less?",
name: "less",
prefix: "前缀"
}, {
type: "confirm",
message: "是否使用ts",
name: "ts",
suffix: "后缀",
when: function(answers) { // 当less为true的时候才会提问当前问题
return answers.less
}
}];
list
const promptList = [{
type: 'list',
message: '请选择一种水果:',
name: 'fruit',
choices: [
"Apple",
"Pear",
"Banana"
],
filter: function (val) { // 使用filter将回答变为小写
return val.toLowerCase();
}
}];
rawlist
const promptList = [{
type: 'rawlist',
message: '请选择样式文件:',
name: 'style',
choices: [
"less",
"scss",
"css"
]
}];
expand
const promptList = [{
type: "expand",
message: "请选择样式文件:",
name: "style",
choices: [
{
key: "l",
name: "less",
value: "less"
},
{
key: "s",
name: "scss",
value: "scss"
},
{
key: "c",
name: "css",
value: "css"
}
]
}];
checkbox
const promptList = [{
type: "checkbox",
message: "选择颜色:",
name: "style",
choices: [
"less",
"acss",
"css",
],
pageSize: 3 // 设置行数
}];
a可以全选
也可以这样
const promptList = [{
type: "checkbox",
message: "选择颜色:",
name: "style",
choices: [
{
name: "less",
checked: true // 默认选中
},
new inquirer.Separator(), // 添加分隔符
{
name: "scss",
},
new inquirer.Separator("--- 分隔符 ---"), // 自定义分隔符
{
name: "css",
}
],
pageSize: 6 // 设置行数
}];
password
const promptList = [{
type: "password", // 密码为密文输入
message: "请输入密码:",
name: "pwd"
}];
editor
const promptList = [{
type: "editor",
message: "请输入内容:",
name: "editor"
}];
按下enter开始编辑
按下i进入编辑模式
编辑结束,按esc,:wq保存并退出
5 从0开始搭建脚手架
项目根目录commander
mkdir commander
cd commander
touch index.js
npm init
package.json文件中加入一个属性
"bin": {
"clitest": "./index.js"
},
如果把这个commander包发布到npm,然后全局下载这个包,就可以通过clitest命令去执行index.js文件。
因为我们是在本地调试,没有发布这个包,所以需要用npm link把这个命令关联起来
打开终端,输入:
npm link
如果被拒绝,可以使用sudo提权。
然后命令行执行clitest,这种情况下会报错,因为没有告诉命令行用什么环境去执行。需要在index.js文件中加入一句注释,告诉它执行环境是node
#! /usr/bin/env node
console.log(1)
clitest 正常打印:
安装:
npm install commander
npm install inquirer
修改index.js文件
#! /usr/bin/env node
const cm = require('commander');
const inquirer = require('inquirer')
// 定义命令
cm.version('1.0.0', '-v, --version');
// 解析命令
cm.parse(process.argv);
parse 是解析你命令行里边传进来的参数 比如 你写了一个 clitest -v, 那么这个时候 回调里边的args的值就是
[ '/usr/local/bin/node', '/usr/local/bin/clitest', '-v' ]
clitest -v 查看版本号:
自定义命令:第一个参数数命令,第二个参数是解释信息,第三个参数是一个回调
// 自定义命令
cm.option('-a, --atest', 'this is test', () => {
console.log(3)
})
和用户交互:
cm.command("init <name>").action(name => {
inquirer.prompt(promptList).then((answers) => {
console.log(answers)
})
})
现在已经拿到了用户输入的信息,接下里就是根据用户输入的信息去下载相应的模版。
根目录下创建
mkdir bin
cd bin
touch index.js
cd ../
mkdir project 创建一个项目目录
简单的创建一下项目目录结构
bin/index.js
module.exports = function cloneProject({ name }) {
console.log(name)
}
在index.js中引入这个方法,调用,把用户输入的信息传递给这个方法:
...
const cloneProject = require('./bin/index')
...
cm.command("init <name>").action(name => {
inquirer.prompt(promptList).then((answers) => {
console.log(answers);
cloneProject({ name, ...answers })
})
})
下面模拟一个本地clone项目过程:
创建vue项目的时候,全局安装vue-cli后就可以直接下面命令初始化一个vue项目,项目的名称是my-project
vue create my-project
使用我们新创建的脚手架
clitest init my-project
cloneProjec函数将会拿到my-project这个目录名称,我们就可以在cloneProjec这个函数内部将project中所有文件内容clone到my-project中。vue的脚手架做的是去github,clone项目到my-project中,原理是一样的。
方法实现如下:
bin/index.js
const fs = require('fs');
const sourceFile = [];
module.exports = function cloneProject({ name }) {
const sourcePath = './project'
const targetPath = './' + name
fs.mkdir(targetPath, () => {
getPath(sourcePath);
sourceFile.forEach((pathItem) => {
const newPath = targetPath + pathItem.path.replace('./project', '')
if (pathItem.key === 'dir') {
fs.mkdir(newPath, () => { })
} else {
const data = fs.readFileSync(pathItem.path)
fs.writeFileSync(newPath, data)
}
})
})
}
function getPath(path) {
const files = fs.readdirSync(path);
files.forEach((item) => {
const nowPath = `${path}/${item}`;
const stat = fs.statSync(nowPath);
if (stat.isDirectory()) {
getPath(nowPath);
sourceFile.push({ key: 'dir', path: nowPath })
} else {
sourceFile.push({ key: 'file', path: nowPath })
}
})
}
拉取github上面的项目
根目录下的index.js
#! /usr/bin/env node
const cm = require('commander');
const inquirer = require('inquirer')
const cloneProject = require('./bin/index')
const downLoad = require('download-git-repo')
const ora = require('ora')
const spinner = require('spinner')
let url = 'vuejs/vue' // 全路径https://github.com/vuejs/vue 不用加前缀
let clone = false
let downGit = (name) => {
const spinner = ora('正在拉取模板...')
spinner.start()
downLoad(url, name, {
clone
}, err => {
spinner.stop()
console.log(err ? err : "项目创建成功")
process.exit(1)
})
}
cm.command("init <name>").action(name => {
downGit(name)
})
// 解析命令
cm.parse(process.argv);
项目根目录下会多一个aaa文件夹,这个就是vue
这样就可以帮写好的项目架构放置在github上面,发布一个脚手架,通过脚手架把初始化的项目clone到本地。