Для начала установим typescript и typescript-language-server:
sudo npm install --global typescript typescript-language-server
Запустить typescript-language-server:
typescript-language-server --stdio
Вот пример файла с настройкой и запуском LSP-сервера:
-- ~/.config/nvim/lua/lsp.lua
-- 1. Описание сервера
vim.lsp.config['tsserver'] = {
cmd = { 'typescript-language-server', '--stdio' },
filetypes = { 'javascript', 'javascriptreact', 'typescript', 'typescriptreact' },
root_markers = { 'package.json', 'tsconfig.json', 'jsconfig.json', '.git' },
settings = {}, -- настройки tsserver можно оставить пустыми
}
-- 2. Включение сервера
vim.lsp.enable('tsserver')
И давайте подключим этот LSP-сервер в самом низу файла init.lua:
-- ~/.config/nvim/init.lua
-- ...
require("lsp")
Проверить, работает ли LSP-сервер:
:checkhealth vim.lsp
Ещё один способ проверить, работает ли LSP-сервер:
:lua print(vim.inspect(vim.lsp.get_clients({bufnr=0})))
-- Если вывод: "{}", то значит LSP-сервер не работает
-- А если вывод есть, то всё в порядке.
-- Если запустить эту команду в .js- / .ts-файле, то получим вывод,
-- а если запустить, например, в .lua-файле, то получим: "{}".
-- Значит, для .lua LSP-сервер не работает.
Если открыть .js-файл, то мы можем заметить напротив некоторых строк пометки (если включен signcolumn - vim.opt.signcolumn = "yes"):
Как посмотреть подсказку / комментарий. Нужно переместиться на строку с подсказкой / ошибкой и нажать "K".
Также для работы понадобятся:
Сам nvim-cmp ничего не предлагает. nvim-cmp – это менеджер меню, а варианты ему приносят источники (sources). Каждая строка в dependencies – один источник данных. cmp-nvim-lsp – самый важный источник. Это мост между LSP и nvim-cmp. LSP не участвует в автодополнении без cmp-nvim-lsp.
-- ~/.config/nvim/lua/plugins/cmp.lua
return {
{
'hrsh7th/nvim-cmp',
dependencies = {
'hrsh7th/cmp-nvim-lsp',
'hrsh7th/cmp-buffer',
'hrsh7th/cmp-path',
},
config = function()
local cmp = require('cmp')
cmp.setup({
completion = {
completeopt = 'menu,menuone,noselect',
},
mapping = cmp.mapping.preset.insert({
['<C-Space>'] = cmp.mapping.complete(),
['<CR>'] = cmp.mapping.confirm({ select = true }),
['<Tab>'] = cmp.mapping.select_next_item(),
['<S-Tab>'] = cmp.mapping.select_prev_item(),
}),
sources = {
{ name = 'nvim_lsp' },
{ name = 'buffer' },
{ name = 'path' },
},
})
end,
},
}
cmp.mapping – это не vim.keymap. Это внутренняя система обработки клавиш плагина nvim-cmp. Она работает только когда активно completion-меню. Это логика UI-автодополнения, а не редактора.
А затем подключаем nvim-cmp в init.lua:
-- ~/.config/nvim/init.lua
-- ...
require("lazy").setup({
spec = {
{ ... },
{ import = "plugins.cmp" },
},
install = { colorscheme = { "habamax" } }
})
Теперь можно открыть .js- или .ts-файл и автодополнение должно работать.
Подправим файл ~/.config/nvim/lua/plugins/cmp.lua:
-- ~/.config/nvim/lua/plugins/cmp.lua
return {
{
'hrsh7th/nvim-cmp',
dependencies = {
-- completion
'hrsh7th/cmp-nvim-lsp',
'hrsh7th/cmp-buffer',
'hrsh7th/cmp-path',
-- snippets
'L3MON4D3/LuaSnip',
'saadparwaiz1/cmp_luasnip',
'rafamadriz/friendly-snippets',
},
config = function()
local cmp = require('cmp')
local luasnip = require('luasnip')
-- Загружаем сниппеты из friendly-snippets
require('luasnip.loaders.from_vscode').lazy_load()
cmp.setup({
snippet = {
expand = function(args)
luasnip.lsp_expand(args.body)
end,
},
mapping = cmp.mapping.preset.insert({
['<C-Space>'] = cmp.mapping.complete(),
['<CR>'] = cmp.mapping.confirm({ select = true }),
['<Tab>'] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_next_item()
elseif luasnip.expand_or_jumpable() then
luasnip.expand_or_jump()
else
fallback()
end
end, { 'i', 's' }),
['<S-Tab>'] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_prev_item()
elseif luasnip.jumpable(-1) then
luasnip.jump(-1)
else
fallback()
end
end, { 'i', 's' }),
}),
sources = {
{ name = 'nvim_lsp' },
{ name = 'luasnip' }, -- добавим ещё и luasnip
{ name = 'buffer' },
{ name = 'path' },
},
})
end,
},
}
Теперь, когда мы запустим .js- или .ts-файл и начнём набирать код – например, for, – то в выпадающем списке появится выбор сниппета: for~ snippet.
Для начала установим lua-languager-server:
sudo pacman -S lua-language-server
# Проверяем:
lua-language-server --version
Добавляем LSP-сервер для Lua в ~/.config/nvim/lua/lsp.lua:
-- ~/.config/nvim/lua/lsp.lua
-- 1. Описание TypeScript- / JavaScript-сервера:
vim.lsp.config['tsserver'] = {
cmd = { 'typescript-language-server', '--stdio' },
filetypes = { 'javascript', 'javascriptreact', 'typescript', 'typescriptreact' },
root_markers = { 'package.json', 'tsconfig.json', 'jsconfig.json', '.git' },
settings = {}, -- настройки tsserver можно оставить пустыми
}
-- 2. Описание Lua-сервера:
vim.lsp.config['lua_ls'] = {
cmd = { 'lua-language-server' },
filetypes = { 'lua' },
root_markers = { '.git', '.luarc.json', '.luarc.jsonc' },
settings = {
Lua = {
runtime = {
version = 'LuaJIT', -- важно для Neovim
},
diagnostics = {
globals = { 'vim' }, -- чтобы не ругался на vim.*
},
workspace = {
library = vim.api.nvim_get_runtime_file('', true),
checkThirdParty = false,
},
},
},
}
-- 3. Включение серверов:
vim.lsp.enable('tsserver')
vim.lsp.enable('lua_ls')
Теперь nvim-cmp и сниппеты должны понимать и Lua.
lala