Skip to content

Latest commit

 

History

History
602 lines (402 loc) · 29.6 KB

README.md

File metadata and controls

602 lines (402 loc) · 29.6 KB

Command Line Interface для OScript

Stars Release Открытый чат проекта https://gitter.im//oscript-cli/Lobby

Build Status Coverage Status

Короткое название библиотеки cli

Данная библиотека для языка OScript позволяет создавать консольные приложения с разбором и проверкой аргументов.

Документация и описание публичного API

Быстрый старт

Пример простого приложения

#Использовать cli

Перем Лог;

///////////////////////////////////////////////////////////////////////////////

Процедура ВыполнитьПриложение()

    Приложение = Новый КонсольноеПриложение(ПараметрыПриложения.ИмяПриложения(), "Помощник генерации приложения на основании шаблона cli");
    Приложение.Версия("v version", ПараметрыПриложения.Версия());

    Приложение.УстановитьОсновноеДействие(ЭтотОбъект)
    Приложение.Запустить(АргументыКоманднойСтроки);

КонецПроцедуры

Процедура ВыполнитьКоманду(Знач Команда) Экспорт

    Сообщить("Полезная работа");

КонецПроцедуры

///////////////////////////////////////////////////////


Попытка

    ВыполнитьПриложение();

Исключение

    Сообщить(ОписаниеОшибки());

КонецПопытки;

Пример приложения с несколькими командами

#Использовать cli

///////////////////////////////////////////////////////////////////////////////

Процедура ВыполнитьПриложение()

    Приложение = Новый КонсольноеПриложение("cli", "Помощник генерации приложения на основании шаблона cli", ЭтотОбъект);
    Приложение.Версия("v version","1.0.0");

    Приложение.ДобавитьКоманду("i init", "Инициализация структуры нового приложения", Новый КомандаInit);
    Приложение.ДобавитьКоманду("g generate", "Генерация элементов структуры приложения", Новый КомандаGenerate);

    Приложение.Запустить(АргументыКоманднойСтроки);

КонецПроцедуры

Процедура ВыполнитьКоманду(Знач КомандаПриложения) Экспорт
    КомандаПриложения.ВывестиСправку();
КонецПроцедуры

///////////////////////////////////////////////////////

Попытка

    ВыполнитьПриложение();

Исключение

    Сообщить(ОписаниеОшибки());

КонецПопытки;

Пример приложения с вложенными командами

#Использовать cli

///////////////////////////////////////////////////////////////////////////////

Процедура ВыполнитьПриложение()

    Приложение = Новый КонсольноеПриложение("cli", "Помощник генерации приложения на основании шаблона cli");
    Приложение.Версия("v version","1.0.0");

    Приложение.ДобавитьКоманду("i init", "Инициализация структуры нового приложения", Новый КомандаInit);
    Приложение.ДобавитьКоманду("g generate", "Генерация элементов структуры приложения", Новый КомандаGenerate);

    Приложение.Запустить(АргументыКоманднойСтроки);

КонецПроцедуры

///////////////////////////////////////////////////////

Попытка

    ВыполнитьПриложение();

Исключение

    Сообщить(ОписаниеОшибки());

КонецПопытки;

Класс КомандаGenerate Для добавления подкоманды в любую команду используются методы ДобавитьПодкоманду или ДобавитьКоманду

Процедура ОписаниеКоманды(Команда) Экспорт

    // Метод <ДобавитьПодкоманду>
    Команда.ДобавитьПодкоманду("c command", "Генерация дополнительной вложенной команды", Новый КомандаGenerateCommand);
    
    // Метод <ДобавитьКоманду>
    Команда.ДобавитьКоманду("o option", "Генерация опции для команды", Новый КомандаGeneratOption);

Процедура ВыполнитьКоманду(Знач Команда) Экспорт

КонецПроцедуры

Мотивация

Для PR в cmdline слишком большие изменения в API, т.е. обеспечить совместимость очень трудоемко. Сравнительная таблица возможностей:

cli cmdline
Встроенная команда help
Автоматическая генерация справки по приложению и командам
Встроенная команда version
Команды
Подкоманды
Совмещение булевых (флаговых) опций -xyz
Совмещение опции и значения -fValue
Взаимоисключающие опции: --start ❘ --stop
Необязательные опции : [-a -b] or [-a [-b]]
Проверка аргументов : FILE PATH
Необязательные аргументы : SRC [DST]
Повторение аргументов : SRC... DST
Зависимость опций и аргументов друг от друга : SRC [-f DST]
Формирование своей строки выполнения: [-d ❘ --rm] FILE [КОМАНДА [АРГУМЕНТЫ...]]

