649 - Cinco complementos para ser mas productivos con Neovim

649 - Cinco complementos para ser mas productivos con Neovim

#neovim es una herramienta espectacular con cientos de opciones. Te cuento cinco complementos para ser mas productivos y mejorar tu trabajo.

1:25
-3:15

Llevo un par de semanas intentando programar una extensión para GNOME Shell, y finalmente he tenido que abandonar. Lo que yo quería hacer, en un tiempo pasado, si que fue posible. Actualmente, podría ser, pero con una experiencia de usuario mas que dudosa, y esto, finalmente, y contra mi espíritu, he tenido que dejarlo. Sin embargo, he estado disfrutando enormemente en el proceso, gracias a la fantástica integración que tiene Neovim con TypeScript. Y es que, actualmente, y por lo menos en mi caso, la experiencia de desarrollo que actualmente tengo con Neovim, no la tengo con ninguna otra herramienta. Aunque, la configuración tiene mas peligro que un caramelo en la puerta de un colegio. El mundo de los complementos de Neovim es una auténtica locura, y si no andas con cuidado, te puede suceder lo que a Alicia en el país de las maravilla. En este episodio te quiero hablar de cinco complementos para Neovim, que me están ayudando a ser mas productivo. Algunos de estos complementos los llevo utilizando ya años y otros se acaban de incorporar, reemplazando a otros.

Cinco complementos para ser mas productivos con Neovim

La madriguera del conejo

… de repente un conejo blanco de ojos rosas pasó corriendo junto a ella.
No era algo tan extraordinario, y a Alicia no le resultó muy extravagante que el conejo se dijera a sí mismo:

  • ¡Cielos! ¡Cielos! ¡Llegaré tarde!
    Al pensar después en ello, se le ocurrió que debería haberle sorprendido, pero en ese momento lo encontró de los más natural. No obstante, cuando el conejo se sacó un reloj del bolsillo del chaleco para echarle una ojeada y salir disparado, Alicia se puso de pie al momento, porque se dio cuenta de que nunca había visto un conejo con chaleco, ni bolsillos, ni reloj, y, ardiendo de curiosidad se puso a perseguir al conejo por la pradera y pudo apenas ver como se metía en una gran madriguera bajo el seto.
    Al cabo de un instante Alicia iba tras él, sin reflexionar siquiera en como podría salir de ahí.

Capítulo 1. Por la madriguera del conejo. Alicia en el país de las maravillas. Lewis Carroll.

Solo unos pocos encuentran el camino, otros no lo reconocen cuando lo encuentran, otros ni siquiera quieren encontrarlo.

Como Alicia, entrar en el mundo de los complementos de Neovim, es entrar en esa gran madriguera bajo el seto. ¿Como hacerlo sin perderse?. La verdad es que es complicado.

Simplemente ponte a trabajar con Neovim. Cuando necesites una funcionalidad, primero investiga si se puede hacer directamente con Neovim sin necesidad de utilizar un complemento. En segundo lugar busca entre los complementos mas utilizados aquel que de esa funcionalidad que buscas. Y por último personaliza ese complemento para que se ajuste a tus necesidades.

Indicarte que cada día aparecen nuevos complementos, con lo que es posible que hoy selecciones uno, pero dentro de unas semanas o meses lo reemplaces por otro.

Dicho esto te quiero hablar de cinco complementos que estoy utilizando últimamente y que me están ayudando a ser mas productivo utilizando Neovim.

Indicar que las instrucciones que indicaré en los siguientes apartados para la instalación de los distintos complementos se refieren a Lazy, que es el gestor de complementos que utilizo.

conform

Posiblemente la culpa de mi obsesión sea de Python, pero lo cierto es que necesito el código formateado. Un código formateado es bello por definición propia. Así que, en muchas ocasiones me encontraba reformateando el código. Pero esto fue hasta que dí con conform. Este complemento para Neovim se define así mismo como un formateador ligero pero potente para Neovim.

