# LSP-серверы — `api.editor` Запуск серверов целиком настраивается Lua-сценарием. Редактор предоставляет только клиент по stdio, синхронизацию документов и доставку диагностики. ## Запуск сервера ```lua api.editor: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 сервера }) ``` | Метод | Описание | | --- | --- | | `api.editor:run_lsp(config)` | Запустить сервер по описанию | | `api.editor:lsp_servers()` | Имена запущенных серверов: `{ "gopls", ... }` | | `api.editor:stop_lsp("gopls")` | Остановить сервер; `true`, если сервер был запущен | | `api.editor:restart_lsp("gopls")` | Перезапустить сервер с прежними настройками | | `api.editor:on_lsp_diagnostics(delay_ms, fn)` | Обработчик диагностики всех серверов; `nil` вместо `fn` удаляет его | `cmd` обязателен. Если `root` не задан или относителен, он отсчитывается от текущего рабочего каталога процесса. Поле `watcher` принимает строку, таблицу или boolean: ```lua watcher = "**/*.go" watcher = { pattern = "**/*.go", ignore = { "vendor/**" } } watcher = true -- все файлы, игнорируя только стандартные каталоги сборки ``` > `--config` меняет только каталог `init.lua`, поэтому `root = "."` указывает > на текущий каталог запуска — проект должен быть текущим рабочим каталогом. ## Автодополнение и подсказки Автодополнение включается само при вводе идентификатора; `Ctrl/Cmd+Space` открывает список вручную. Поведение клавиш описано в [keymap.md](keymap.md) и может быть переопределено через `api.keymap:map_completion_key`. Документация выбранного элемента показывается второй всплывающей панелью справа от списка. Наведение мыши показывает Markdown-документацию символа. Диагностику, которую сервер присылает после правок, редактор подчёркивает волнистой линией: ошибки — красной, предупреждения и остальные сообщения — жёлтой. Подчёркивание работает и при выключенной подсветке синтаксиса. ## Обработчик диагностики `api.editor:on_lsp_diagnostics(delay_ms, fn)` регистрирует один обработчик на все LSP-серверы. `delay_ms` — пауза тишины: если сообщения приходят чаще, вызовы пропускаются, а обработчик получает последний снимок после того, как обновления прекратились. Если зарегистрировать обработчик, когда диагностика уже накоплена, он сработает сразу после этой паузы. ```lua api.editor:on_lsp_diagnostics(1000, function(servers) for _, entry in ipairs(servers) do print(entry.server, entry.path, #entry.diagnostics) end end) ``` `servers` — массив записей по одной на пару «документ, сервер»: ```lua { server = "gopls", -- имя сервера, приславшего диагностику uri = "file:///project/main.go", -- URI документа path = "/project/main.go", -- путь файла; nil для не-file URI diagnostics = { { line = 0, character = 2, -- начало (с нуля, как в LSP) end_line = 0, end_character = 8, severity = 1, -- 1 ошибка, 2 предупреждение, 3 info, 4 hint severity_name = "error", -- error | warning | information | hint message = "undefined: foo", source = "gopls", code = "UndeclaredName", tags = {}, -- unnecessary, deprecated }, }, } ``` Позиции нумеруются с нуля; для отображения прибавляйте единицу к `line` и `character`. Остановка сервера удаляет его сообщения из следующих снимков. Пример из `init.lua` с защитой от ошибки запуска: ```lua local gopls_ok, gopls_err = pcall(function() api.editor: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 ```