DEV Community

Enrique Marques Junior
Enrique Marques Junior

Posted on • Updated on

Neovim: Migrando do coc.vim para nvim-lsp

A versão 0.5 do Neovim (nightly build) traz algumas mudanças como a integração do Lua como uma linguagem de primeira classe e o suporte a LSP embutido. Adeus CoC!

Você pode obter a versão 0.5 do Neovim aqui ou via homebrew:

$ brew unlink neovim
$ brew install neovim --HEAD
$ nvim --version
Enter fullscreen mode Exit fullscreen mode

Migrando suas configurações para Lua

Vale dar uma passada pelo guia de primeiros passos usando Lua no Neovim e começar a migrar aos poucos suas configurações.

Exemplo do meu init.lua:

vim.g.mapleader = ','
vim.api.nvim_set_keymap("n", ";", ":", { noremap = true })

vim.cmd [[
  source ~/.config/nvim/config.vim
  source ~/.config/nvim/plugins.vim
  source ~/.config/nvim/settings.vim
  source ~/.config/nvim/keymappings.vim
]]

require'config.lsp'
-- ... configs
Enter fullscreen mode Exit fullscreen mode

Escolhi mudar o init.vim para init.lua e aos poucos ir migrando cada .vim. Também mantenho por enquanto o mesmo gerenciador de plugins (vim-plug), então vamos instalar os novos plugins também por ele.

Configurando o LSP

A primeira coisa que precisamos fazer é instalar os plugins:

Instalação, Inicialização e Comandos

Para que algum servidor comece a funcionar é necessário que ele seja instalado e inicializado no seu init.lua. Com o nvim-lspinstall podemos instalar com o comando :LspInstall <linguagem>.

Utilizando no exemplo o tsserver, vamos instalar com o comando :LspInstall typescript (lista ref) e para iniciar os servidores que instalamos o seguinte trecho (em lua) é necessário:

require'lspsaga'.init_lsp_saga()
require'lspinstall'.setup()
local servers = require'lspinstall'.installed_servers()
for _, server in pairs(servers) do
  require'lspconfig'[server].setup{}
end
Enter fullscreen mode Exit fullscreen mode

Com isso você já terá o LSP rodando e pode testar abrindo um arquivo .ts ou .tsx e executar o comando :LspInfo. O lspconfig também vai aparecer no comando :checkhealth então vale a pena executa-lo para verificar se está tudo ok.

Para configurar os atalhos você precisará passar uma função on_attach no setup do lspconfig, exemplo:

local on_attach = function(client, bufnr)
-- ...mappings
end

require'lspinstall'.setup()
local servers = require'lspinstall'.installed_servers()
for _, server in pairs(servers) do
  require'lspconfig'[server].setup{ on_attach = on_attach }
end
Enter fullscreen mode Exit fullscreen mode

Com os mappings:

local on_attach = function(_, bufnr)
  local function buf_set_keymap(...) vim.api.nvim_buf_set_keymap(bufnr, ...) end
  local function buf_set_option(...) vim.api.nvim_buf_set_option(bufnr, ...) end
  local opts = { noremap = true, silent = true }

  buf_set_option('omnifunc', 'v:lua.vim.lsp.omnifunc')
  buf_set_keymap('n', '<leader>ca', ':Lspsaga code_action<CR>', opts)
  buf_set_keymap('v', '<leader>ca', ':Lspsaga range_code_action<CR>', opts)
  buf_set_keymap('n', '<leader>rn', ':Lspsaga rename<CR>', opts)
  buf_set_keymap('n', 'K', ':Lspsaga hover_doc<CR>', opts)
  buf_set_keymap('n', 'dn', ':Lspsaga diagnostic_jump_next<CR>', opts)
  buf_set_keymap('n', 'dp', ':Lspsaga diagnostic_jump_prev<CR>', opts)
  buf_set_keymap('n', 'gf', ':lua vim.lsp.buf.definition()<CR>', opts)
