В этой статье вы ознакомитесь с базовыми знаниями, необходимыми для создания инструмента Node-CLI.
Во-первых, анализ параметров командной строки
В NodeJS параметры, переданные в командной строке, можно получить с помощью следующего кода:
process.argv.slice(2)
Но для построения CLI-инструмента этого далеко не достаточно.В первую очередь необходимо учитывать различные стили ввода параметров:
- Стиль параметра Unix: с префиксом -, но за которым следует один символ, например, -abc разрешается в ['a', 'b', 'c'].
- Стиль параметра GNU: добавить -- впереди, например, команду в npm, npm --save-dev webpack.
- Стиль параметра BSD: впереди не добавляются модификаторы.
Здесь вы можете обрабатывать process.argv через регулярные выражения:
/**
* 解析Unix、BSD和GNU参数风格
* @param {Array} argv 命令行参数数组
* @returns
*/
function parseArgv (argv) {
const max = argv.length
const result = {
_: []
}
for (let i = 0; i < max; i++) {
const arg = argv[i]
const next = argv[i + 1]
if (/^--.+/.test(arg)) {
// GNU风格
const key = arg.match(/^--(.+)/)[1]
if (next != null && !/^-.+/.test(next)) {
result[key] = next
i++
} else {
result[key] = true
}
} else if (/^-[^-]+/.test(arg)) {
// Unix风格
const items = arg.match(/^-([^-]+)/)[1].split('')
for (let j = 0, max = items.length; j < max; j++) {
const item = items[j]
// 非字母不解析
if (!/[a-zA-Z]/.test(item)) {
continue
}
if (next != null && !/^-.+/.test(next) && j === max - 1) {
result[item] = next
i++
} else {
result[item] = true
}
}
} else {
// BSD风格
result._.push(arg)
}
}
return result
}
С помощью вышеуказанного метода можно получить следующие результаты:
node example1.js --save-dev -age 20 some
// => 结果
{
_: ['some'],
'save-dev': true,
a: true,
g: true,
e: 20
}
Приведенный выше пример не только показывает результат синтаксического анализа, но и подчеркивает, что стиль параметров Unix анализирует только одну букву, поэтому значение этого стиля параметров может быть неоднозначным и ограниченным по количеству, поэтому вам нужно использовать это в правильном сценарии параметры стиля:
npm --save-dev webpack
npm -D webpack
npm использует стиль параметров Unix для сокращения, что является очень подходящим способом, поэтому -age в предыдущем примере следует изменить на --age в соответствии с семантикой, что более разумно.
Во-вторых, интерфейс командной строки.
Модуль readline в NodeJS предоставляет методы вопросов и подсказок для создания интерфейса командной строки. Ниже приведен простой интерфейс вопросов и ответов:
const readline = require('readline');
const question = ['请输入您的姓名', '请输入您的年龄']
const result = []
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
prompt: `?${question[0]} `
});
rl.prompt();
rl.on('line', (line) => {
result.push(line.trim())
const max = result.length
if (max === question.length) {
rl.close()
}
rl.setPrompt(`?${question[max]} `)
rl.prompt();
}).on('close', () => {
console.log(`谢谢参与问答 *** 姓名: ${result[0]} 年龄: ${result[1]}`);
process.exit(0);
});
Конечно, элементы интерактивного интерфейса не единственные.При использовании различных инструментов CLI вы должны столкнуться с такими как: одиночный выбор, индикатор выполнения загрузки...
Следующее может попытаться реализовать интерфейс с одним выбором:
const readline = require('readline')
let selected = 0
const choices = ['javascript', 'css', 'html']
let lineCount = 0
const rl = readline.createInterface(process.stdin, process.stdout)
function reader () {
let str = ''
for (let i = 0; i < choices.length; i++) {
lineCount++
str += `${selected === i ? '[X]' : '[ ]'} ${choices[i]}\r\n`
}
process.stdout.write(str)
}
reader()
process.stdin.on('keypress', (s, key) => {
const name = key.name
const max = choices.length
if (name === 'up' && selected > 0) {
selected--
} else if (name === 'down' && selected < max - 1) {
selected++
} else if (name === 'down' && selected === max - 1) {
selected = 0
} else if (name === 'up' && selected === 0) {
selected = max - 1
} else {
return true
}
// 移动光标至起始位置,确保后续输入覆盖当前内容
readline.moveCursor(process.stdout, 0, -lineCount)
lineCount -= choices.length
reader()
})
rl.on('line', () => {
console.log(`you choose ${choices[selected]}`)
process.exit(0)
}).on('close', () => {
rl.close()
})
3. Индивидуальный стиль
Чтобы эффективно отличать информацию в интерфейсе командной строки, мы можем добавить соответствующие стили к выходной информации здесь.
Вот синтаксис добавления стилей к строкам:
\x1b[背景颜色编号;字体颜色编号m
Каждый стиль должен начинаться с \x1b[:
// \x1b[0m 清除样式
process.stdout.write('\x1b[44;37m OK \x1b[0m just do it\n')
В-четвертых, пользовательские команды Node.
Следующим шагом является настройка команды Node.Сначала необходимо создать файл выполнения команды:
// hello.js 首行需要指定脚本的解释程序
#!/usr/bin/env node
console.log('hello')
Повторно используйте конфигурацию bin в package.json:
{
"bin": {
"hello": "./hello.js"
},
}
Выполните команду ссылки npm:
npm link
# 输入自定义命令
hello
# 输出 hello
V. Резюме
Вышеизложенное представляет некоторые базовые знания, необходимые для разработки Node-CLI, но для тех, кто использовал такие инструменты, как webpack-cli и vue-cli, вы можете обнаружить, что эти отличные инструменты CLI также имеют:
- подкоманды в стиле git;
- автоматизированная справочная информация;
- ....
Тогда вам очень помогут следующие зрелые фреймворки: