-
Notifications
You must be signed in to change notification settings - Fork 8
Lua domain model ru
Lua в MC — это один runtime расширений, а не набор отдельных «Lua-плагинов редактора», «Lua-плагинов панелей» и специальных сценариев в ядре. Runtime загружает пакеты, изолирует их от внутренних структур MC и предоставляет несколько независимых предметных API.
Главная архитектурная граница проходит между политикой расширения и механизмами MC:
- Lua-пакет определяет поведение, преобразования и содержимое;
- runtime adapter проверяет Lua-значения и переводит их в стабильный C ABI;
- host services выполняют разрешённые операции MC;
- ядро владеет виджетами, памятью, жизненным циклом, отрисовкой и внутренними структурами.
Lua никогда не получает WPanel, WEdit, WView, dir_list, указатели на
буферы, widget ID, VFS-объекты или функции ядра.
Lua package
↓ domain API: mc.editor, mc.panel_provider, mc.ui, ...
Lua runtime adapter
↓ typed, append-only runtime ABI
MC host services
↓ native public mechanisms
Editor / panels / viewer / diff viewer / dialogs / processes
Самостоятельный пользовательский пакет с декларативным описанием и callback-функциями. Пакет хранит собственную бизнес-логику и состояние, но не владеет объектами интерфейса MC.
Единственный нативный Lua runtime (mc-lua). Он:
- обнаруживает и загружает пакеты;
- создаёт изолированные Lua-состояния;
- проверяет аргументы и результаты callbacks;
- преобразует Lua-таблицы в типизированные ABI snapshots;
- проверяет capability и активный контекст;
- изолирует ошибки пакета;
- не реализует прикладную логику пакетов.
Типизированная граница между runtime и MC. ABI развивается только добавлением новых полей и функций в конец структур. В нём передаются значения с явными размерами, immutable snapshots и opaque handles с generation.
ABI не должен содержать сущности конкретного пакета. В нём допустимы только общие операции: открыть diff, получить текст, предоставить элементы панели или запустить процесс.
Реализует механизмы, которые уже принадлежат MC: editor transactions, panel navigation, native viewer и mcdiff, диалоги, keymap, процессы, refresh и события. Host проверяет handles, владеет native memory и гарантирует cleanup.
Единица загрузки и изоляции. Имеет стабильный ID, отображаемое имя, workspace, точку входа, состояние enabled/disabled и набор требуемых capabilities.
Один пакет может зарегистрировать несколько действий или providers, но Lua runtime остаётся одним загруженным runtime-плагином MC.
Краткоживущий контекст активного вызова MC. Он определяет, какие объекты и мутации доступны сейчас. Сохранённый Lua-объект не даёт права выполнять операции после завершения callback.
Ссылка вида {kind, id, generation} на host-owned объект. Handle не раскрывает
адрес объекта. После закрытия объекта старый handle возвращает closed и не
может ожить при повторном использовании внутреннего адреса.
Snapshot — неизменяемое описание состояния на конкретной revision. Идентификатор
revision является токеном равенства, а не сохраняемой версией документа.
Операция с устаревшими координатами должна завершаться stale_revision, не
изменяя данные.
Именованная операция пакета. Может иметь клавишу и место в меню, но её ID не зависит от представления. Keymap и меню доставляют один и тот же action, а runtime не исполняет entry-файл повторно.
Описание источника данных, а не открытый FILE *. Источник может быть bytes,
локальным файлом, процессом или pipeline. Host материализует источник,
передаёт его штатному consumer и освобождает ресурсы.
На границе ABI используются стабильные машинные коды (not_supported,
closed, stale_revision, provider_busy) и отдельный диагностический текст.
Lua-ошибка callback изолируется runtime и не должна завершать MC.
Ниже перечислены сущности модели и их связи. Это не перечень функций ABI: методы, поля C-структур и ограничения сериализации описывают контракты, а доменная модель фиксирует смысл объектов.
Загруженный движок языка. Runtime регистрируется в MC один раз, объявляет версию, capabilities и минимальные требования к host. Он обнаруживает packages, создаёт их окружения и является единственным посредником между ними и host.
Область применения package: файловый менеджер, редактор, viewer, terminal или diff viewer. Workspace определяет доступный контекст и каталог обнаружения, но не создаёт отдельный Lua runtime.
Декларативная идентичность package: ID, имя, workspace, версия API, entry point и класс пакета. Descriptor существует отдельно от загруженного Lua state и проверяется до исполнения entry point.
Источник package — системный или пользовательский каталог. Одинаковый ID в более приоритетном origin замещает менее приоритетный. Origin входит в модель обнаружения и диагностики, но не меняет доменный API package.
Именованное право на класс host-операций. Наличие функции в ABI ещё не означает, что она доступна в текущем run mode или callback phase. Effective capability является пересечением возможностей сборки, host, runtime, workspace и активного контекста.
Регистрация package на event с типом и приоритетом. Subscription принадлежит package, снимается явно либо автоматически при unload. Она не является синхронным запросом и не возвращает решение вызывающему домену.
Неизменяемый снимок события. Содержит общую метаинформацию и typed payload конкретного домена. Snapshot не предоставляет доступ к живому widget и не должен сохраняться как handle host-объекта.
Host-owned редактируемый документ. Его идентичность представлена editor handle, а состояние — document info snapshot. Документ содержит buffer, cursor, selection, revision и file state.
Position связывает byte offset с вычисленными line и column на одной revision. Range — полуоткрытый интервал двух offsets. Координаты не являются отдельными живыми объектами и теряют применимость при изменении revision.
Снимок режима выделения и одного или нескольких ranges. Selection может быть отсутствующим, линейным или колонным. Выделенный текст является производным значением buffer на той же revision.
Edit — декларативная замена range текстом. Transaction — проверенный набор edits, применяемый атомарно и образующий одну undo-запись. Host отвечает за порядок применения, проверку пересечений, revision и redraw.
Panel — host-owned UI-представление списка. mc.panel предоставляет временную
ссылку на уже существующую active или passive panel. Эта ссылка не является
provider instance и не даёт владения panel widget.
Глобальная регистрация логического namespace. Provider содержит identity, prefix, capabilities, callbacks, actions и help metadata. Один provider может обслуживать несколько независимых instances.
Сохранённое описание точки входа provider. Connection имеет стабильный ID и display metadata. В callbacks редактирования передаётся immutable snapshot; создание, копирование, переименование и удаление являются отдельными транзакционными операциями provider.
Состояние одного открытия provider. Instance принадлежит паре provider/panel, хранит текущую logical location и закрывается вместе с panel либо package. Несколько instances не разделяют навигационное состояние неявно.
Revisioned snapshot текущей logical location. View объединяет presentation, columns, entries, focus, actions, footer и contextual help. Он заменяется целиком после reload или результата операции.
Элемент view с устойчивым в пределах instance ID, display name, kind, role,
metadata и значениями columns. Entry является snapshot, а не файлом и не
file_entry_t. Directory-like entry задаёт навигацию; file-like entry может
предоставлять content.
Column описывает семантическое поле entry и правила его показа. Presentation содержит только данные отображения; решение о ширине, обрезке, сортировке и отрисовке остаётся у host.
Снимок current entry и отмеченных entry IDs на одной view revision. Selection передаётся action как значение и не является изменяемой коллекцией panel.
Navigation request типизирует переход к entry, parent или location. Operation result декларативно сообщает host о refresh, новой location, focus, status или закрытии instance; callback не управляет panel widget напрямую.
Связь panel entry с consumer содержимого. Provider может передать custom view, source/stream либо local-copy representation. Содержимое отделено от entry metadata и имеет собственное владение и cleanup.
Глобальное описание семейства управляемых источников: identity, callbacks, help и правила подготовки. Definition не содержит открытый источник.
Состояние одного созданного controller. Session появляется после create,
передаётся viewer во владение при открытии и закрывается ровно один раз.
Opaque объект, связывающий session с host viewer. Controller управляет
prepare/options/commit/rollback/key lifecycle, но не предоставляет Lua доступ
к WView.
Подготовленный snapshot источника: source, display title, help и политика auto-scroll. Spec валидируется до замены текущего datasource; неудачная подготовка оставляет прежний источник активным.
Неизменяемая последовательность байтов с явной длиной. Embedded NUL допустим, если consumer поддерживает byte content. При необходимости host материализует bytes во временный ресурс.
Ссылка на локальный путь с явно определённым владением временным файлом. Путь является transport detail, а display title задаётся отдельно.
Процесс, описанный argv и рабочим каталогом. Command line не является display identity. Host владеет запуском, pipe, EOF, ожиданием процесса и отменой.
Упорядоченная композиция process sources. Pipeline является одним логическим источником и имеет общий lifecycle, ошибку и consumer.
Декларативное описание host-owned modal dialog: title, controls, buttons, default action и правила размещения. Lua не создаёт widgets и не назначает их координаты напрямую.
Типизированный элемент формы: label, input, checkbox, radio/select либо разделитель. Control имеет ID, display metadata, начальное значение и, где применимо, options. ID связывает specification с result.
Immutable результат завершённого dialog: выбранная action и значения controls. Cancel является нормальным результатом взаимодействия, а не Lua-ошибкой.
Именованный фрагмент persistent UI state, принадлежащий package и UI area. Повторная установка пары owner/area/ID заменяет значение; unload очищает все indicators owner.
Process request задаёт команду и resource limits. Result содержит stdout, stderr, exit status, signal и признаки truncation. Ненулевой exit status — результат процесса, а невозможность запуска — ошибка host operation.
Ссылка на package-owned help source и node. Help может принадлежать provider, view, entry или controller; host выбирает наиболее конкретный доступный контекст и открывает штатную help system.
Работа с уже открытым документом:
- current context и lifecycle handle;
- document info, path, readonly, modified и revision;
- cursor и selection snapshots;
- чтение и замена ranges;
- атомарные transactions с одной undo-записью;
-
save().
Редактор не содержит UI-методов. Диалоги находятся в mc.ui, процессы — в
mc.process, события — в mc.on.
Автоматизация уже существующей панели: active/passive panel, cwd, current, selected, refresh и chdir. Этот API не создаёт новую панель и не поставляет её содержимое.
Провайдер виртуального пространства панели:
- registration metadata и capabilities;
- список сохранённых connections и CRUD callbacks;
- независимый instance на каждое открытие;
- revisioned view с entries, columns и presentation metadata;
- typed navigation;
- actions над current/selection/view;
- content через view, stream или local-copy contract;
- context-dependent help.
Provider определяет логическое пространство. MC владеет панельным виджетом,
сортировкой, отметками, историей и обработкой стандартных команд. Lua adapter
подключается через тот же mc_panel_plugin_t, что и нативные providers; общему
filemanager не нужны исключения для Lua.
Общие host-owned средства представления:
- status и message;
- declarative dialogs;
- persistent indicators;
- открытие native viewer;
- открытие native diff viewer.
mc.ui.open_diff() принадлежит UI-домену, а не panel ABI: он открывает
host-owned интерфейс и доступен любому Lua-пакету.
Контроллер источника описывает данные, title, help и параметры обновления.
MC открывает штатный viewer и управляет его жизненным циклом. title является
человекочитаемым именем; command и временный путь остаются деталями источника.
Контролируемый запуск внешнего процесса с ограничением вывода и явным результатом: stdout, stderr, exit code, signal и признаки truncation. Process API не является частью editor или panel API.
Односторонние уведомления о lifecycle и действиях MC. События подходят для
open, save, key и подобных наблюдений, но не заменяют синхронные запросы
provider, которым требуется немедленный результат.
- MC владеет native widgets и host objects.
- Runtime владеет регистрациями, Lua states и преобразованными ABI-значениями.
- Package владеет только Lua-состоянием своих instances и sessions.
- Callback result действует до документированной точки освобождения.
- Временные файлы и процессы освобождает слой, который их материализовал.
- Закрытие panel instance, editor или viewer инвалидирует связанные handles.
- Несколько панелей одного provider получают независимые instances.
Клавиша сначала преобразуется общим keymap в команду MC. Панельный plugin
получает стандартную команду через handle_key(). Lua adapter переводит её в
доменную операцию provider.
Shift-F4 → CK_EditNew → runtime adapter → new_connection()
F4 → CK_Edit → runtime adapter → edit_connection(snapshot)
Shift-F6 → CK_MoveSingle → runtime adapter → rename_connection(snapshot)
Shift-F3 → CK_ViewRaw → provider view(mode="plain")
Общий filemanager не должен узнавать, что provider реализован на Lua.
Если расширению не хватает возможности, сначала нужно определить, отсутствует ли общий ABI-механизм. Исправление должно находиться в runtime adapter или соответствующем общем домене. Изменение ядра оправдано только тогда, когда оно реализует универсальный host-механизм, одинаково пригодный для разных расширений.
Новая возможность относится:
- к editor ABI, если оперирует документом, selection или transaction;
- к panel provider ABI, если описывает namespace, entries или navigation;
- к viewer-source ABI, если описывает источник и его lifecycle;
- к
mc.ui, если открывает или обновляет host-owned интерфейс; - к
mc.process, если запускает внешний процесс; - к runtime core, если касается загрузки, изоляции и ABI marshaling;
- к пакету, если содержит его прикладную политику.
Это разделение позволяет развивать Lua как универсальную платформу расширений, не превращая ядро MC в набор специальных случаев для отдельных скриптов.