Установка

Для установки необходимо:

  • Скачать файл cli.ospx из раздела releases
  • Воспользоваться командой:
$ opm install -f <ПутьКФайлу>

Либо скачать библиотеку с помощью opm:

opm install cli

Базовые принципы

При создании приложения необходимо указать имя приложения и описание:

Приложение = Новый КонсольноеПриложение("cli", "Помощник генерации приложения на основании шаблона cli");

Каждый возможный вариант выполнения - это "Команда". Команды могут создаваться явно, кроме того, само Приложение содержит в себе корневую (Основную) команду.

Каждая команда реализуется в виде отдельного класса. Каждый такой класс обязан иметь экспортную процедуру

Процедура ВыполнитьКоманду(Знач Команда) Экспорт
КонецПроцедуры

Для установки основной функции выполнения приложения в приложении надо установить основное действие. В простейшем случае основным действием может выступать сам стартовый сценарий:

Передать данный класс через процедуру:

Приложение.УстановитьОсновноеДействие(ЭтотОбъект)

Встроенная команда "Версия"

Для добавления отображения версии через опции: -v, --version надо добавить строчку:

Приложение.Версия("v version", "1.2.3");

Это позволит запускать приложение с ключом v или --version:

my-app --version

Запуск парсера аргументов и приложения в целом

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

Приложение.Запустить(АргументыКоманднойСтроки);

Этот вызов является "точкой входа" в консольное приложение. В общем случае после него уже не идет никакого дополнительного кода. Парсер анализирует аргументы и запускает команды автоматически.

Параметры команд/приложения

Все параметры разделяются на два типа:

  • Опция
  • Аргумент

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

Опция

Опция может быть следующих простых типов:

  • Булево
  • Строка
  • Число
  • Дата

Также опция может принимать массивы данных типов, например:

  • МассивЧисел
  • МассивСтрок
  • МассивДат
  • МассивБулево
  • Перечисление

Для простых типов поддерживается определение типа значения по умолчанию. Пример:

Отладка = Команда.Опция("f force", ,"Описание опция")
    .ТБулево() // тип опции Булево
    ;
// Можно заменить на вызов

Отладка = Команда.Опция("f force", Ложь ,"Описание опция");

Пример булево опции:

Отладка = Команда.Опция("v debug", ложь ,"Описание опции")
    .Флаговый() // тип опции булево
    .ВОкружении("ИМЯ_ПЕРЕМЕННОЙ")
    .ПоУмолчанию(Ложь)
    .СкрытьВСправке(); // Любой тип

ВОкружении Возможна передача нескольких переменных окружения, разделенных через пробел

Пример перечисления опции:

ЦветКонсоли = Команда.Опция("c color", "green" ,"Описание опции")
    .ТПеречисление() // тип опции перечисление
    .Перечисление("green", Новый ЗеленыйЦвет(), "Консоль будет зеленого цвета")
    .Перечисление("red", Цвета.Красный, "Консоль будет красного цвета")
    .Перечисление("Случайный", СлучайныйЦвет(), "Консоль будет случайного цвета")
    ;

Перечисление ограничивает пользователя в выборе значения опции, при этом разработчик для каждой опции может задавать свой тип значения

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

Пример синтаксиса опций

Для типа булево:

  • -f : одно тире для коротких имен
  • -f=false : одно тире для коротких имен и значение булево (true/false)
  • --force : двойное тире для длинных имен
  • -it : группировка булевых опций, будет эквивалентно: -i -t

Для типа строка, число, дата, длительность:

  • -e=value : одно тире для коротких имен, через равно значение опции
  • -e value : одно тире для коротких имен, через пробел значение опции
  • -Ivalue : одно тире для коротких имен, и сразу значение опции
  • --extra=value : двойное тире для длинных имен, через равно значение опции
  • --extra value : двойное тире для длинных имен, через пробел значение опции

Для массивов опций (МассивСтрок, МассивЧисел, МассивДат):

