了解node命令行配置-搭建自己的脚手架

 

 

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到本地。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值