LSP

Una de las características más notables que tiene Neovim es la posibilidad de utilizar LSPs (Protocólo de servidor de lenguaje), lo que permite que el editor pueda comunicarse con el servidor de lenguaje para ofrecerle:

Esto traducido en el lenguaje humano y natural es que el editor se comunica con el servidor LSP y proporciona al usuario las herramientas para que, cuando está picando código en X lenguaje, reciba la información de dicho lenguaje, como los errores y las advertencias que hay en el código. Dicha información se muestra en pantalla cuando hay un error de sintáxis, así rollo “texto en rojo comunicando el error”.

Neovim ya contaba con esta funcionalidad de serie hace tiempo. Pero con la llegada de la versión 0.11 de Neovim, ahora el usuario puede definir qué LSPs quiere cargar en Neovim sin tener que recurrir a plugins externos como el famoso nvim-lspconfig .

A partir de la versión 0.11 de Neovim, el uso de require(“lspconfig”) del plugin mencionado se considera deprecado.

Instalación y configuración de LSPs

Lo primero que tenemos que hacer es tener bien claro con qué lenguajes de programación vamos a trabajar.

En este enlace se recoge la configuración de los diferentes LSPs que puede manejar Neovim.

Una vez que ya tengamos claro los lenguajes, lo siguiente es instalar dichos LSPs en el sistema.

Dependiendo de si estás en Windows, Linux o MacOS, el método de instalación de los LSPs puede variar. En el caso de Linux, hay distribuciones que cuentan con algunos LSPs en sus repositorios. En caso contrario, había que instalar Node y NPM para instalar el LSP que necesites.

Para esta sección vamos a instalar los LSPs de Lua (lua-language-server) y de JavaScript/TypeScript (typescript-language-server).

Partimos en el supuesto de que ya están instalados los LSPs en el equipo. Ahora sólo hay que configurarlos para que Neovim los cargue.

Configurando los LSPs

Lo primero es crear el directorio “lsp” en el directorio raíz de la configuración de Neovim. Dentro de ese directorio se guardarán los archivos de configuración de cada LSP.

Vamos a empezar primero con el LSP de Lua. Creamos el archivo “lua_ls.lua” dentro de ese directorio y escribimos esto:

return {
    cmd = {"lua-language-server", "--stdio"},
    filetypes = {"lua"},
    root_markers = { {".luarc.json", ".luarc.jsonc"}, { ".git" }, { ".stylua.toml", "stylua.toml", "selene.toml" } },
    settings = {
        runtime = {
            version = "LuaJIT",
            path = {
                "lua/?.lua",
                "lua/?/init.lua",
            },
        },
        Lua = {
            codeLens = {
                enable = true
            },
            hint = {
                enable = true,
                semicolon = "Disable"
            }
        }
    }
}

Vamos a desmenuzar el contenido de este archivo.

Lo primero es que estamos devolviendo una tabla de Lua de la configuración del mismo LSP. Y dentro de dicha tabla se encuentran los siguientes campos:

Ahora vamos a repetir la operación pero con el LSP de JavaScript/TypeScript. Para ello creamos el archivo “ts_ls.lua” dentro del directorio lsp e introducimos esto:

return {
    cmd = {"typescript-language-server", "--stdio"},
    filetypes = {"javascript", "javascriptreact", "typescript", "typescriptreact" },
    root_markers = {{".git"}, {"package.json", "tsconfig.json", "jsconfig.json"}}
}

Pero aún no hemos acabado porque toca lo más importante, que es activar los LSPs e inyectar las capacidades del cliente LSP.

Vamos a crear el archivo “lsp.lua” dentro del directorio “lua” y vamos a meter este contenido:

-- Obtener las capacidades del cliente LSP
local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities.textDocument.completion.completionItem.snippetSupport = true

-- Habilita los LSPs
vim.lsp.enable({"lua_ls", "ts_ls"})

-- Inyecta las capacidades del cliente a todos los LSPs
vim.lsp.config('*', {
    capabilities = capabilities,
    root_markers = { '.git' },
})

Y ya por último añadimos esta línea al archivo “init.lua” para que cargue el archivo que hemos creado antes:

require("lsp")

Ahora vamos a cerrar Neovim. La próxima vez que abramos un archivo .lua o de JavaScript/TypeScript, el LSP ya debería estar funcionando.

Vamos a abrir un archivo de TypeScript para ver lo que pasa…

LSP funcionando

¡Bravo! ¡El LSP está funcionando muy bien! 👏👏👏

Y para comprobar que ha cargado muy bien el LSP, utilizaremos el comando :checkhealth vim.lsp.

Comprobación del funcionamiento de los LSP con :checkhealth

En la captura anterior se muestran los LSPs que están activados en el búfer actual, y qué configuraciones de LSP están activadas.

Al final Neovim carga todas las configuraciones del directorio lsp y lo junta todo como si fuese un único archivo.

Funciones de LSP a nivel de búfer

A continuación vamos a hacer un repaso de los métodos/funciones para interactuar con el LSP a nivel de búfer. Dichas funciones pertenecen a la clase vim.lsp.buf.*

FunciónDescripción
format()Formatea el documento/búfer actual
rename()Cambia el nombre de una variable o palabra clave
code_actions()Nos da a elegir diversas acciones que modifican el código
hover()Muestra la información referente al elemento en el que está situado el cursor

Algunos de los descritos son los más utilizados, pero hay más que se pueden consultar con el comando :h vim.lsp.buf. Además hay algunos LSPs que no disponen de esas funcionalidades avanzadas.

Nota sobre el autocompletado (u “omnicompletado”)

Neovim trae incluido un sistema de autocompletado, que nos permite elegir entre diferentes palabras clave, términos, entre otros.

Para el propósito del manejo de los LSPs para ver los métodos y definiciones, vamos a usar el “omnicompletado” nativo, que se consigue con las combinaciones CTRL + X y CTRL + O en el modo de inserción.

Autocompletado LSP nativo de Neovim

En el caso de la captura anterior se muestran los métodos de manejo de cadenas de JavaScript/TypeScript.

Pero en mi opinión, dicho autocompletado no muestra la documentación en relación a dicho método. Por lo que tenemos que tirar de plugins como nvim-cmp o blink.nvim. El paquete mini.nvim también tiene un módulo de autocompletado.

Autocompletado con el médulo de Mini.nvim

En la captura anterior se ha mostrado el módulo “completion” de mini.nvim, y dicho autocompletado muestra a la derecha del listado la información de los métodos, funciones y variables.

Conclusión

Ya hemos visto cómo se configura y se activan los LSPs en Neovim de forma nativa en la versión 0.12 de Neovim. Y todo eso sin necesidad de usar plugins de terceros.

Si quieres ir más allá sobre el manejo nativo del LSP, puedes echarle un ojo a la sección de LSP de la documentación oficial de Neovim .