Alguna de las características de conform son las siguientes,

  • Preserva marcas y pliegues. La mayoría de los formateadores reemplazan todo el búfer, lo que elimina marcas y pliegues, y puede causar movimientos inesperados en la vista o el cursor. conform calcula diferencias mínimas y las aplica utilizando las utilidades de formato integradas en LSP.
  • Corrige formateadores LSP mal implementados. Algunos servidores LSP son poco rigurosos y simplemente reemplazan todo el búfer, provocando los problemas mencionados anteriormente. conform se conecta al manejador de LSP y convierte estas respuestas en cambios correctos por secciones.
  • Habilita el formato por rangos para todos los formateadores. Como conform calcula diferencias mínimas, puede realizar formato por rangos incluso si el formateador subyacente no lo soporta.
  • API simple. conform ofrece una API simple e imperativa, modelada a partir de vim.lsp.buf.format().
  • Formatea bloques de código incrustados. Puede formatear bloques de código dentro de archivos Markdown o similares (consulta el formato de lenguajes incrustados).

Instalación y configuración

La configuración que tengo implementada en mis equipos es la siguiente,

{
    'stevearc/conform.nvim',
    opts = {
        lua = { "stylua" },
        -- Conform will run multiple formatters sequentially
        python = { "isort", "black" },
        -- Use a sub-list to run only the first available formatter
        javascript = { { "prettierd", "prettier" } },
        markdown = { { "prettierd", "prettier" } },
        typescript = { "eslint_d" },
        sh = { "shfmt" },
        bash = { "shfmt" },
    },
    config = function()
        vim.api.nvim_create_user_command("Reformat", function(args)
            local range = nil
            if args.count ~= -1 then
                local end_line = vim.api.nvim_buf_get_lines(0, args.line2 - 1, args.line2, true)[1]
                range = {
                    start = { args.line1, 0 },
                    ["end"] = { args.line2, end_line:len() },
                }
            end
            require("conform").format({ async = true, lsp_fallback = true, range = range })
        end, { range = true })
    end
}

En mi caso, no tengo ningún atajo de teclado asignado, aunque debería. Cuando necesito reformatear un código, simplemente utilizo :Reformat y listo.

telescope

El siguiente de los complementos es ya todo un clásico. Sin embargo, tiene tantas opciones y posibilidades que prácticamente es imposible acabárselo. La cuestión, es que algo que haces muy a menudo es buscar. El objetivo es abrir un archivo, en base a su contenido a su título a lo que sea, aquí es donde entra telescope.

Si no conoces telescope indicarte que se trata de un buscador, implementado con lógica difusa, y que es extensible. Básicamente se trata de un complemento que te ayuda a buscar casi cualquier cosa que puedas imaginar.

Y por supuesto que telescope es, por si solo, otra madriguera de conejo. Aquí puedes elegir entre diferentes pickers, sorters y previewers. Un auténtico infierno. Por que no solo tienes los que están implementados por los propios desarrolladores de Telescope. También tienes los de la comunidad… Así que ya te puedes imaginar. Y no solo es esto, es que además te tienes que acordar de todos los que tienes disponibles.

Por ejemplo, tienes pickers para,

  • archivos. Encontrar archivos en base a su nombre o a su contenido.
  • vim. Puedes encontrar buffers, commandos, etc.
  • neovim. Puedes buscar todo lo referente a lsp.
  • git. Todo lo refernte a git, desde ramas a commits.

Por otro lado, tienes los previewers. Aquí tienes otro mundo,

  • archivos. Te permite ver el contenido utilizando cat o bat.
  • imágenes. Igual que el anterior pero para imágenes y utilizando chafa.

Y por último tienes los sorters. Existen diferentes, desde algunos para organizar los archivos como cualquier otra cosa.

Instalación y configuración

En este caso la configuración que tengo definida es ligeramente mas compleja tal y como puedes ver a continuación,