повторение опции создаст массив данных указанного типа опций:

  • -e PATH:/bin -e PATH:/usr/bin : Массив, содержащий ["/bin", "/usr/bin"]
  • -ePATH:/bin -ePATH:/usr/bin : Массив, содержащий ["/bin", "/usr/bin"]
  • -e=PATH:/bin -e=PATH:/usr/bin : Массив, содержащий ["/bin", "/usr/bin"]
  • --env PATH:/bin --env PATH:/usr/bin : Массив, содержащий ["/bin", "/usr/bin"]
  • --env=PATH:/bin --env=PATH:/usr/bin : Массив, содержащий ["/bin", "/usr/bin"]

Аргументы

Аргументы могут быть следующих простых типов:

  • Булево
  • Строка
  • Число
  • Дата

Для простых типов поддерживается определение типа значения по умолчанию. Пример:

Отладка = Команда.Аргумент("PATH", "" ,"Описание аргумента")
    .ТСтрока() // тип опции Строка
    ;
// Можно заменить на вызов

Отладка = Команда.Аргумент("PATH", "" ,"Описание аргумента");

Также аргументы могут принимать массивы данных типов, например:

  • МассивЧисел
  • МассивСтрок
  • МассивДат
  • Перечисление (см. пример опций)

Пример Строки аргумента:

Отладка = Команда.Аргумент("PATH", "" ,"Описание аргумента")
    .ТСтрока() // тип опции Строка
    .ВОкружении("ИМЯ_ПЕРЕМЕННОЙ")
    .ПоУмолчанию(Ложь)
    .СкрытьВСправке(); // Любой тип

ВОкружении Возможна передача нескольких переменных окружения, разделенных через пробел

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

Операторы

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

Для примера, если команда "ХочуФайл" принимает в качестве аргумента имя файла, но начинающегося с -, тогда строка запуска данной программы будет выглядеть так:

ИмяФайла = Команда.Аргумент("FILE", "", "имя файла для создания")

Допустим, нужное нам имя файла равно -f, тогда если выполнить нашу команду:

ХочуФайл -f

то будет выдана ошибка, т.к. -f распознано как опция, а не аргумент. Для того, чтобы решить данную проблему, необходимо объявить окончание опций через оператор --

ХочуФайл -- -f

Тогда определение аргументов будет работать корректно.

Команды и подкоманды

cli поддерживает создание команд и подкоманд. Неограниченное количество вложенных подкоманд. А также установки синонимов для команд и подкоманд.

Приложение = Новый КонсольноеПриложение("testapp", "Выполняет полезную работу");
КомандаAve = Приложение.ДобавитьКоманду("a ave", "Команда ave", КлассРеализацииПодкоманды);
  • Первый аргумент, наименование команды, которое необходимо будет вводить для запуска
  • Второй аргумент, описание команды, которое будет выводиться в справке
  • Третий аргумент, КлассРеализацииКоманды

cli поддерживает указание псевдонимов команд. Для примера:

КомандаAve = Приложение.ДобавитьКоманду("start run r", "Команда start", КлассРеализацииПодкоманды);

Псевдонимы для команды будут start, run, иr - можно использовать любой из них.

cli поддерживает автоматическую инициализацию параметров команд. Переданный класс должен реализовывать процедуру:

Процедура ОписаниеКоманды(Команда) Экспорт
    Путь = Команда.Аргумент("PATH", "" ,"Описание аргумента")
        .ТСтрока() / тип опции Строка
        .ВОкружении("ИМЯ_ПЕРЕМЕННОЙ")
        .ПоУмолчанию(Ложь)
        .СкрытьВСправке(); // Любой тип

    Отладка = Команда.Опция("o opt", Ложь ,"Описание опции")
        .ТСтрока() / тип опции Строка
        .ВОкружении("ИМЯ_ПЕРЕМЕННОЙ")
        .ПоУмолчанию(Ложь)
        .СкрытьВСправке(); // Любой тип
КонецПроцедуры

Строка использования приложения (спек)

Синтаксис спек базируется на POSIX. Спек является грамматикой парсера аргументов и определяет порядок следования аргументов и опций в командной строке, а также вариативность параметров. Спек формируется либо вручную через указание в поле Спек, либо автоматически в момент вызова выполнения приложения / или команды.

Опции

Для определения опций можно использовать длинные и короткие имена опций:

Команда.Спек = "-f";

И/или:

Команда.Спек = "--force";

Пример добавления аргументов в команду:

Команд.Опция("f force", ...);

Аргументы

Правила наименования аргументов, имя должно содержать только символы в верхнем регистре:

Пример использования аргументов в определении строки использования приложения

