DEV Community

Heiker
Heiker

Posted on • Edited on

Configurando el cliente LSP de neovim: la manera fácil

Cuando llega el momento de "agregar soporte para el protocolo LSP" en neovim muchas personas usan estos plugins:

Lograr que estas piezas se integren requiere de un esfuerzo considerable. No es un problema, tampoco es que sea difícil... es sólo que requiere esfuerzo y no todos están dispuestos a hacerlo.

Pero ahora les digo que hay una manera fácil. Hice un plugin (lsp-zero) que puede ayudarles a integrar todas esas piezas.

Y esta es toda la configuración necesaria para empezar.

local lsp_zero = require('lsp-zero')

lsp_zero.on_attach(function(client, bufnr)
  lsp_zero.default_keymaps({buffer = bufnr})
end)

require('mason').setup({})
require('mason-lspconfig').setup({
  handlers = {
    lsp_zero.default_setup,
  },
})
Enter fullscreen mode Exit fullscreen mode

Deben estar pensando "¿eso es todo?" Sí... y no. Técnicamente tienen que instalar algunas dependencias para que funcione.

Vamos a crear una configuración con todo lo necesario para que nuestro ejemplo funcione.

Empezando de cero

Requerimientos

  • Conocimiento básico sobre Neovim: qué es el modo normal, modo de inserción, modo de comandos y cómo navegar entre ellos.
  • Neovim versión 0.8.0 o mayor.
  • Si tienes un sistema de la familia unix: git, curl o wget, unzip, tar, gzip.
  • Para windows + powershell: git, tar, and 7zip or peazip or archiver or winzip o WinRAR.

Necesitamos todo eso porque queremos gestionar todos nuestros servidores de lenguaje desde neovim.

El punto de entrada

Comenzamos nuestro viaje creando el archivo de configuración init.lua. La ubicación de este archivo varía de acuerdo al sistema operativo. Entonces lo primero que haremos será obtener la ubicación de la carpeta de configuración de Neovim. Deben ejecutar este comando en su terminal.

nvim --headless -c 'echo stdpath("config")' -c 'echo ""' -c 'quit'
Enter fullscreen mode Exit fullscreen mode

Ahora deben crear esa carpeta. Pueden el método que les resulte más cómodo, puede ser con la terminal o con un explorador de archivos.

Ya dentro de la carpeta de configuración creamos un archivo vacío llamado init.lua.

En este punto podremos acceder al archivo de configuración desde Neovim usando este comando.

nvim -c 'edit $MYVIMRC'
Enter fullscreen mode Exit fullscreen mode

Lo siguiente que haremos será probar si Neovim puede leer nuestra configuración. Vamos a cambiar el tema del editor, usaremos un tema claro. Abrán el archivo init.lua y coloquen esto.

vim.cmd.colorscheme('morning')
Enter fullscreen mode Exit fullscreen mode

Reinicien Neovim. Deberían notar el cambio en el tema. Si Neovim les arroja un error eso quiere decir que su versión de Neovim no cumple los requerimientos. Les sugiero que vayan el repositorio de Neovim en github, en la sección "releases" podrán encontrar los ejecutables para la versión más reciente.

¿Qué pueden hacer?

  • Si tienen Neovim v0.7 pueden instalar la rama compat-07 de lsp-zero. Pueden seguir este tutorial.

  • Si tienen Neovim v0.6 o v0.5 pueden instalar la version v1 de lsp-zero. Puede seguir el tutorial de la version 1.

Suponiendo que todo salió bien, ya pueden cambiar el tema a algo más cómodo.

vim.cmd.colorscheme('habamax')
Enter fullscreen mode Exit fullscreen mode

El manejador de plugins

Nota: técnicamente no necesitamos uno pero los manejadores de plugins nos faciltan la vida.

Vamos a usar lazy.nvim, simplemente porque es popular. Pueden hacer muchas cosas con lazy.nvim pero aquí sólo les mostraré un uso básico.

Algo muy bueno que tiene lazy.nvim es que desde su documentación nos enseñan cómo podemos instalarlo usando lua.

Vamos a agregar esto en nuestro init.lua.

local lazypath = vim.fn.stdpath('data') .. '/lazy/lazy.nvim'

-- Instalar lazy.nvim si no está presente
if not vim.loop.fs_stat(lazypath) then
  print('Instalando lazy.nvim....')
  vim.fn.system({
    'git',
    'clone',
    '--filter=blob:none',
    'https://github.com/folke/lazy.nvim.git',
    '--branch=stable',
    lazypath,
  })
  print('Listo.')
