# Lua API Приложение выполняет `init.lua` при запуске и предоставляет сценариям объект `app` для управления окном, вкладками, подсветкой и LSP-серверами. ## Запуск и каталог сценариев Каталог поиска `init.lua` задаётся константой `SCRIPT_DIR` в `src/constants.rs` (по умолчанию — текущий каталог). Его можно переопределить аргументом командной строки: ```sh gpui-editor-test --config /path/to/project main.go cargo run -- --config ./config cargo run -- main.go ``` - В каталоге `--config` должны лежать `init.lua` и подключаемые им модули. - Первый позиционный аргумент открывается после выполнения `init.lua` через `app:open(path)` — как `vim main.go` или `nano main.go`. ## Объект `app` Номера вкладок во всех методах нумеруются с нуля. ### Вкладки | Метод | Описание | | --- | --- | | `app:tabs()` | Список вкладок: `{{ index = 0, title = "main.rs" }, ...}` | | `app:active_tab()` | Индекс активной вкладки | | `app:set_active_tab(index)` | Сделать вкладку активной; `true`, если вкладка существует | | `app:next_tab()` | Переключить на следующую вкладку, вернуть индекс | | `app:previous_tab()` | Переключить на предыдущую вкладку, вернуть индекс | | `app:open_tab()` | Открыть пустую вкладку, вернуть индекс | | `app:open(path)` | Открыть файл с диска, вернуть индекс вкладки. Если файла нет — открывается пустой буфер с таким именем | | `app:close_tab(index)` | Закрыть вкладку; `true`, если вкладка закрыта | ### Текст | Метод | Описание | | --- | --- | | `app:active_text()` | Текст активной вкладки | | `app:set_active_text(text)` | Заменить текст активной вкладки | ### Подсветка синтаксиса Подсветка по умолчанию выключена. Поддерживаемые языки: `rust`, `go`, `js`, `json`, `python`. | Метод | Описание | | --- | --- | | `app:set_language(index, "rust")` | Включить подсветку для вкладки; `false`, если вкладки нет или язык не поддерживается | | `app:language(index)` | Язык подсветки вкладки или `nil` | | `app:clear_language(index)` | Выключить подсветку для вкладки | ```lua app:set_language(0, "rust") ``` ### Сохранение | Метод | Описание | | --- | --- | | `app:save()` | Сохранить активную вкладку в её файл | ### Привязка клавиш `app:map_key(keys, fn)` назначает обработчик на нажатие или отпускание клавиши (синтаксис в духе nvim): | Запись | Значение | | --- | --- | | `"a"` | нажатие A | | `"1"` | нажатие 1 | | `"!a"` | отпускание A | | `""` | C при зажатом Shift | | `""` | Z при зажатом Ctrl | | `""` | отпускание R при зажатом Alt | Клавиша сравнивается с именем клавиши от GPUI. Caps Lock не важен. На Linux и Windows буквы берутся по аппаратному keycode, поэтому `` работает и на русской раскладке. ```lua app:map_key("", function() app:save() end) app:map_key("", function() app:close() end) app:map_key("", function() app:close() end) app:map_key("", function() app.right_panel:toggle() end) app:map_key("", function() app.bottom_panel:toggle() end) ``` ### Окно | Метод | Описание | | --- | --- | | `app:close()` | Закрыть окно | | `app:toggle_maximize()` | Развернуть окно / вернуть прежний размер | | `app:set_maximized(true/false)` | Развернуть (`true`) или восстановить (`false`) окно | | `app:minimize()` | Свернуть окно | | `app:is_maximized()` | Развёрнуто ли окно прямо сейчас | ## LSP-серверы Запуск серверов целиком настраивается Lua-сценарием. ```lua app:run_lsp({ name = "gopls", -- условное имя для stop/restart cmd = "gopls", -- путь к бинарнику или имя в PATH args = { "serve" }, -- аргументы процесса env = { GOFLAGS = "-mod=mod" }, -- переменные окружения languages = { "go" }, -- какие languageId обслуживает watcher = "**/*.go", -- шаблон файлового вотчера root = ".", -- корень workspace (по умолчанию cwd) initialization_options = {}, -- initializationOptions сервера }) ``` | Метод | Описание | | --- | --- | | `app:run_lsp(config)` | Запустить сервер по описанию | | `app:lsp_servers()` | Имена запущенных серверов: `{ "gopls", ... }` | | `app:stop_lsp("gopls")` | Остановить сервер; `true`, если сервер был запущен | | `app:restart_lsp("gopls")` | Перезапустить сервер с прежними настройками | Поле `watcher` принимает строку или таблицу: ```lua watcher = "**/*.go" watcher = { pattern = "**/*.go", ignore = { "vendor/**" } } ``` Автодополнение включается само при вводе идентификатора; `Ctrl+Space` открывает список вручную. Пока список открыт, `↑`/`↓` и `PageUp`/`PageDown` перемещают выделение (курсор при этом стоит на месте), `Enter` или `Tab` вставляют выбранный элемент, `Esc` закрывает список. Горизонтальные стрелки, `Home` и `End` закрывают список и работают с курсором как обычно. Документация выбранного элемента показывается второй всплывающей панелью справа от списка. Примеры запуска: ```lua app:run_lsp({ name = "gopls", cmd = "gopls", args = { "serve" }, languages = { "go" }, watcher = "**/*.go" }) app:run_lsp({ name = "rust-analyzer", cmd = "rust-analyzer", languages = { "rust" }, watcher = "**/*.rs" }) ``` Пример из `init.lua` с защитой от ошибки запуска: ```lua local gopls_ok, gopls_err = pcall(function() app:run_lsp({ name = "gopls", cmd = "gopls", args = { "serve" }, root = ".", languages = { "go" }, watcher = { pattern = "**/*.go", ignore = { "vendor/**" } }, initialization_options = { usePlaceholders = true, completeUnimported = true, }, }) end) if not gopls_ok then print("[lsp] gopls не запущен: " .. tostring(gopls_err)) end ``` > `--config` меняет только каталог `init.lua`, поэтому `root = "."` указывает > на текущий каталог запуска — проект должен быть текущим рабочим каталогом. ## Панели окна По умолчанию панели закрыты, размер меняется перетаскиванием. Для `app.left_panel`, `app.right_panel` и `app.bottom_panel` доступны одинаковые методы: | Метод | Описание | | --- | --- | | `app.left_panel:open()` | Открыть панель | | `app.left_panel:close()` | Закрыть панель | | `app.left_panel:toggle()` | Переключить панель; вернуть `true`, если панель открыта | | `app.left_panel:is_open()` | Открыта ли панель | ```lua app.left_panel:open() app.right_panel:toggle() app.bottom_panel:close() ``` ## Подключение других Lua-файлов Файлы подключаются из каталога сценариев: | Способ | Описание | | --- | --- | | `include("tools.lua")` | Выполнить файл сразу | | `require("tools")` | Выполнить один раз (как обычный Lua-модуль) | ## Добавление новых методов Методы добавляются в `src/api.rs`: всё, что есть в `impl AppApi`, помеченном `#[mlua::userdata_impl]`, автоматически доступно из Lua. Чтобы не экспортировать метод, его помечают `#[lua(skip)]`. ## Полный пример `init.lua` ```lua print("[lua] init.lua выполнен") app:set_language(0, "rust") app:next_tab() app:map_key("", function() app:close() end) app:map_key("", function() app.right_panel:toggle() end) app:map_key("", function() app.bottom_panel:toggle() end) app:open_tab() ```