DEV Community

Heiker
Heiker

Posted on • Updated on

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

Cuando llega el momento de "agregar soporte para LSP" en neovim muchas personas usan tres componentes: el cliente LSP nativo, nvim-cmp (un plugin de autocompletado) y mason.nvim. 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 incluye todo el código de configuración necesario para integrar nvim-cmp, mason.nvim y el cliente LSP. Y la mejor parte, ustedes como usuarios sólo deben agregar estas líneas de código en su configuración personal:

local lsp = require('lsp-zero').preset({
  name = 'minimal',
  set_lsp_keymaps = true,
  manage_nvim_cmp = true,
  suggest_lsp_servers = false,
})

lsp.setup()
Enter fullscreen mode Exit fullscreen mode

Aquí un vistazo de lo que van a obtener.

Demo screenshot. Menú de sugerencias con tres items

Ver video completo.

Mostrado en video:

  • Plugin de autocompletado (nvim-cmp) completamente configurado.
  • Sugerencias de autocompletado proporcionadas por el servidor de lenguaje lua_ls, así como también de otras fuentes.
  • Expansión de snippets y movilización del cursor entre placeholders.
  • Íconos de diagnóstico mostrados al costado.
  • Mensajes de diagnóstico mostrados en una ventana flotante.
  • "Code actions."

Deben estar pensando "¿Todo eso con 7 líneas de código?" Sí... y no. Técnicamente tienen que instalar algunas dependencias para que funcione. Se requieren más de 7 líneas.

Si utilizan packer.nvim deberán incluir esto en su lista de plugins.

use {
  'VonHeikemen/lsp-zero.nvim',
  branch = 'v1.x',
  requires = {
    -- Soporte LSP
    {'neovim/nvim-lspconfig'},
    {
      'williamboman/mason.nvim',
      run = function() pcall(vim.cmd, 'MasonUpdate') end
    },
    {'williamboman/mason-lspconfig.nvim'},

    -- Autocompletado
    {'hrsh7th/nvim-cmp'},
    {'hrsh7th/cmp-buffer'},
    {'hrsh7th/cmp-path'},
    {'saadparwaiz1/cmp_luasnip'},
    {'hrsh7th/cmp-nvim-lsp'},
    {'hrsh7th/cmp-nvim-lua'},

    -- Snippets
    {'L3MON4D3/LuaSnip'},
    {'rafamadriz/friendly-snippets'},
  }
}
Enter fullscreen mode Exit fullscreen mode

Si desean podemos probarlo recreando la configuración que usé en el demo.

Empezando de cero

Requerimientos

Primero lo primero, vamos revisar qué necesitamos.

  • Neovim versión 0.7.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.

De aquí en adelante voy a asumir que el sistema que usan es linux. También asumiré que saben cómo ejecutar comandos dentro de neovim.

Comenzamos con un poco de lua