return {
    "nvim-telescope/telescope.nvim",
    event = "VeryLazy",
    dependencies = {
        "nvim-telescope/telescope-live-grep-args.nvim",
        "nvim-telescope/telescope-symbols.nvim",
        "nvim-telescope/telescope-file-browser.nvim",
        "nvim-telescope/telescope-dap.nvim",
        "olacin/telescope-gitmoji.nvim",
        "xiyaowong/telescope-emoji.nvim",
        "LinArcX/telescope-command-palette.nvim",
        "nvim-telescope/telescope-fzy-native.nvim",
        "nvim-telescope/telescope-media-files.nvim",
        "nvim-telescope/telescope-ui-select.nvim",
    },
    config = function()
        local lga_actions = require("telescope-live-grep-args.actions")
        require('telescope').setup {
            defaults = {
                file_ignore_patterns = { "node_modules/.*", ".git/.*", "dist/.*", ".yarn/.*", ".docker-volumes/.*" },
                dynamic_preview_title = true,
                path_display = { "truncate" },
            },
            pickers = {},
            extensions = {
                ["ui-select"] = {
                    require("telescope.themes").get_dropdown({})
                },
                media_files = {
                    filetypes = { "png", "jpg", "mp4", "webm", "pdf" },
                    find_cmd = "rg",
                },
                workspaces = {
                    keep_insert = true,
                },
                live_grep_args = {
                    auto_quoting = true,
                    mappings = {
                        i = {
                            ["<C-k>"] = lga_actions.quote_prompt(),
                            ["<C-i>"] = lga_actions.quote_prompt({ postfix = " --iglob " }),
                        },
                    },
                },
                gitmoji = {
                    action = function(entry)
                        vim.ui.input({ prompt = "Enter commit message: " .. emoji .. " " }, function(msg)
                            if not msg then
                                return
                            end
                            local emoji_text = entry.value.text
                            vim.cmd(':G commit -m "' .. emoji_text .. ' ' .. msg .. '"')
                        end)
                    end,
                },
                command_palette = {
                    { "File",
                        { "entire selection (C-a)",  ':call feedkeys("GVgg")' },
                        { "save current file (C-s)", ':w' },
                        { "save all files (C-A-s)",  ':wa' },
                        { "quit (C-q)",              ':qa' },
                        { "file browser (C-i)",      ":lua require'telescope'.extensions.file_browser.file_browser()", 1 },
                        { "search word (A-w)",       ":lua require('telescope.builtin').live_grep()",                  1 },
                        { "git files (A-f)",         ":lua require('telescope.builtin').git_files()",                  1 },
                        { "files (C-f)",             ":lua require('telescope.builtin').find_files()",                 1 },
                    },
                    { "Help",
                        { "tips",            ":help tips" },
                        { "cheatsheet",      ":help index" },
                        { "tutorial",        ":help tutor" },
                        { "summary",         ":help summary" },
                        { "quick reference", ":help quickref" },
                        { "search help(F1)", ":lua require('telescope.builtin').help_tags()", 1 },
                    },
                    { "Code",
                        { "Preview markdown", ":Glow" },
                        { "Reformat code",    ":Reformat" }
                    },
                    { "Vim",
                        { "reload vimrc",              ":source $MYVIMRC" },
                        { 'check health',              ":checkhealth" },
                        { "jumps (Alt-j)",             ":lua require('telescope.builtin').jumplist()" },
                        { "commands",                  ":lua require('telescope.builtin').commands()" },
                        { "command history",           ":lua require('telescope.builtin').command_history()" },
                        { "registers (A-e)",           ":lua require('telescope.builtin').registers()" },
                        { "colorshceme",               ":lua require('telescope.builtin').colorscheme()",    1 },
                        { "vim options",               ":lua require('telescope.builtin').vim_options()" },
                        { "keymaps",                   ":lua require('telescope.builtin').keymaps()" },
                        { "buffers",                   ":Telescope buffers" },
                        { "search history (C-h)",      ":lua require('telescope.builtin').search_history()" },
                        { "paste mode",                ':set paste!' },
                        { 'cursor line',               ':set cursorline!' },
                        { 'cursor column',             ':set cursorcolumn!' },
                        { "spell checker",             ':set spell!' },
                        { "relative number",           ':set relativenumber!' },
                        { "search highlighting (F12)", ':set hlsearch!' },
                    }
                },
            }
        }
        require("telescope").load_extension("file_browser")
        require("telescope").load_extension("media_files")
        require("telescope").load_extension("fzy_native")
        require("telescope").load_extension("gitmoji")
        require("telescope").load_extension("emoji")
        require("telescope").load_extension("command_palette")
        require("telescope").load_extension("ui-select")
    end,
}

barbar

Como pensamos que somos seres multitarea no solemos tener abierto un único archivo. Mas bien todo lo contrario. Por regla general tenemos abiertos varios archivos. Esto pasa casi igual que con las pestañas en tu navegador de referencia. En ocasiones he visto en un navegador tantas pestañas abiertas de forma simultánea que es imposible contarlas.