end

vim.opt.rtp:prepend(lazypath)
Enter fullscreen mode Exit fullscreen mode

Prestén atención a la variable lazypath, esta almacena el resultado de la función stdpath('data') la cual nos da la ubicación de la carpeta de datos de Neovim. De esta manera no necesitamos cambiar la ruta dependiendo del sistema operativo, Neovim lo hará por nosotros. Si quieren saber la ubicación de esa carpeta ejecute este comando en Neovim.

:echo stdpath('data') . '/lazy/lazy.nvim'
Enter fullscreen mode Exit fullscreen mode

Para usar lazy.nvim tenemos que invocar la función .setup() del módulo lazy.

require('lazy').setup({
  ---
  -- Lista de plugins...
  ---
})
Enter fullscreen mode Exit fullscreen mode

Agregando un plugin

Esta es la parte donde aprendemos a usar lazy.nvim. Vamos a probar con un plugin simple, un tema para Neovim llamado tokyonight.nvim.

¿Listos? Estos son los pasos para descargar un tema.

  1. Añadimos el plugin a nuestra lista de plugins.
require('lazy').setup({
  {'folke/tokyonight.nvim'},
})
Enter fullscreen mode Exit fullscreen mode

Con lazy.nvim lo único que necesitamos para descargar un plugin desde github es el nombre de usuario y el nombre del repositorio.

  1. Debemos borrar la línea que configura el tema.

  2. Configuramos el tema nuevo al final de init.lua.

vim.opt.termguicolors = true
vim.cmd.colorscheme('tokyonight')
Enter fullscreen mode Exit fullscreen mode
  1. Guardamos los cambios.

  2. Reiniciamos Neovim.

Después de abrir Neovim debería mostrarnos un mensaje indicando que está descargando lazy.nvim. Después deberá aparecer una ventana flotante, esta nos va a mostrar el progreso de la descarga del resto de los plugins. Finalmente los plugins que instalamos serán cargados.

Configurando lsp-zero

Ahora podemos agregar lsp-zero y todas sus dependencias a la lista de plugins.

require('lazy').setup({
  {'folke/tokyonight.nvim'},
  {'VonHeikemen/lsp-zero.nvim', branch = 'v3.x'},
  {'williamboman/mason.nvim'},
  {'williamboman/mason-lspconfig.nvim'},
  {'neovim/nvim-lspconfig'},
  {'hrsh7th/nvim-cmp'},
  {'hrsh7th/cmp-nvim-lsp'},
  {'L3MON4D3/LuaSnip'},
})
Enter fullscreen mode Exit fullscreen mode

Luego de eso podemos agregar el código de configuración al final de nuestra configuración.

local lsp_zero = require('lsp-zero')

lsp_zero.on_attach(function(client, bufnr)
  lsp_zero.default_keymaps({buffer = bufnr})
end)

require('mason').setup({})
require('mason-lspconfig').setup({
  handlers = {
    lsp_zero.default_setup,
  },
})
Enter fullscreen mode Exit fullscreen mode

Guarden los cambios, reinicien Neovim y esperen a que termine la descarga de los plugins.

Instalando un servidor LSP

Vamos a probar con el servidor LSP para lua.

Van a abrir el archivo init.lua con Neovim y van a ejecutar este comando :LspInstall. El plugin mason-lspconfig.nvim va a sugerir una lista de servidores. Neovim deberá mostrar este mensaje.

Please select which server you want to install for filetype "lua":
1: lua_ls
Type number and <Enter> or click with the mouse (q or empty cancels):
Enter fullscreen mode Exit fullscreen mode

Por el momento sólo tenemos una opción, lua_ls. Deben oprimir 1 y confirman la selección presionando Enter. Deberá aparecer una ventana flotante. Cuando se termina la descarga del servidor aparecerá un mensaje.

Actualmente los servidors LSP no pueden iniciar automáticamente después de su instalación. Deben reiniciar Neovim. Una vez que el servidor empiece a analizar su código deberán notar las advertencias en la variable global vim, eso significa que todo está bien.

Para asegurarnos que lua_ls pueda detectar la raíz de nuestro proyecto debemos crear un archivo llamado .luarc.json. Este archivo puede estar vacío, sólo debe existir en la carpeta de configuración de Neovim.

Si quieren, pueden configurar lua_ls específicamente para Neovim, usando la función .nvim_lua_ls().

