-
Notifications
You must be signed in to change notification settings - Fork 8
Lua domain model
Ilia Maslakov edited this page Aug 22, 2026
·
3 revisions
В основе архитектуры лежит жесткое разделение ответственности между политикой (Lua) и механизмом (MC Core).
- Единый Runtime: Lua в MC — это одна подсистема, а не набор отдельных плагинов. Она загружает пакеты, изолирует их от внутренних структур MC и предоставляет несколько независимых предметных API.
-
Архитектурная граница:
- Lua-пакет: Определяет поведение, преобразования и содержимое.
- Runtime adapter: Проверяет Lua-значения, переводит их в стабильный C ABI.
- Host services: Выполняют разрешённые операции MC.
- MC Core: Владеет виджетами, памятью, жизненным циклом, отрисовкой.
-
Правило нулевого доступа: Lua никогда не получает прямых указателей на внутренние структуры MC (
WPanel,WEdit, буферы, widget ID, VFS-объекты и т.д.). Взаимодействие идет только через Opaque handles и immutable snapshots.
graph TD
%% Nodes
P[1. Lua Package]
RA[2. Lua Runtime Adapter / mc-lua]
HS[3. MC Host Services]
MC_W[Core: Editor, Panels, Viewer]
MC_M[Core: VFS, Memory, Events]
%% Edges
P -->|Domain API: mc.editor...| RA
RA -->|Validated, Typed ABI| HS
HS -->|Native public operations| MC_W
HS -->|Native public operations| MC_M
Эти сущности пронизывают все домены API. Они обеспечивают стабильность и безопасность.
-
Runtime: Загруженный движок (
mc-lua). Регистрируется один раз, создает изолированные Lua-среды для пакетов. - Capability (Право): Именованное разрешение на класс операций. Эффективное право есть пересечение возможностей сборки, хоста, рантайма, воркспейса и контекста.
- Context: Краткоживущий контекст активного вызова MC. Определяет доступные объекты и мутации здесь и сейчас. Хранить контекст для использования вне callback-функции нельзя.
-
Opaque handle: Защищенная ссылка (
{kind, id, generation}) на объект, принадлежащий хосту. Не раскрывает адрес памяти. При закрытии объекта handle становитсяstaleи никогда не "оживает" повторно. -
Snapshot & Revision: Неизменяемое описание состояния объекта на конкретной временной отметке (revision). Операции с устаревшими координатами завершаются ошибкой
stale_revision, не меняя данные. -
Error Model: На границе ABI используются стабильные машинные коды (
not_supported,closed,stale_revision,provider_busy) и диагностический текст. Lua-ошибки в callback изолируются и не роняют MC. - Source (Источник данных): Абстрактное описание откуда взять данные (bytes, локальный файл, процесс, pipeline). Хост сам материализует источник и передает его consumer'у.
API разделены по предметным областям (workspaces). Пакет может требовать capabilities для нескольких доменов.
Сущности, описывающие жизненный цикл самого расширения.
- Package: Единица загрузки. Имеет ID, имя, точку входа и capabilities.
- Package Descriptor: Декларативное описание (метаданные) пакета. Проверяется до исполнения Lua-кода.
- Workspace: Область применения (file manager, editor, viewer, terminal). Определяет контекст.
- Package Origin & Precedence: Системный или пользовательский каталог. Пакет с одинаковым ID в более приоритетном origin замещает менее приоритетный.
- Indicator: Именованный фрагмент постоянного UI-состояния, принадлежащий пакету.
Работа с открытым текстовым документом. MC владеет документом, Lua получает его снимок.
- Editor Document: Хостовый документ. Идентифицируется через handle.
- Document Info Snapshot: Состояние документа (path, readonly, modified, revision).
- Position & Range: Координаты в буфере. Завязаны на revision.
- Selection: Снимок выделения (режим + один или несколько ranges).
-
Edit & Transaction:
- Edit: Декларативная замена текста в range.
- Transaction: Атомарный набор edits, создающий одну запись undo.
Разделение на управление существующими панелями и провайдеры виртуальных пространств.
- Panel & Panel Reference: Временная ссылка на уже существующую активную или пассивную панель MC. Не дает владения виджетом.
-
Panel Provider: Глобальная регистрация логического пространства (например,
git:,arc:,ftp:). Определяет capabilities, callbacks, действия. - Connection: Сохраненное описание точки входа (например, конкретный URL).
- Provider Instance: Состояние одного открытия провайдера в конкретной панели. Живет пока открыта панель.
- Panel View: Revisioned snapshot текущего состояния панели (entries, columns, focus). Заменяется целиком после refresh.
- Panel Entry: Элемент view (snapshot, не файл). Может быть directory-like (навигация) или file-like (контент).
- Column & Presentation: Семантическое поле entry и правила его отображения (хост решает, как рисовать).
- Panel Selection: Снимок current entry и отмеченных IDs. Передается в action как значение.
- Content Contract: Механизм связи panel entry с consumer'ом содержимого (custom view, source/stream).
Просмотр данных в штатном viewer'е MC.
- Viewer Source Definition: Глобальное описание семейства источников (имя, callbacks, хелп).
-
Viewer Session: Состояние контроллера от момента
createдо закрытия. - Viewer Controller: Opaque объект, связывающий сессию с host viewer'ом.
- Viewer Source Specification: Подготовленный immutable snapshot источника для открытия в viewer.
Общие host-owned элементы интерфейса.
- Dialog Specification: Декларативное описание модального диалога. Lua не управляет виджетами напрямую.
- Dialog Control: Типизированный элемент формы (label, input, checkbox и т.д.).
- Dialog Result: Immutable результат завершенного диалога.
- Help Reference: Ссылка на package-owned help system.
Контролируемый запуск системных команд.
- Process Request: Команда (argv), рабочая директория, лимиты.
- Process Result: Результат завершения процесса (stdout, stderr, exit status, признаки truncation).
- Pipeline Source: Композиция process sources.
Механизм подписки на действия MC.
- Subscription: Регистрация пакета на событие.
- Event Snapshot: Неизменяемый снимок данных события. Не дает доступа к живому виджету.
Важно показать, как доменная модель работает в динамике.
- Нажатие клавиши в MC.
- Глобальный keymap преобразует её в MC Command (например,
CK_EditNew). - Плагин панели получает команду через
handle_key(). -
Runtime Adapter перехватывает вызов и переводит его в Domain Operation (вызывает Lua-callback
on_edit_newу провайдера). - Lua-пакет выполняет логику и возвращает результат (например,
NavigationRequestилиEditTransaction).
Пример:
Shift-F4 → CK_EditNew → runtime adapter → calls provider's Lua function `new_connection()`
F4 → CK_Edit → runtime adapter → calls `edit_connection(snapshot)`