Hasta la hace muy poco estaba utilizando cokeline para gestionar los diferentes buffer que tenía abiertos, pero barbar ha venido a sustituirlo. Y es que con mucha menos configuración tengo una barra de pestañas con todos los buffer.

Barbar.nvim es un plugin que añade una barra de pestañas que permite pestañas reordenables, de tamaño automático, clicables, con iconos, comandos para ordenar y un modo mágico para saltar entre buffers. Además, los nombres de las pestañas se vuelven únicos cuando hay coincidencia entre nombres de archivos.

En el modo de BufferPick, las pestañas muestran una letra objetivo en lugar de su icono. Salta a cualquier buffer simplemente escribiendo su letra objetivo. Mejor aún, la letra objetivo permanece constante mientras el buffer exista, por lo que si trabajas con un conjunto de archivos, incluso puedes escribir la letra de memoria por adelantado.

Instalación y configuración

En este caso la configuración es realmente sencilla,

{
    {
        'romgrk/barbar.nvim',
        dependencies = {
            'lewis6991/gitsigns.nvim',
            'nvim-tree/nvim-web-devicons',
        },
        init = function() vim.g.barbar_auto_setup = false end,
        opts = {
            sidebar_filetypes = {
                ['neo-tree'] = { event = 'BufWipeout' }
            },
        },
    },
}

En este caso la única opción interesante es la de neo-tree, que me permite mantener a la izquierda el panel lateral correspondiente al árbol de directorio.

Sin embargo, te tengo que decir que tiene muchas posibilidades de configuración, desde animaciones hasta la posibilidad de selecciona en función del tipo de archivo. Igualmente, en cada uno de las pestañas puedes ver información relativa a si hay cambios en git, o si hay errores, o muchos detalles que lo hacen realmente interesante, y te diría que hasta imprescindible.

Desde luego, para poder moverte con comodidad entre los distintos buffer que tengas abiertos es una herramienta que te va a hacer la vida mas fácil.

Atajos de teclado

En mi caso, he modificado algunos atajos de teclado para hacerme la vida mucho mas sencilla. Así, por ejemplo he asignado Alt + <número> para cambiar fácilmente a las pestañas de la 0 a la 9.

De la misma manera he creado los atajos de teclado Alt+p para utilizar el picker y Alt+c para cerrar una determinada pestaña.

neovim-project

Este es uno de los complementos que te hablaba en la introducción del episodio que acabo de incorporar a mi caja de herramientas de complementos de Neovim.

El plugin Neovim project simplifica la gestión de proyectos al mantener un historial de proyectos y proporcionar acceso rápido a sesiones guardadas mediante Telescope o fzf-lua. Funciona sobre el Neovim Session Manager, que es necesario para almacenar todas las pestañas y buffers abiertos de cada proyecto.

  • Comienza donde lo dejaste la última vez.
  • Cambia de un proyecto a otro en segundos.
    _ Las sesiones e historial pueden sincronizarse entre tus dispositivos (usando rsync, Syncthing, Nextcloud, Dropbox, etc.).
  • Encuentra todos tus proyectos mediante patrones glob definidos en la configuración.
  • Guarda automáticamente los directorios expandidos en neo-tree.nvim y el orden de los buffers en barbar.nvim.
  • Elige tu selector favorito.

Para hacer esto utiliza una serie de comandos que son los que te facilitan este trabajo. Así tienes lo siguiente,

Por supuesto, aquí tienes la traducción:

  • :NeovimProjectDiscover – encuentra un proyecto basado en patrones.
  • :NeovimProjectHistory – selecciona un proyecto de tu historial reciente.
  • :NeovimProjectLoadRecent – abre la sesión anterior.
  • :NeovimProjectLoadHist – abre un proyecto del historial proporcionando un directorio del proyecto.
  • :NeovimProjectLoad – abre un proyecto de entre todos tus proyectos proporcionando un directorio del proyecto.

Instalación y configuración

En mi caso la instalación y configuración es la siguiente, pero como verás en las primeras líneas, tu lo vas a tener que configurar por necesidad,