require('mason-lspconfig').setup({
  handlers = {
    lsp_zero.default_setup,
    lua_ls = function()
      local lua_opts = lsp_zero.nvim_lua_ls()
      require('lspconfig').lua_ls.setup(lua_opts)
    end,
  },
})
Enter fullscreen mode Exit fullscreen mode

Ya están listos. Pueden reiniciar Neovim y abrir init.lua, el soporte para la configuración deberá mejorar ligeramente.

Ejemplo completo

local lazypath = vim.fn.stdpath('data') .. '/lazy/lazy.nvim'

-- Instalar lazy.nvim si no está presente
if not vim.loop.fs_stat(lazypath) then
  print('Instalando lazy.nvim....')
  vim.fn.system({
    'git',
    'clone',
    '--filter=blob:none',
    'https://github.com/folke/lazy.nvim.git',
    '--branch=stable',
    lazypath,
  })
  print('Listo.')
end

vim.opt.rtp:prepend(lazypath)

require('lazy').setup({
  {'folke/tokyonight.nvim'},
  {'VonHeikemen/lsp-zero.nvim', branch = 'v3.x'},
  {'williamboman/mason.nvim'},
  {'williamboman/mason-lspconfig.nvim'},
  {'neovim/nvim-lspconfig'},
  {'hrsh7th/nvim-cmp'},
  {'hrsh7th/cmp-nvim-lsp'},
  {'L3MON4D3/LuaSnip'},
})

-- Set colorscheme
vim.opt.termguicolors = true
vim.cmd.colorscheme('tokyonight')

-- LSP
local lsp_zero = require('lsp-zero')

lsp_zero.on_attach(function(client, bufnr)
  lsp_zero.default_keymaps({buffer = bufnr})
end)

require('mason').setup({})
require('mason-lspconfig').setup({
  handlers = {
    lsp_zero.default_setup,
    lua_ls = function()
      local lua_opts = lsp_zero.nvim_lua_ls()
      require('lspconfig').lua_ls.setup(lua_opts)
    end,
  },
})
Enter fullscreen mode Exit fullscreen mode

¿Qué Sigue?

Visiten el repositorio de lsp-zero en github. Lean la documentación ahí o con el comando :help lsp-zero.

Lean sobre los atajos de teclado que crea lsp-zero:

También pasen por la documentación de mason.nvim.

Pueden preguntarme cualquier cosa sobre lsp-zero aquí, en la sección de discusión en github, o en matrix #lsp-zero-nvim:matrix.org.


Gracias por su tiempo. Si este artículo les pareció útil y quieren apoyar mis esfuerzos para crear más contenido pueden dejar una propina en ko-fi.com/vonheikemen.

buy me a coffee

Top comments (10)

Collapse
 
vonheikemen profile image
Heiker • Edited

Aquí les dejo la misma configuración pero creada en vimscript, usando vim-plug para descargar plugins.

Collapse
 
gorjes4444 profile image
Gorjes4444

Hola, muy bueno tu post, pero tengo dos problemas, ojalá me puedas guiar.
Tengo instalado neovim en windows y esta es mi configuración de init.lua

Image description

Image description

Un problema que tengo es que cuando paso al modo insertar me sale el mensaje de error de la imgen de abajo. Luego puedo insertar pero no puedo quitar ese error.

El otro problema es que no tengo opciones de autocompletado con palabras del mismo buffer y no se como configurar esa opción. Entiendo que hay que poner

sources = {
{ name = 'buffer' }
}
})
O algo así pero no entiendo en que archivo debería hacerlo. Soy muy nuevo en esto y estoy bastante perdido. Sepan comprender y acepto consejos.
Saludos

Collapse
 
vonheikemen profile image
Heiker

Intenta colocar tus nuevos plugins fuera de las dependencias de lsp-zero. Probablemente hay un problema en el orden en que se cargan los módulos.

{'folke/tokyonight.nvim'},
{
  'nvim-lualine/lualine.nvim',
  requires = {'nvim-tree/nvim-web-devicons', opt = true}
},
{'nvim-lua/plenary.nvim'},
{'j-morano/buffer_manager.nvim'},
{
  'VonHeikemen/lsp-zero.nvim',
  branch = 'v2.x',
  dependencies = {
    -- Soporte LSP
    {'neovim/nvim-lspconfig'},
    {'williamboman/mason.nvim'},
    {'williamboman/mason-lspconfig.nvim'},

    -- Autocompletado
    {'hrsh7th/nvim-cmp'},
    {'hrsh7th/cmp-nvim-lsp'},
    {'L3MON4D3/LuaSnip'},
  }
},
Enter fullscreen mode Exit fullscreen mode

