Наверху написано, очень хочу написать рецепт, страдаю ограниченными кулинарными способностями, поэтому заголовок враньё, ха-ха ^_~
Сегодня поговорим о разработке инструментов командной строки (например, CLI: интерфейс командной строки, CLI будет использоваться для замены длинных существительных инструментов командной строки ниже).
Прочитав эту статью, вы получите более полное представление о разработке CLI от начала до конца.
Вы также можете добавить эту статью в закладки, когда захотите разработать CLI, вернитесь и посмотрите ее, вы всегда найдете то, что хотите.
Дэниел: Арахисовая кола готова, просто подожди и начинай.
Ладно, пошли, пошли!
> Сделайте первый шаг: инициализируйте проект
Создайте пустой каталог проекта (все начинается сcook-cli
Например, так здесь мы называем этоcook-cli
), а затем нажмите команду в этом каталоге для инициализации, процесс выглядит следующим образом:
$ mkdir cook-cli
$ cd cook-cli
$ npm init --yes
пройти черезnpm init
команда, инициализирует каталог вNode.js
проект, он будет вcook-cli
создается в каталогеpackage.json
документ.
Добавить--yes
Он автоматически ответит на все вопросы, заданные в процессе инициализации.Вы можете попробовать убрать этот параметр и отвечать на вопросы по порядку самостоятельно.
> Основная ветка открыта: скелетный код CLI
Проект инициализирован, давайте добавим скелетный код и позволим CLI немного поработать.
- исполнитель
мы создаемsrc/index.js
Файл, отвечающий за реализацию функциональной логики CLI, и есть фактическая работа. код показывает, как показано ниже:
export function cli(args) {
console.log('I like cooking');
}
- пресс-секретарь
Затем создайтеbin/cook
файл, который является исполняемым входным файлом CLI и представителем CLI в исполняемой среде. код показывает, как показано ниже:
#!/usr/bin/env node
require = require('esm')(module /*, options*/);
require('../src').cli(process.argv);
Осторожно, вы обнаружите, что он используется здесьesm
Этот модуль, его роль состоит в том, чтобы позволить нам использовать его непосредственно в исходном коде js.ECMAScript modules
канонические загрузочные модули, т.е. использовать напрямуюimport
а такжеexport
. надsrc/index.js
можно написать прямо в кодеexport
благодаря этому модулю.
(Пожалуйста, запустите в корневом каталоге проектаnpm i esm
установить модуль)
- официальное объявление
У нас есть представители, но мы должны их предать гласности. так вpackage.json
увеличить вbin
заявление, объявляющее о существовании пресс-секретаря. следующим образом:
{
...
"bin": {
"cook": "./bin/cook"
},
...
}
> Репетиция момента: локальный запуск и отладка
До появления CLI локальная разработка и отладка были необходимы, поэтому был необходим удобный путь отладки.
Дэниел: Разрабатывая веб-приложение, я могу отлаживать функционал через браузер. Как насчет CLI вчера?
CLI в конечном итоге запускается на терминале, поэтому сначала нам нужно зарегистрировать его как локальную командную строку. Метод очень прост, достаточно выполнить следующую команду в корневом каталоге проекта:
$ npm link
Эта команда зарегистрируетcook
CLI и свяжите его код логики выполнения с каталогом вашего проекта, чтобы каждый раз, когда вы его сохраняете, он сразу же вступал в силу.
Попробуйте выполнить следующие команды:
$ cook
Дэниел: Красиво! Но у меня все еще есть проблема, я хочу установить точки останова в vscode для отладки, поэтому иногда проще устранить неполадки.
Ты прав. Способ тоже очень простой, достаточно добавить в vscode следующую конфигурацию, путь такой:调试 > 添加配置
. В соответствии с фактическими отлаживаемыми параметрами команды изменитеargs
можно использовать значение.
{
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Cook",
"program": "${workspaceFolder}/bin/cook",
"args": ["hello"] // Fill in the parameters you want to debug
}
]
}
> Распознавание намерений: анализ входных параметров
Небольшая интерлюдия: хотя вы можете часто сталкиваться с различными CLI в своей работе, вот краткое введение в некоторые термины, связанные с CLI:
- Команда и подкоманда
# cook 即为命令
$ cook
# start 即为 cook 的 子命令
$ cook start
- параметры команды
# -V 为简写模式(short flag)的选项(注意:只能一个字母,多个字母代表多个选项)
$ cook -V
# --version 为全写模式(long name)的选项
$ cook --version
- Аргументы команды (аргумент)
# source.js 和 target.js 都为 cp 命令的参数
$ cp source.js target.js
Фактически, подкоманды также являются параметрами команды.
Хорошо, из приведенного выше введения мы хотим реализовать CLI, и анализ входных параметров (включая подкоманду, параметры, аргумент) неизбежен, поэтому давайте посмотрим правде в глаза.
командир: Эй, брат, не бойся, это я!
Да, братан, как хорошо, что ты есть. Далее мы используемcommander
Этот модуль анализирует входные параметры Процесс и пример следующие:
- Установка модуля
$ npm i commander
- пример src/index.js
......
import program from 'commander';
export function cli(args) {
program.parse(args);
}
Получите это в одном предложении, это так аккуратно и аккуратно.
Даниэль: Что насчет участия? Как это использовать?
В следующих примерах мы будем использовать эти проанализированные объекты ввода. Так что, пожалуйста, расслабьтесь.
> Не могу жить без тебя: версии и помощь
Версия и справочная информация являются обязательной частью интерфейса командной строки, иначе это выглядит непрофессионально. Давайте посмотрим, как это сделать.
Исправлятьsrc/index.js
, код показан ниже:
import program from 'commander';
import pkg from '../package.json';
export function cli(args) {
program.version(pkg.version, '-V, --version').usage('<command> [options]');
program.parse(args);
}
пройти черезprogram.version
а такжеusage
Цепной звонок сделан, и это все еще так холодно.
Попробуйте выполнить следующие команды:
$ cook -V
$ cook -h
> Добавить генералы: добавить подкоманды
Теперь приступаем к обогащению функционала CLI, начиная с добавления подкомандыstart
Начинать.
у него есть параметрfood
и вариант--fruit
, код показан ниже:
......
export function cli(args) {
.....
program
.command('start <food>')
.option('-f, --fruit <name>', 'Fruit to be added')
.description('Start cooking food')
.action(function(food, option) {
console.log(`run start command`);
console.log(`argument: ${food}`);
console.log(`option: fruit = ${option.fruit}`);
});
program.parse(args);
}
В приведенном выше примере показано, как получить проанализированные входные параметры вaction
Вы можете получить все, что хотите, и то, что вы хотите сделать, полностью зависит от вас.
Попробуйте запустить подкоманду:
$ cook start pizza -f apple
> Ищите иностранную помощь: вызовите внешнюю команду
Иногда нам нужно вызывать внешние команды в CLI, напримерnpm
какой-то тип.
execa: Моя очередь выступать. ┏ (^ω^)=☞
- Установка модуля
$ npm i execa
- пример src/index.js
......
import execa from 'execa';
export function cli(args) {
.....
program
.command('npm-version')
.description('Display npm version')
.action(async function() {
const { stdout } = await execa('npm -v');
console.log('Npm version:', stdout);
});
program.parse(args);
}
над переваломexeca
вызвать внешнюю командуnpm -v
. давай, распечатывайnpm
Номер его версии:
$ cook npm-version
> Облегчение коммуникации: обеспечение взаимодействия человека с компьютером
Иногда мы хотим, чтобы интерфейс командной строки взаимодействовал с пользователем с помощью метода вопросов и ответов, когда пользователь предоставляет нужную нам информацию, вводя или выбирая.
В этот момент подул порыв ветра, и я увидел
Inquirer.js
Бегать по разноцветным облакам.
- Установка модуля
$ npm i inquirer
Наиболее распространенные сценарии: ввод текста, опция, проверка, радио. Примеры следующие:
- пример src/index.js
......
import inquirer from 'inquirer';
export function cli(args) {
......
program
.command('ask')
.description('Ask some questions')
.action(async function(option) {
const answers = await inquirer.prompt([
{
type: 'input',
name: 'name',
message: 'What is your name?'
},
{
type: 'confirm',
name: 'isAdult',
message: 'Are you over 18 years old?'
},
{
type: 'checkbox',
name: 'favoriteFrameworks',
choices: ['Vue', 'React', 'Angular'],
message: 'What are you favorite frameworks?'
},
{
type: 'list',
name: 'favoriteLanguage',
choices: ['Chinese', 'English', 'Japanese'],
message: 'What is you favorite language?'
}
]);
console.log('your answers:', answers);
});
program.parse(args);
}
Код простой, переходим непосредственно к рендерам:
> Уменьшите беспокойство: ждите напоминаний
Опыт взаимодействия человека с компьютером очень важен.Если работа не может быть завершена немедленно, необходимо своевременно сообщать пользователю о текущем ходе работы, что может уменьшить беспокойство пользователя в ожидании.
ora
а такжеlistr
Бок о бок, шагая аккуратными шагами, они приблизились.
Первый, кто играет,ora
- Установка модуля
$ npm i ora
- пример src/index.js
......
import ora from 'ora';
export function cli(args) {
......
program
.command('wait')
.description('Wait 5 secords')
.action(async function(option) {
const spinner = ora('Waiting 5 seconds').start();
let count = 5;
await new Promise(resolve => {
let interval = setInterval(() => {
if (count <= 0) {
clearInterval(interval);
spinner.stop();
resolve();
} else {
count--;
spinner.text = `Waiting ${count} seconds`;
}
}, 1000);
});
});
program.parse(args);
}
вот изображение:
listr
Потом пришел.
- Установка модуля
$ npm i listr
- пример src/index.js
......
import Listr from 'listr';
export function cli(args) {
......
program
.command('steps')
.description('some steps')
.action(async function(option) {
const tasks = new Listr([
{
title: 'Run step 1',
task: () =>
new Promise(resolve => {
setTimeout(() => resolve('1 Done'), 1000);
})
},
{
title: 'Run step 2',
task: () =>
new Promise((resolve) => {
setTimeout(() => resolve('2 Done'), 1000);
})
},
{
title: 'Run step 3',
task: () =>
new Promise((resolve, reject) => {
setTimeout(() => reject(new Error('Oh, my god')), 1000);
})
}
]);
await tasks.run().catch(err => {
console.error(err);
});
});
program.parse(args);
}
По-прежнему нечего сказать, по-прежнему прямо на картинке:
> Добавь немного красок: жизнь больше не будет монотонной
chalk
: Я литературный юноша, я живу искусством, этим я не должен заниматься.
- Установка модуля
$ npm i chalk
- пример src/index.js
.....
import chalk from 'chalk';
export function cli(args) {
console.log(chalk.yellow('I like cooking'));
.....
}
Цветной интерфейс командной строки заставляет вас чувствовать себя лучше:
> Оформление фасада: добавить бордюр
boxen
: Это моя специальность, следите за мной!
- Установка модуля
$ npm i boxen
- пример src/index.js
......
import boxen from 'boxen';
export function cli(args) {
console.log(boxen(chalk.yellow('I like cooking'), { padding: 1 }));
......
}
Ну, это выглядит более профессионально:
> Объявление результатов: готово к публикации
если тыscope
публикуется таким образом, как@daniel-dx/cook-cli
. затем вpackage.json
Добавление следующей конфигурации на ваш веб-сайт позволит вам беспрепятственно публиковать (конечно, если вы являетесь платным участником npm, эту конфигурацию можно сохранить)
{
"publishConfig": {
"access": "public"
},
}
У двери запускаем:
$ npm publish
Хорошо, ваш CLI был опубликован для всего мира, и теперь вы можете перейти кwww.npmjs.com/CLI для запроса вашего опубликованного под a.
> Теплое напоминание: пришло время обновиться
update-notifier: Наконец-то пришло мое время, я подожду, пока цветы не исчезнут. Х﹏Х
- Установка модуля
$ npm i update-notifier
- пример src/index.js
......
import updateNotifier from 'update-notifier';
import pkg from '../package.json';
export function cli(args) {
checkVersion();
......
}
function checkVersion() {
const notifier = updateNotifier({ pkg, updateCheckInterval: 0 });
if (notifier.update) {
notifier.notify();
}
}
Для локальной отладки мы понижаем локальный CLI на одну версию и ставимpackage.json
изversion
превратиться в0.0.9
, затем запуститеcook
Проверьте эффект:
o( ̄︶ ̄) о отлично!
Выше подробно описаны некоторые из необходимых или общих шагов для разработки CLI.
Конечно, если вы просто хотите быстро разработать CLI, как часто говорят некоторые руководители: не рассказывайте мне процесс, я просто хочу результат. Это вполне можно использовать какoclif
Эти фреймворки предназначены для разработки интерфейсов командной строки прямо из коробки.
Как программисты, нам все еще нужно посвятить некоторое время и энергию, чтобы понять все тонкости решения, прошлое и настоящее, чтобы мы могли быть более практичными и идти дальше.
Ну вот и все на сегодня, до свидания друзья!
Чуть не забыл, прикрепите исходный код примера:GitHub.com/Daniel-stuff/from…
┏(^0^)┛ До свидания!