May 01, 2024
Интерактивные консоли Java с JLine и ConsoleUI
Мэтью Тайсон, архитектор программного обеспечения, InfoWorld | Интерфейс командной строки (CLI) — это внутренний мир разработки программного обеспечения. Из оболочки у нас есть прямой доступ ко всем функциям операционной системы.
Мэтью Тайсон
Архитектор программного обеспечения, InfoWorld |
Интерфейс командной строки (CLI) — это внутренний мир разработки программного обеспечения. Из оболочки мы имеем прямой доступ ко всем возможностям операционной системы, а вместе с ней и возможность создавать и координировать все аспекты программного обеспечения. Многие инструменты и платформы включают командные строки. Мало того, командная строка — это основная магия работы с программными системами; это дом почти неограниченных возможностей.
В этой статье мы рассмотрим создание сложных приложений с интерактивным интерфейсом командной строки (CLI) и REPL (циклов чтения-оценки-печати или интерактивных оболочек) на Java. Мы настроим базовое демонстрационное приложение на Java и воспользуемся библиотеками JLine и ConsoleUI, чтобы добавить необходимые нам функции.
Наша демонстрация основана на теоретическом приложении, которое проверяет рабочий каталог программного проекта и собирает информацию о проектах в нем. Приложение также может создавать новые проекты в каталоге. Пример приложения запустит REPL, который принимает две команды: описать и создать, которые можно заполнить с помощью табуляции. Команда описания выведет список иерархии папок рабочего каталога с цветовой кодировкой (при необходимости с использованием разбивки по страницам), а команда create запускает интерактивное меню, которое позволяет пользователю выбрать тип проекта для создания — Java, JavaScript или Python. Если это приложение Java, мы разрешим множественный выбор дополнительных функций, которые пользователь может добавить (база данных или REST API), что позволит нам увидеть вложенное меню.
Мы просто будем использовать эти функции для изучения возможностей JLine, а не для их фактической реализации.
Для этого тура вам понадобятся установленные Java JDK и Maven. Мы начнем с создания нового приложения с архетипом Maven, как показано в листинге 1.
Maven будет использовать эти команды, чтобы составить для нас новый проект. Прежде чем идти дальше, давайте также добавим все необходимые нам зависимости, а также установим версию Java 11 (любая версия, начиная с Java 8, должна работать), как я сделал в листинге 2. Это относится к pom .xml в корне проекта (остальную часть pom.xml оставьте как есть).
Далее давайте изменим основной класс в src/main/java/com/infoworld/App.java, чтобы запустить цикл REPL. Измените App.java, используя код из листинга 3.
В листинге 3 создается очень простая программа, которая отслеживает строки пользовательского ввода и возвращает их обратно. К этому я добавил «дополнитель», который содержит две команды, которые мы поддерживаем, описываем и создаем. Это означает, что когда пользователь вводит текст в командной строке, он может использовать клавишу Tab для выполнения этих команд. Двойное нажатие табуляции откроет меню с доступными командами. JLine сделал это очень легко с помощью вызова метода .completer(new StringsCompleter("describe", "create")) в свободном стиле. Помимо Strings, в JLine есть несколько встроенных средств завершения, но вы также можете создать свои собственные.
По сути, REPL представляет собой бесконечный цикл while, который прерывается, когда пользователь выходит из программы.
Вы можете проверить это, запустив команду Maven exec:java, показанную в листинге 4.
Вы получите подсказку «морковка», эхо-ответ и команды завершения табуляции.
Теперь, когда у нас есть echo REPL, работающий с автозаполнением, давайте приступим к обработке команд. Мы сделаем это с помощью типичного Java, сравнивая введенную строку с командами и вызывая методы для каждой из них. На данный момент create ничего не делает, но мы реализуем логику вывода иерархии каталогов, как показано в листинге 5.
Теперь, когда вы запустите приложение и введете команду описания, вы увидите список рабочего каталога в формате отступа. Работа по построению этой строки происходит в getDirectoryHierarchy(). Этот метод использует обычную Java из пакета java.nio.file для обхода каталога и вывода каждого файла и каталога, делая отступ для каждого уровня каталога, на который мы спускаемся. Эта работа в основном выполняется с помощью path.relativize(p).getNameCount(), который говорит: из моего текущего пути (.) дайте мне относительный путь к текущему (например, ./src/main/java). getNameCount() просто подсчитывает количество имен в этом пути — в данном случае три. Для каждого имени добавляем пробел.