end

require'lspinstall'.setup()
local servers = require'lspinstall'.installed_servers()
for _, server in pairs(servers) do
  require'lspconfig'[server].setup{ on_attach = on_attach }
end
Enter fullscreen mode Exit fullscreen mode

Comandos:

  • <leader>ca: Abre pop-up com as Code Actions
  • <leader>rn: Para renomear símbolo
  • K: Exibe a referência/documentação da seleção ou posição do cursor
  • dn e dp: Navega entre os diagnósticos
  • gf: Navegação de código

Mais comandos: aqui

Se você precisar configurar algo especifico para algum servidor, lembre-se de adicionar a chamada on_attach para manter os comandos, exemplo (para linguagem lua):

require'lspconfig'.lua.setup {
  on_attach = on_attach,
  settings = {
    Lua = {
      diagnostics = {
        globals = { 'vim' }
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Para as sugestões e o auto completion, certifique-se de que você tenha os plugins SirVer/ultisnips e hrsh7th/vim-vsnip para sugestões de snippets. E então adicione o seguinte trecho:

require'compe'.setup {
  enabled = true;
  preselect = 'disable';
  source = {
    path = true;
    buffer = true;
    calc = true;
    nvim_lsp = true;
    nvim_lua = true;
    vsnip = true;
    ultisnips = true;
    -- treesitter = true;
  };
}

local t = function(str)
  return vim.api.nvim_replace_termcodes(str, true, true, true)
end

local check_back_space = function()
  local col = vim.fn.col('.') - 1
  if col == 0 or vim.fn.getline('.'):sub(col, col):match('%s') then
    return true
  else
    return false
  end
end

vim.g.vsnip_filetypes = {
  typescriptreact = {"typescript"}
}

_G.tab_complete_next = function()
  if vim.fn.pumvisible() == 1 then
    return t "<C-n>"
  elseif vim.fn.call("vsnip#available", {1}) == 1 then
    return t "<Plug>(vsnip-expand-or-jump)"
  elseif check_back_space() then
    return t "<Tab>"
  else
    return vim.fn['compe#complete']()
  end
end
_G.tab_complete_prev = function()
  if vim.fn.pumvisible() == 1 then
    return t "<C-p>"
  elseif vim.fn.call("vsnip#jumpable", {-1}) == 1 then
    return t "<Plug>(vsnip-jump-prev)"
  else
    return t "<S-Tab>"
  end
end

local opt = { expr = true, silent = true}
vim.api.nvim_set_keymap("i", "<Tab>", "v:lua.tab_complete_next()", opt)
vim.api.nvim_set_keymap("s", "<Tab>", "v:lua.tab_complete_next()", opt)
vim.api.nvim_set_keymap("i", "<S-Tab>", "v:lua.tab_complete_prev()", opt)
vim.api.nvim_set_keymap("s", "<S-Tab>", "v:lua.tab_complete_prev()", opt)
vim.api.nvim_set_keymap("i", "<CR>", 'compe#confirm("<CR>")', opt)
Enter fullscreen mode Exit fullscreen mode

Com isso você tem o autocomplete funcionando e a navegação mapeada com Tab/Shift+Tab e o Esc para fechar o pop-up.

Obs: Caso você utilize o treesitter, remova o comentário das opções do setup.

É isso ☺️. Me diz ai o que achou e manda nos comentários como ficou seu nvim.

Abraços!

Top comments (3)

Collapse
 
msansoress profile image
manuel sansores

I can't use your config, I cloned your repo and install plugins but show error in console

lsp.lua:23: attempt to index field
'lua' (a nil value)
Press ENTER or type command to continue

Collapse
 
enrsaid profile image
Enrique Marques Junior

Updated my config-nvim, more details: dev.to/enrsaid/neovim-initlua-buil...

Collapse
 
hubdev4 profile image
HubDev

Is there support to flutter like coc-flutter?