{
    "coffebar/neovim-project",
    opts = {
        projects = { -- define project roots
            "/data/projects/*",
            "/data/typescript/*",
            "/data/rust/*",
            "/data/python/*",
            "/data/vaults/*"
        },
        picker = {
            type = "telescope", -- or "fzf-lua"
        }
    },
    init = function()
        -- enable saving the state of plugins in the session
        vim.opt.sessionoptions:append("globals") -- save global variables that start with an uppercase letter and contain at least one lowercase letter.
    end,
    dependencies = {
        { "nvim-lua/plenary.nvim" },
        -- optional picker
        { "nvim-telescope/telescope.nvim", tag = "0.1.4" },
        -- optional picker
        { "Shatur/neovim-session-manager" },
    },
    lazy = false,
    priority = 100,
}

Un detalle

Hasta el momento no he sido mucho de utilizar este tipo de complementos, porque me parecía que no eran necesarios. Sin embargo, en los últimos tiempos me estoy gandulizando, o acomodando, como lo quieras decir.

Como te decía, este es un complemento que es de reciente incorporación pero que ya me ha dado muchas satisfacciones. Me permite ser mas productivo porque puedo continuar por donde lo había dejado, y por tanto ahorra mucho tiempo.

transfer

Este es el último de los complementos de los que quería hablarte. Sin embargo, es algo al que le tengo mucha fe, y que puede que en un momento determinado llegue a reemplazar por completo a Obsidian. O casi.

Se trata de un sencillo complemento que lo que te permite es sincronizar archivos con un servidor remoto utilizando rsync y ssh. La gracia de este complemento es que te permite mapear entre rutas locales y remotas, a la vez que excluir determinadas rutas.

Los comandos disponibles son los siguientes,

  • TransferInit – crea un archivo de configuración y lo abre. Si ya existe, simplemente te permite editarlo.
  • DiffRemote – abre una vista de diferencias con el archivo remoto.
  • TransferRepeat – repite el último comando de transferencia (excepto TransferInit y DiffRemote).
  • TransferUpload [ruta] – sube el archivo o directorio especificado.
  • TransferDownload [ruta] – descarga el archivo o directorio especificado.
  • TransferDirDiff [ruta] – compara el directorio con el remoto y muestra los archivos modificados en la lista de quickfix.

Instalación y configuración

La instalación es tremendamente sencilla,

return {
    "coffebar/transfer.nvim",
    lazy = true,
    cmd = { "TransferInit", "DiffRemote", "TransferUpload", "TransferDownload", "TransferDirDiff", "TransferRepeat" },
    opts = {},
}

Una observación

Para que esto funcione correctamente tienes que estar en un directorio un nivel por encima. Por ejemplo, en mi caso, mis notas están en /data/vaults/obsidian/. Pues bien, para que funcione correctamente yo me tengo que situar en /data/vaults/. Esto no me termina de gustar, pero, que le vamos a hacer. Supongo que tendré que escribir al desarrollador.

Iosevka

Después de bastantes años utilizando FiraCode como tipografía por defecto, finalmente he cambiado a otra que ya he probado en alguna ocasión, y que comenté recientemente en un episodio anterior en el que te hablaba de Obsidan, y donde la he adoptado también. Y lo cierto es que la estoy utilizando tanto para escribir texto como para código, ambas en su versión Nerd, por supuesto. Que además me ha permitido resolver un problema que tenía con los caracteres japoneses.

Iosevka es una familia tipográfica de código abierto, sans-serif + slab-serif, monoespaciada + casi proporcional, diseñada para escribir código, usar en terminales y preparar documentos técnicos. La verdad, y tal y como contaba en ese episodio, no estaba muy conforme con esta tipografía, pero en el momento en que me he acostumbrado, la verdad es que me encanta.


Más información,

1 comentario en “Cinco complementos para ser mas productivos con Neovim

  1. SE
    selairi@gmail.com hace 2 días

    Un plugin que me gusta bastante es quickui localizable en:
    https://github.com/skywind3000/vim-quickui
    Genera un menú tipo Borland C que es muy práctico, pues no tengo buena memoria para los comandos.
    BufferGator también lo uso para cambiar rápidamente entre buffers.
    Por supuesto, cualquier plugin para manejar plantillas de código como snipmate.
    Un saludo

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *