Cline и создание интерактивного приложения командной строки

от автора

Независимо от того насколько большая ваша любовь к командной строке, согласитесь, что простой и удобный интерфейс консоли, поддержка истории, авто дополнение, простые команды весьма впечатляют. Не вдаваясь в дисскусию о преимуществах и недостатках «темноты», хочу представить на суд Хабра-сообщества свою маленькую поделку из мира Node.js, главной задачей которой является улучшение жизни разработчика, который решился написать консольную утилиту.

Cline — обзор

Cline это маленькая библиотека базирована на нодовском readline модуле, таким образом у нас есть поддержка истории, авто дополнение, опрашивание пользователя и, с моей легкой руки, дополнения в виде маски на ввод пароля, возможности слушать ввод пользователя в виде отдельных команд описанных, как простые или регулярные выражения, вывода справки, упрощенной работы с историей, интерактивного режима.

Со всем этим создание приложения, которое после запуска буде ждать ввода команд от пользователя упрощается в разы.

Пример

Для тех, кому достаточно кода для понимания возможностей библиотеки, вот пример:

Пример

var cli = require('cline')(); cli.command('start', 'starts program', function () {     cli.password('Password:', function (str) {         console.log(str);     }) }); cli.command('stop', function () {     cli.confirm('Sure?', function (ok) {         if (ok) {             console.log('done');         }     }) });  cli.command('{string}', '', {string: '[A-Za-z]+'}); cli.command('{number}', '', {number: '\\d+'});  cli.on('command', function (input, cmd) {     if ('start' !== cmd && 'stop' != cmd) {         cli.prompt('More details on ' + cmd + ':');     } });  cli.history(['start', 'stop']); cli.interact('>');  cli.on('history', function (item) {     console.log('New history item ' + item); });  cli.on('close', function () {     console.log('History:' + cli.history());     process.exit(); }); 

Использование

Cline использует в своей работе Interface или что-то на него похожее, если у вас есть своя реализация Interface вы можете передать ее как параметр (поддержка тестирования):

var cli = require('cline')(myInterface);

Центральной возможностью cline является добавление команд.

cli.command(expression, description, parameters, callback);

expression – это выражение, которое мы ждем от пользователя, может вмещать динамические параметры, например, kill {id}, тут id – имя динамического параметра, о нем я напомню позже.

description – дополнительное объяснение для команды, используется для генерации справки.

parameters – объект, содержащий имена динамических параметров упомянутых в выражениях, как ключи, и регулярные выражения, как значения. Например, {id: ‘\\d+’} – id будет значить любое число.

callback – функция, которая будет вызвана, когда пользователь введет строку соответствующую expression. Вызывается она с двумя аргументами: строка от пользователя и объект со значениями динамических параметров.

cli.command('kill {id}', 'kill task by id', {id: '\\d{1,3}'}, function (input, args) {     console.log(input) // kill 12     console.log(args.id) // 12 }); 

Все параметры cli.command, кроме expression, необязательны, при чем можно пропускать как угодно.

cli.command(expression, description, callback); cli.command(expression, parameters, callback); cli.command(expression, description); cli.command(expression, parameters); 

Все эти варианты абсолютно валидны.

Взаимодействие с пользователем

Ожидать от пользователя можно 3 вещи:

1.Ввод

cli.prompt('Your turn:');

2.Подтвержение

cli.confirm('Sure?', function (ok) {});

3.Пароль

cli.password('Password:', ‘*’, function (pass) {});

А также можно просто перейти в интерактивный режим

cli.interact('>');

В таком режиме, библиотека ожидает ввода от пользователя и пытается каждую строку проинтерпретировать как команду, ища совпадения в списке описанных команд и после исполнения функции-слушателя на команде, опять ожидает ввода. Повторный вызов интерактивного режима просто изменит строку приглашения.

Системные команды, история и события

Без каких-либо дополнительных манипуляций при использовании cline, сразу доступны 3 команды:
clear или \c – очищает экран

help или \? – выводит справку

exit или \q – выход

С историей все просто, никаких файлов или потоков, просто заполняем историю так:

cli.history(['start', 'stop']);

порядок элементов соответствует давности, первый элемент в списке будет самым старым.
Ну а прочитать историю можно так:

cli.history();

получим список. Еще можно подписаться на событие добавления элемента в историю. Ну, а дальше вам решать, как этот список сохранять.

Так как cline наследует EventEmitter, тут широко используется событийная модель, вы можете подписываться на такие события:
close – пользователь вызвал команду выхода или остановил процесс использовав Ctrl + C

history – при добавлении нового элемента в историю, новый элемент передается слушателю как параметр.

command – ввод пользователя совпал из одной из команд (кроме системных), строка от пользователя и выражение команды передаются как параметр слушателю.

На последок

Если вы не хотите тихо молчать, когда пользователь вводит что-то, кроме команд которые вы описали, делаем так:

cli.command('*', function (input) {           console.log(input + ' is not correct');    cli.usage();      });

Большое спасибо за внимание, надеюсь вам пригодится cline или может быть даже вдохновит на написание своей консольной утилиты или хотя бы на форк в гитхабе.

P.S. Отдельное спасибо НЛО за инвайт.

ссылка на оригинал статьи http://habrahabr.ru/post/196380/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *