Terminode или Новичок пишет «терминал» (часть 2)

от автора

В прошлой своей статье я рассказывал о том, как начинал создавать свой якобы «терминал». Её заметило две с лишним тысячи человек, что для меня уже было каким‑то неплохим числом. Некоторые писали мне различные советы, кто‑то давал критику по статье. И вот, спустя небольшое время работы я снова пишу статью о своем «терминале» под именем Terminode. Вот она вторая часть «новичка пишущего терминал».

Что же это такое?

Terminode — CLI App, позволяющее немного облечить работу с терминалом.

Судя по прошлой статье я понял, что я пишу CLI App. На тот момент мой проект не выделялся ничем не мог похвастаться каким‑то прям функциями. Сейчас я добавил некоторые интересные фичи, используя новую библиотеку — prompt_toolkit

Prompt Toolkit — радость любого питониста

prompt_toolkit — библиотека, позволяющая создавать мощные приложения в терминале.

Pyvim - Vim в терминале на Python

Pyvim — Vim в терминале на Python

Данная библиотека позволяет создавать из простых CLI Apps, мощные текстовые редакторы, эмуляторы терминала.В ней есть автодополнение кода, подсветка синтаксиса, история введенных команд, Vim‑режим и многое другое. Эта библиотека позволила мне внести новые фичи в своей проект без особых усилий, а также немного «выделить» его среди других.

Автодополнение в Terminode

В моем приложении есть набор некоторых команд. Иногда вводить их надоедает, хочется вводить всё по нажатию одной кнопки. Поэтому сначала я улучшил свою переменную промптов

from prompt_toolkit import PromptSession  class Terminode:     def __init__(self):         self.username = config.username         self.session = PromptSession()      def run(self):         while True:             try:                 now = datetime.now()                 time_format = '%H:%M:%S'                 cur_dir = os.getcwd()                  cmd_prompt = f"{now:{time_format}} | {self.username} | {cur_dir} | "                 user_input = self.session.prompt(cmd_prompt).strip()

PromptSession() требуется для создания сессии ввода промптов. Эта сессия может сохранять введенные команды в файл истории. Также здесь я переместил cmd_prompt внутрь цикла, чтобы убрать функцию обновления промпта (это помогло немного ускорить приложение)

Далее я добавил к сессии промптов уже добавление каждой введенной команды в файл истории

from sys_controller import get_script_root from prompt_toolkit.history import FileHistory  self.session = PromptSession(history=FileHistory(                             f"{get_script_root()}/history.terminode"))

Файл можно назвать как угодно, главное, чтобы он мог быть читаемым для библиотеки. Здесь также можно наблюдать секретную функцию get_script_root(). В прошлый раз я допустил огромную ошибку, не посмотрев куда сохраняются логи моего приложения. Файлы Terminode сохранялись в той директории, которая была активна на этот момент в приложении. Из-за этого не работали многие функции приложения. Мною было принято решение добавить две функции, которые ищут путь до корневой папки Terminode и файлов в ней.

def get_script_root():     if getattr(sys, 'frozen', False):         return Path(sys.executable).parent     else:         return Path(__file__).parent.resolve()  def find_file_in_root(filename):     root_dir = get_script_root()     file_path = root_dir / filename          if file_path.exists():         return file_path     else:         raise FileNotFoundError(f"File {filename} not found in {root_dir}")

get_script_root() отдает корневую папку приложения. find_file_in_root() принимает название файла и отдает абсолютный путь до файла в корневой папке приложения. Эти две функции помогли мне заставить файлы создаваться только в корневой папке самого Terminode.

Автодополнение и подсказки из истории

После всех наработок пришло время добавлять автодополнение и подсказки.

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

from prompt_toolkit.completion import WordCompleter from prompt_toolkit.auto_suggest import AutoSuggestFromHistory  now = datetime.now() time_format = '%H:%M:%S' cur_dir = os.getcwd()  cmd_prompt = f"{now:{time_format}} | {self.username} | {cur_dir} | " cmd_completer = WordCompleter(self.commands) user_input = self.session.prompt(             cmd_prompt, completer=cmd_completer,             mouse_support=True, auto_suggest=AutoSuggestFromHistory()).strip()

Здесь начнём по порядку разбирать, за что отвечают различные настройки

  1. cmd_completer— Автодополнение (ну почти). Когда приложение видит что‑то похожее на команду, которая есть в списке кастомных команд, то она предлагает быстро дописать эту/эти команды.

  2. completer — Использует список слов, которые нужно сверять с промптом.

  3. mouse_support — Позволяет скроллить список предлагаемых команд в терминале с помощью колесика мыши. Честно, багованная фича.

  4. auto_suggest — Автодополнение из истории введенных Вами команд. Помогает быстрее вспоминать Ваши бывшие промпты!

Заключение этой работы

В заключении второй части (она вышла конечно короче) могу сказать, что моё приложение становится всё более удобным для работы с терминалом. На текущий момент уже можнонеплохо скоротать время, используя Terminode. Также я напоминаю, что есть система модулей — моды для Terminode, которые может создать кто‑угодно!

Я надеюсь вам было интересно читать мою статью. После некоторых следующих наработок я напишу третью часть DevBlog‑а о Terminode. За прогрессом работы можно следить в репозитории проекта. Также можно всегда сделать форк или пулл реквест и помочь проекту.

Всем спасибо за прочтение моей статьи!

GitHub Repo | TG-Channel


ссылка на оригинал статьи https://habr.com/ru/articles/913014/