Con el otro problema. Puedes configurar el autocompletado en tu archivo init.lua. Debes tener en cuenta que cada "source" que agregas a nvim-cmp es un plugin nuevo que debes instalar. Entonces, debes instalar este plugin: cmp-buffer. Luego, usa el modulo cmp para configurar la opción sources. Así.

local lsp = require('lsp-zero').preset({})

lsp.on_attach(function(client, bufnr)
  lsp.default_keymaps({buffer = bufnr})
end)

lsp.setup()

local cmp = require('cmp')

cmp.setup({
  sources = {
    {name = 'nvim_lsp'},
    {name = 'buffer'},
  }
})
Enter fullscreen mode Exit fullscreen mode

Debes usar cmp.setup() después de configurar lsp-zero, así te aseguras de que tu configuración sobreescriba la de lsp-zero.

Aqui {name = 'nvim_lsp'} pertenece a este plugin cmp-nvim-lsp, ese ya lo tienes instalado, esta en las dependencias de lsp-zero, pero debes colocarlo para no perder el autocompletado del cliente LSP. Ahora, {name = 'buffer'} es cmp-buffer. Esto es importante: la propiedad name no es el nombre del plugin. Cuando vas a instalar un "source" para nvim-cmp no intentes adivinar, revisa la documentación para saber qué valor debería tener name.

Collapse
 
gorjes4444 profile image
Gorjes4444

¡Muchisimas gracias hermano! Gracias por contestar y gracias por la paciencia.

Collapse
 
shayredd22 profile image
ShayRedD12 • Edited

tengo una pregnta...
lo que pasa es que me sale este error al tratar de instalar el server de phppactor
adjunto pantallazo del error
Image description

solo me deja instalar el de instelepehense pero cuando trato de escribir algo en un archivo php no sale ninguna sujerencia

Collapse
 
vonheikemen profile image
Heiker

Para instalar phpactor necesitas composer.

Si quieres saber si un servidor LSP está activo en un archivo ejecuta el comando :LspInfo.

Collapse
 
peterr2d2 profile image
Pedro Farias

Hola disculpa por las molestias soy nuevo con lo de las configuraciones y conozco muy poco sobre nvim y lua, segui los pasos que tienes en el post pero tengo el siguiente error y no se muy bien a que se debe

Image description

espero me puedas ayudar

Collapse
 
vonheikemen profile image
Heiker

Este archivo está creando un conflicto.

/home/arthur/.config/nvim/lua/lsp-zero/init.lua
Enter fullscreen mode Exit fullscreen mode

Impide que neovim cargue el script que está dentro del plugin. Porque estás creando otro módulo con el nombre lsp-zero.

Debes crear otro módulo con un nombre único para evitar conflictos con cualquier plugin. Puedes crear uno llamado user y colocar tu script ahí.

/home/arthur/.config/nvim/lua/user/lsp-zero/init.lua
Enter fullscreen mode Exit fullscreen mode

Luego en tu configuración lo llamas de esta manera.

require('user.lsp-zero')
Enter fullscreen mode Exit fullscreen mode
Collapse
 
vantyc profile image
vantyc

*Espectacular trabajo! en unos minutos has resuelto mi busqueda de semanas. Gracias!
1.- Se puede hacer lo mismo con vim, quiza con otro conjunto de plugins?
2.- Cuando aparecen errores en el código pre-existente como sacas el menú de correcciones o el detalle del error en neovim?

Collapse
 
vonheikemen profile image
Heiker

1.- Se puede hacer lo mismo con vim, quiza con otro conjunto de plugins?

Creo que sí. Se puede usar vim-lsp para integrar un cliente lsp. Luego tienes vim-lsp-settings, es como un complemento de vim-lsp, es una colección de configuraciones para servidores LSP. También parece tener un método para instalar servidores. La integración con el autocompletado puede hacerse con asyncomplete,vim (plugin del mismo autor de vim-lsp) o ddc.vim que también es muy bueno.

2.- Cuando aparecen errores en el código pre-existente como sacas el menú de correcciones o el detalle del error en neovim?

El mensaje de error en la ventana flotante se activa con el atajo g + l. Las correcciones (en neovim le dicen "code actions") se activan con F4.