什么是CLI
CLI(command-line interface,命令行界面)是指可在用户提示符下键入可执行指令的界面,它通常不支持鼠标,用户通过键盘输入指令,计算机接收到指令后,予以执行。像我们平常经常使用的 Git, npm 等都是CLI工具。
通常认为,命令行界面(CLI)没有图形用户界面(GUI)那么方便用户操作。因为,命令行界面的软件通常需要用户记忆操作的命令,但是,由于其本身的特点,命令行界面要较图形用户界面节约计算机系统的资源。在熟记命令的前提下,使用命令行界面往往要较使用图形用户界面的操作速度要快。所以,图形用户界面的操作系统中,都保留着可选的命令行界面。
一个简单的CLI实现
CLI可以通过多种语言实现,本文将选择NodeJs来实现一个简单的CLI工具
初始化项目环境
首先 我们需要新建一个文件夹,用来开发
mkdir hello-cli
cd hello-cli
初始化项目及配置
npm init
此时文件夹内会生成一个package.json文件。
新建一个index.js文件 作为命令行触发的脚本,随便写几行。
记得加上 #!/usr/bin/env node。 这一行的目的是告诉系统,使用node的解释器来解释下面的代码。但是,该命令仅生效于类linux系统,因为对于windows而言,是通过文件的后缀名来决定读取文件的方式的。如果要在windows内调试,需要使用git bash。
#!/usr/bin/env node
console.log('hello cli');
console.error('nice to meet you')
在package.json内配置命令。考虑到习惯问题,在这里模块使用改为ES6 Module。
{
"name": "hello-cli",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module", //改为ES6 Module
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
/** 新增下方代码 **/
"bin": {
"hello-cli": "index.js" //这里是你的命令及脚本入口
},
"author": "",
"license": "ISC"
}
通过 npm link 进行本地调试。
npm link
打开命令行输入
hello-cli
运行成功!
CLI参数处理
当我们在使用git时总会使用git add , git commit 等,而这些add, commit 便是CLI的参数。脚本内通过 process.argv 获得CLI参数作为输入。因此我们测试一下:
index.js
console.log(process.argv);
命令行输入
hello-cli -v
可见, process.argv是一个数组,数组内前两个元素是你的解释器位置和文件位置,第三个便是输入的命令。
如果输入两个参数呢?
开发第一个功能
有了上面的基础,我们便可以对功能进行开发,这里我们来开发一个功能,输出当前CLI的版本号
index.js
#!/usr/bin/env node
import fs from 'fs';
import path from 'path';
import {fileURLToPath} from 'url';
const commandList = process.argv.slice(2);
commandList.forEach(async (command) => {
switch(command){
case '-v':
/** 由于执行命令的位置不确定, 因此不能使用相对路径传入readFileSync,下文使用了import.meta.url来获得绝对路径进行拼接*/
const fileName = fileURLToPath(import.meta.url);
const dirName = path.dirname(fileName);
const packagePath = path.join(dirName, 'package.json'); //读取package.json文件
const pkg = fs.readFileSync(packagePath);
const packageObj = JSON.parse(pkg);
console.log(`version: ${packageObj.version}`);
break;
default:
console.log(`无法识别命令: ${command}`);
}
})
使用CLI
hello-cli -v
获取版本号成功!
接下来便开始开发自己的CLI工具啦!
交互实现
若想实现命令行的交互能力需要引用npm包:inquirer
首先安装 inquire:下文仅对于inquire进行简单的使用,具体文档可参考: inquirer官方文档
npm i inquirer
然后,实现交互能力
#!/usr/bin/env node
import inquirer from 'inquirer';
import fs from 'fs';
import path from 'path';
import {fileURLToPath} from 'url';
const commandList = process.argv.slice(2);
commandList.forEach(async (command) => {
switch(command){
case '-v':
const fileName = fileURLToPath(import.meta.url);
const dirName = path.dirname(fileName);
const packagePath = path.join(dirName, 'package.json')
const pkg = fs.readFileSync(packagePath);
const packageObj = JSON.parse(pkg);
console.log(fileName)
console.log(`version: ${packageObj.version}`);
break;
case 'age':
await getAge();
break;
default:
console.log(`无法识别命令: ${command}`);
}
})
async function getAge() {
const question = {
type: 'input', //type是交互的参数,这里选择输入类型
name: 'age', //name是这个问题用户输入结果的key,所有answer是一个对象
message: 'how old are you?', //这里是交互的问题
default: '18', //这个是问题答案的默认值,如果用户不输入则取该值
}
/** prompt会生成一个问题,同时在用户输入后对返回的promise进行决义,其参数是一个CLI执行过程中生成的输入聚合对象 */
await inquirer.prompt(question).then((answer) => {
console.log(`经过计算,你的年龄是:${answer.age}`);
})
}
让我们来试试结果