116 lines
5.9 KiB
Markdown
116 lines
5.9 KiB
Markdown
# 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
|
|
```
|