Команда.Спек="SRC DST"

Пример добавления аргументов в команду:

Команда.Аргумент("SRC", ...);
Команда.Аргумент("DST", ...);

Сортировка строки использования

cli позволяет произвольно настраивать порядок использования опций и аргументов:

Команда.Спек = "-f -g NAME -h PATH";

В примере выше задана грамматика: в командой строке могут идти сначала опции -f и -g, затем аргумент NAME, затем опция -h, затем аргумент PATH.

Необязательность

Чтобы сделать аргументы или опции необязательными, их необходимо заключить в [...]:

Команда.Спек = "[-x]";

Выбор между

Для отражения выбора между несколькими опциями или аргументами используется символ |:

Команда.Спек = "--server | --agent";
Команда.Спек = "-H | -L | -P";
Команда.Спек = "-f | PATH";

Повторитель

Для повторения аргументов или опций необходимо использовать оператор ...:

Команда.Спек = "PATH...";
Команда.Спек = "-f...";

Логические группы

Возможна логическая группировка опций и аргументов. Данную группировку стоит использовать и комбинировать с такими символами как | и ...:

Команда.Спек = "(-e КОМАНДА)... | (-x|-y)";

Приведенный пример настраивает строку использования следующим образом:

  • Повторение опции -e и команды
  • Или
  • Выбор между -x и -y

Группировка опций

Все короткие опции (типа булево) можно группировать в любом порядке вместе:

Команда.Спек = "-abcd";

Все опции

Для определение любой опции приложения:

Команда.Спек = "[OPTIONS]";

Для примера, для команды с опциями a, b, c и d, указание [OPTIONS] или [ОПЦИИ] будет аналогично указанию:

Команда.Спек = "[-a | -b | -c | -d]...";

Аннотация к опциям в строке использования

Можно задавать в строке использования =<очень хороший текст> аннотации после указания опции в длинной или короткой форме, для того чтобы определить дополнительное описание или значение по умолчанию.

Для примера:

Команда.Спек = "[ -a=<абсолютный путь к файлу> | --timeout=<в секундах> ] ARG";

Данные аннотации игнорируются парсером, и не влияют на работу приложения

Операторы

Оператор -- устанавливает метку завершению любых опций. Все что следует за данным оператором считается аргументами.

Более, сложный пример:

Приложение.Спек = "work -lp [-- CMD [ARG...]]";

Грамматика строки использования

Используется упрощенная (EBNF grammar) грамматика при создании строки использования:

Описание символа Символ и использование Проверка
Короткая опция '-' [A-Za-z]
Длинная опция '--' [A-Za-z][A-Za-z0-9]*
Соединенные опции '-' [A-Za-z]+
Все опции '[OPTIONS]' или [ОПЦИИ]
Логическая группа '(' любые другие символы ')'
Необязательная '[' любые другие символы ']'
Повтор аргумента '...'
Конец повтора аргументов '--'

Можно комбинировать в указанные символы как хочется, чтобы добиться любых необходимых проверок опций и аргументов.

Строка использования по умолчанию

По умолчанию, если разработчиком не установлена иная, cli автоматически создает для приложения и каждой команды строки использования, используя следующую логику:

  • Начало с пустой строки
  • Если определена хоть одна опция, добавляется [OPTIONS] или [ОПЦИИ] к текущей строке использования
  • Для каждого добавленного аргумента, добавляет его представление согласно очереди, объявления аргументов.

Для примера, при добавлении в команду следующих опций и аргументов:

ИнициализацияГит = Команда.Опция("g git-init", Ложь, "инициализировать создание git репозитория").Флаговый();
ИнтерактивныйРежим = Команда.Опция("interactive", Ложь, "интерактивный режим ввода информации о приложении").Флаговый();
ИспользоватьПодкоманды = Команда.Опция("s support-subcommads", Ложь, "шаблон с поддержкой подкоманд").Флаговый();
ФайлКонфига = Команда.Опция("c config-file", "", "файл настроек генерации приложения");

НаименованиеПриложения = Команда.Аргумент("NAME", "", "наименование приложения");
ПутьКПапкеГенерации = Команда.Аргумент("PATH", "", "Путь к папке для генерации нового приложения");

Будет автоматически создана следующая строка использования данной команды:

[OPTIONS] NAME PATH

Доработка

Доработка проводится по git-flow. Жду ваших PR.

Лицензия

Смотри файл LICENSE.