Это личный инструмент для локальной работы в терминале.
Он создается не как универсальное приложение для других пользователей, а как среда, которая должна соответствовать моим личным привычкам работы. Главный критерий качества один: удобно ли это лично мне.
Из этого следуют два правила:
- проект не обязан сохранять традиционное поведение терминала, если оно мне неудобно;
- проект не обязан подстраиваться под чужие ожидания, если они противоречат моему способу работы.
- Работа только локальная.
- Внешний терминал уже существует и отвечает за отображение текста.
- Моя программа управляет раскладкой, вкладками, фокусом, псевдотерминалами и сохранением состояния.
- При закрытии внешнего терминала все дочерние процессы могут завершаться. Сохранение нужно для структуры работы, а не для бессмертных сеансов.
Переопределение сочетаний клавиш является сознательной частью замысла.
Ctrl+Cкопирует выделенный текст в системный буфер обмена.Ctrl+Vвставляет текст из системного буфера обмена.Alt+Xотправляет сигнал прерывания в активный процесс.
Это не считается ошибкой совместимости внутри данного проекта. Наоборот, это одно из ключевых правил интерфейса.
Интерфейс состоит из вкладок.
- Существует набор вкладок.
- У каждой вкладки своя независимая раскладка окон.
- В каждой вкладке может быть несколько областей, связанных с отдельными псевдотерминалами.
- Внутри вкладки пользователь может делить пространство по вертикали и по горизонтали.
- Между областями можно перемещаться с клавиатуры.
Предпочтительная внутренняя модель раскладки: дерево разбиений.
То есть каждая вкладка хранит либо:
- лист, содержащий одно окно с псевдотерминалом;
- либо узел, который делит пространство по вертикали или по горизонтали и содержит дочерние части.
Такая схема проще для сохранения, восстановления и изменения раскладки.
Сохраняемое состояние состоит из:
- набора вкладок;
- порядка вкладок;
- признака активной вкладки;
- раскладки внутри каждой вкладки;
- признака активного окна внутри вкладки;
- рабочего каталога для каждого окна.
Пока не требуется сохранять:
- живые процессы после закрытия программы;
- историю прокрутки;
- содержимое экрана;
- историю команд как обязательную часть системы.
Если позже окажется полезным, история команд может быть добавлена отдельно, но она не должна усложнять первую рабочую реализацию.
Задача: для каждого окна нужно восстановить тот каталог, в котором пользователь работал в момент последнего сохранения.
Предпочтительный порядок решений такой:
- Сначала пытаться получить текущий рабочий каталог процесса оболочки через операционную систему.
- Если это невозможно или ненадежно на части систем, использовать управляемое обновление каталога изнутри оболочки.
На практике это означает следующее.
Основной вариант:
- у каждого окна есть основной процесс оболочки;
- программа знает его идентификатор процесса;
- текущий рабочий каталог читается у этого процесса средствами операционной системы.
Для Linux это обычно реализуемо через путь вида /proc/<pid>/cwd.
Запасной вариант:
- при запуске оболочки можно передавать в нее небольшой код инициализации;
- этот код сообщает приложению о смене текущего каталога после каждой команды
cdили после каждого изменения приглашения оболочки.
Такой способ сложнее и сильнее зависит от конкретной оболочки, поэтому его лучше рассматривать как дополнительный, а не основной.
Вывод: сохранение cwd технически реализуемо. Самый простой путь для начала — читать каталог процесса оболочки через операционную систему там, где это доступно.
Состояние должно записываться в локальный файл при существенных изменениях, например:
- создание окна;
- удаление окна;
- изменение раскладки;
- переключение активной вкладки;
- создание или закрытие вкладки;
- заметная смена рабочего каталога окна.
Сохранение состояния должно быть доступно автоматически, без отдельной настройки со стороны пользователя.
Если программа называется mtrm, то при первом запуске она сама создает каталог ~/.mtrm и использует его для своих служебных файлов.
В этом каталоге как минимум хранится файл состояния текущей рабочей среды.
Формат хранения: YAML или JSON.
Предпочтение можно отдать YAML, если важна читаемость руками, и JSON, если важнее простота сериализации без лишних решений. Для личного инструмента разумно выбрать тот формат, который удобнее быстро читать и править вручную.
При запуске программа:
- читает файл состояния;
- создает нужное количество вкладок;
- восстанавливает раскладку внутри каждой вкладки;
- запускает новые процессы оболочки для каждого окна;
- открывает каждую оболочку в сохраненном рабочем каталоге;
- возвращает активную вкладку и активное окно.
Предлагаемый набор библиотек:
crosstermдля режима прямого чтения клавиатуры и управления терминалом;ratatuiдля отрисовки интерфейса;portable-ptyдля создания псевдотерминалов;arboardдля системного буфера обмена;serdeиtomlлибоserdeиserde_jsonдля сохранения состояния.
Основные подсистемы программы:
- подсистема ввода;
- подсистема раскладки;
- подсистема вкладок;
- подсистема псевдотерминалов и дочерних процессов;
- подсистема сохранения и восстановления состояния;
- подсистема буфера обмена.
Любое нажатие клавиши проходит через фильтр.
- Если сочетание относится к управлению программой, оно обрабатывается самой программой.
- Если сочетание не относится к управлению программой, оно передается в активный псевдотерминал как ввод пользователя.
Это правило должно быть простым и предсказуемым. Лучше иметь небольшой, жестко определенный набор управляющих сочетаний, чем сложную и трудно объяснимую систему.
- Это не клиент-серверный мультиплексор.
- Это не средство для переподключения к удаленным сеансам.
- Это не полноценный графический эмулятор терминала.
- Это не проект, обязанный сохранять исторические соглашения Unix, если они мешают моему удобству.
Первая рабочая версия должна уметь следующее:
- создавать несколько вкладок;
- в каждой вкладке хранить собственную раскладку окон;
- делить окно по вертикали и по горизонтали;
- переключать фокус между окнами;
- запускать оболочку в каждом окне;
- копировать и вставлять через системный буфер обмена;
- сохранять и восстанавливать вкладки, раскладки и рабочие каталоги.
Этого достаточно, чтобы программа уже была полезна по прямому назначению.