7.1 KiB
7.1 KiB
AGENTS.md
qode — настольный редактор кода на GPUI (gpui-kit) с расширением поведения
через Lua и клиентом LSP по stdio. Этот файл описывает архитектуру и принципы,
которые нужно сохранять при изменениях.
Модули
| Путь | Ответственность |
|---|---|
src/main.rs |
Точка входа, окно, аргументы командной строки |
src/constants.rs |
Константы окна, CLI и каталог сценариев |
src/editor.rs |
Доменная модель: документы, вкладки, языки |
src/api.rs |
AppApi / PanelApi / TreeApi — единственная поверхность управления |
src/script.rs |
Lua-движок, app, include, require |
src/keymap.rs |
KeyBinding, KeyMap, встроенные команды и Lua-обработчики |
src/app.rs |
GPUI-вид, отрисовка, события, автодополнение |
src/completion.rs |
Всплывающий список, CaretPopup, преобразования LSP-элементов |
src/panel.rs |
PanelState и блоки панелей |
src/tree.rs |
Абстрактное дерево для панелей |
src/icons.rs |
Каталог иконок Lucide |
src/lsp.rs |
Менеджер LSP-серверов, JSON-RPC, файловый вотчер |
DOCS.md, init.lua |
Пользовательская документация и пример конфигурации |
Главные принципы
1. AppApi — центр приложения
- Документы, вкладки, панели, дерево, окно, подсветка, LSP и привязки клавиш
меняются только через
AppApi(илиPanelApi/TreeApi). - Состояние живёт в общих
Rc<RefCell<_>>/Arc, чтобы UI,AppApiи Lua видели одни и те же объекты. Второй копии состояния быть не должно. - Команды окна складываются в очередь и применяются в начале кадра
(
apply_window_commands); UI и Lua не вызываютWindowнапрямую. - Если действие пользователя меняет состояние, оно выражается методом
AppApi, а не логикой внутри обработчика UI. Отрисовка состояние только читает. - Исключение — системные кнопки окна внутри
gpui-kit::TitleBar: их поведение принадлежит библиотеке.
2. Lua повторяет возможности API
- Публичные методы
impl AppApiс#[mlua::userdata_impl]доступны какapp:method(...). Добавляя возможность, сразу добавляйте и Lua-метод. - Имена —
snake_case; вкладки и индексы нумеруются с нуля; панели —app.left_panel,app.right_panel,app.bottom_panel. - Для методов, которые не должны попадать в Lua, используется
#[lua(skip)]. Для generic-методов добавляется тонкая не-generic Lua-обёртка. DOCS.mdи комментарии вinit.luaобновляются в том же изменении, что и публичный API. Документация описывает фактическое поведение, без «запланированных» методов.
3. Клавиатура — только через KeyMap
- Встроенные привязки (
Ctrl/Cmd+S,Ctrl/Cmd+Space, навигация по списку автодополнения) регистрируются вKeyMapи могут быть заменены или удалены из Lua черезapp:map_key/app:map_completion_key. KeyMapимеет два слоя: глобальный иcompletion. Обработчик может быть Lua-функцией или встроенной командой.- Перехватчик клавиш выполняется раньше действий редактора и используется только для слоя автодополнения; глобальные привязки обрабатываются на корне вида. Этот порядок менять нельзя.
- Текстовый ввод редактора — не привязка клавиши.
4. Модель отделена от GPUI
editor.rs,panel.rsиtree.rsне знают оWindowиContext.- Вид переносит изменения модели в виджет по
Workspace::revision; набор текста в редакторе ревизию не трогает, чтобы не сбрасывать курсор. - Инвариант
Workspace: открыт хотя бы один документ. Поэтомуactive()возвращает документ безOption. - Встроенный старт — одна пустая вкладка. Примеры и демонстрационные
документы не должны попадать в код приложения;
init.lua— единственное место для примеров.
5. LSP работает в фоне
LspManagerобщий (Arc) для вида, API и фоновых задач.- Процессы, чтение stdout/stderr и файловый вотчер живут в отдельных потоках;
ответы приходят через каналы и ожидаются в
background_executor, а не в кадре UI. - Какие серверы запускать, решает Lua; менеджер отвечает только за жизненный цикл, JSON-RPC и синхронизацию документов.
Соглашения
- Код, комментарии и пользовательская документация — на русском.
- Публичные элементы Rust документируются
///. - Новые зависимости добавляются только при реальной необходимости; сначала
используются возможности
gpui-kit,mluaи уже подключённых крейтов. - Изменения должны быть локальными и в стиле окружающего кода. Не добавляйте параллельные пути управления и не оставляйте мёртвый код.
Проверка
Перед завершением изменения:
cargo fmt
cargo test
cargo build
Если какую-то команду выполнить нельзя, это нужно явно указать в ответе.