Vamos ver dónde debería estar el archivo de configuración de neovim. Abren neovim y ejecutan el comando :echo stdpath('config), les mostrará la carpeta donde debería estar nuestro archivo init.lua. En mi caso muestra /home/dev/.config/nvim. Vamos a crear la configuración desde neovim, ejecutamos:

:edit ~/.config/nvim/init.lua
Enter fullscreen mode Exit fullscreen mode

Empecemos con una simple prueba. Si presionan <Tab> en modo de inserción se darán cuenta que el cursor avanza 8 espacios, vamos a cambiar eso. En nuestra configuración agregaremos esto.

-- Expande tab a dos espacios
vim.opt.tabstop = 2
vim.opt.shiftwidth = 2
vim.opt.softtabstop = 2
vim.opt.expandtab = true
Enter fullscreen mode Exit fullscreen mode

Guardamos el archivo y salimos de neovim con el comando :wq.

Entramos nuevamente a neovim, vamos a modo de inserción y presionamos <Tab>. El cursor debería avanzar sólo 2 espacios. De no ser así probablemente se equivocaron colocando la ruta del archivo.

Plugin manager

Para descargar los plugins necesarios vamos a usar packer, pero sólo porque todo los demás hacen lo mismo.

Vamos al repositorio de packer.nvim en github, nos pasamos por la sección quickstart, copiamos el git clone que corresponde a nuestro sistema operativo. Yo les mostraré el de linux:

git clone --depth 1 https://github.com/wbthomason/packer.nvim\
 ~/.local/share/nvim/site/pack/packer/start/packer.nvim
Enter fullscreen mode Exit fullscreen mode

Ahora regresamos al init.lua. Al final del archivo vamos a añadir:

require('packer').startup(function(use)
  -- Packer puede actualizarse solo
  use 'wbthomason/packer.nvim'

  -- Tema
  use 'joshdick/onedark.vim'
end)
Enter fullscreen mode Exit fullscreen mode

Aquí ocurren un par de cosas. Primero inicializamos packer y le decimos que queremos gestionar dos plugins. El patrón que deberían tener en cuenta cuando agregan un plugin es este:

use 'usuario-github/repositorio'
Enter fullscreen mode Exit fullscreen mode

Eso es todo lo que necesita packer para descargar un plugin desde github.

En este punto no necesitamos hacer la rutina de guardar y salir. Guardamos el archivo con el comando :write, luego lo evaluamos con :source %. Ya podremos instalar los nuevos plugins. Ejecutamos :PackerSync. Aparecerá una ventana lateral anunciando el progreso de la descarga. Una vez que culmine la descarga podremos cerrar la ventana presionando q.

Para asegurarnos que todo salió bien vamos a usar el nuevo tema que descargamos. Al final del archivo agregaremos.

vim.opt.signcolumn = 'yes'
vim.opt.termguicolors = true
pcall(vim.cmd, 'colorscheme onedark')
Enter fullscreen mode Exit fullscreen mode

Guardan, evalúan. Notarán que los colores de la interfaz cambian.

Soporte para LSP

Finalmente, ya tenemos una buena base para agregar las funcionalidades basadas en LSP. Bien, vamos a añadir lsp-zero y todas sus dependencias justo debajo de la sentencia use que tiene el tema.

Su lista de plugins debería verse así.

require('packer').startup(function(use)
  -- Packer puede actualizarse solo
  use 'wbthomason/packer.nvim'

  -- Tema
  use 'joshdick/onedark.vim'

  -- LSP
  use {
    'VonHeikemen/lsp-zero.nvim',
    branch = 'v1.x',
    requires = {
      -- Soporte LSP
      {'neovim/nvim-lspconfig'},
      {
        'williamboman/mason.nvim',
        run = function() pcall(vim.cmd, 'MasonUpdate') end
      },
      {'williamboman/mason-lspconfig.nvim'},

      -- Autocompletado
      {'hrsh7th/nvim-cmp'},
      {'hrsh7th/cmp-buffer'},
      {'hrsh7th/cmp-path'},
      {'saadparwaiz1/cmp_luasnip'},
      {'hrsh7th/cmp-nvim-lsp'},
      {'hrsh7th/cmp-nvim-lua'},

      -- Snippets
      {'L3MON4D3/LuaSnip'},
      {'rafamadriz/friendly-snippets'},
    }
  }
end)
Enter fullscreen mode Exit fullscreen mode

Guardamos el archivo, lo evaluamos. Instalamos con :PackerSync.

Ahora añadimos la configuración de lsp-zero.

local lsp = require('lsp-zero')
lsp.preset('recommended')

lsp.setup()
Enter fullscreen mode Exit fullscreen mode

Guardamos el archivo y salimos de neovim.

Abrimos neovim nuevamente. Vamos a editar init.lua. Usen :edit ~/.config/nvim/init.lua. Ahora ejecuten el comando :LspInstall, con esto mason.nvim nos mostrará una lista de servidores que podremos instalar para lua. Deberá aparecer algo como esto.

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

Presionamos 1 para elegir lua_ls, luego presionamos enter. Aparecerá una ventana flotante que nos mostrará el progreso de la instalación.

Es muy probable que el servidor LSP no pueda iniciar automáticamente después de la instalación. Deberán usar el comando :edit para refrescar el archivo o reinciar neovim si lo anterior no funciona. Una vez que neovim inicialice el servidor aparecerán indicadores de advertencia donde está la variable global vim.

Si desean pueden añadir una configuración de lua_ls hecha a la medida para neovim, agregando una sola línea de código.

lsp.nvim_workspace()
Enter fullscreen mode Exit fullscreen mode

Agregan esa línea antes del llamado a .setup().

local lsp = require('lsp-zero').preset({
  name = 'minimal',
  set_lsp_keymaps = true,
  manage_nvim_cmp = true,
  suggest_lsp_servers = false,
})

lsp.nvim_workspace()

lsp.setup()
Enter fullscreen mode Exit fullscreen mode

Eso es todo. Ya están listos. Reinicien neovim nuevamente, deberían tener soporte total para la api de lua dentro de neovim.

Ejemplo completo

---
-- Opciones del editor
---

-- Expande tab a dos espacios
vim.opt.tabstop = 2
vim.opt.shiftwidth = 2
vim.opt.softtabstop = 2
vim.opt.expandtab = true

-- Dame espacio
vim.opt.signcolumn = 'yes'

---
-- Plugins
---

require('packer').startup(function(use)
  -- Packer puede actualizarse solo
  use 'wbthomason/packer.nvim'

  -- Tema
  use 'joshdick/onedark.vim'

  -- LSP
  use {
    'VonHeikemen/lsp-zero.nvim',
    branch = 'v1.x',
    requires = {
      -- Soporte LSP
      {'neovim/nvim-lspconfig'},
      {
        'williamboman/mason.nvim',
        run = function() pcall(vim.cmd, 'MasonUpdate') end
      },
      {'williamboman/mason-lspconfig.nvim'},

      -- Autocompletado
      {'hrsh7th/nvim-cmp'},
      {'hrsh7th/cmp-buffer'},
      {'hrsh7th/cmp-path'},
      {'saadparwaiz1/cmp_luasnip'},
      {'hrsh7th/cmp-nvim-lsp'},
      {'hrsh7th/cmp-nvim-lua'},

      -- Snippets
      {'L3MON4D3/LuaSnip'},
      {'rafamadriz/friendly-snippets'},
    }
  }
end)

-- Declaramos el tema
vim.opt.termguicolors = true
pcall(vim.cmd, 'colorscheme onedark')

-- Configuración LSP
local lsp = require('lsp-zero').preset({
  name = 'minimal',
  set_lsp_keymaps = true,
  manage_nvim_cmp = true,
  suggest_lsp_servers = false,
})

lsp.nvim_workspace()

lsp.setup()
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:

Revisen este ejemplo de configuración más avanzado, aquí se muestran las funciones que tienen disponibles para configurar e instalar servidores LSP.

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 buymeacoffee ☕.

buy me a coffee

Top comments (7)

Collapse
 
vonheikemen profile image
Heiker • Edited

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

" Tab set to two spaces
set tabstop=2
set shiftwidth=2
set softtabstop=2
set expandtab

call plug#begin()
  " Colorscheme
  Plug 'joshdick/onedark.vim'

  " LSP Support
  Plug 'neovim/nvim-lspconfig'
  Plug 'williamboman/mason.nvim', {'do': ':MasonUpdate'}
  Plug 'williamboman/mason-lspconfig.nvim'

  " Autocompletion
  Plug 'hrsh7th/nvim-cmp'
  Plug 'hrsh7th/cmp-buffer'
  Plug 'hrsh7th/cmp-path'
  Plug 'saadparwaiz1/cmp_luasnip'
  Plug 'hrsh7th/cmp-nvim-lsp'
  Plug 'hrsh7th/cmp-nvim-lua'

  " Snippets
  Plug 'L3MON4D3/LuaSnip'
  Plug 'rafamadriz/friendly-snippets'

  " LSP Setup
  Plug 'VonHeikemen/lsp-zero.nvim', {'branch': 'v1.x'}
call plug#end()

try
  set signcolumn=yes
  set termguicolors
  colorscheme onedark
catch
  " do nothing
endtry

lua <<EOF
local lsp = require('lsp-zero').preset({
  name = 'minimal',
  set_lsp_keymaps = true,
  manage_nvim_cmp = true,
  suggest_lsp_servers = false,
})

lsp.setup()
EOF
Enter fullscreen mode Exit fullscreen mode
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.