Cómo migrar de vim-plug a lazy.nvim

Introducción

Ya vimos como convertir una una configuración en Vim script a Lua. Ese tipo de configuración es más flexible y reutilizaable. Ahora vamos por el paso final que es migrar de vim-plug a lazy.vim.

¿Qué es lazy.nvim?

Es un gestor de plugins escrito en Lua que sabe sacar provecho de la arquitectura moderna de Neovim.

¿Qué ventajas y funcionalidades tiene lazy.vim?

El gestor lazy.nvim se destaca por su rendimiento, usabilidad/UX y el modo de gestionar de plugins.

En la siguiente tabla vemos como se destaca en cuento a Rendimiento:

Funcionalidad/Ventaja ¿Qué significa?
Inicio ultra rápido Arranca en segundos porque los módulos se precompilan y se cachean automáticamente.
Instalaciones livianas Clona sólo lo esencial de los repos, ahorrando ancho de banda y espacio.
Plugins sin bloqueo del editor Tareas pesadas se ejecutan en segundo plano, manteniendo Neovim fluido.
Análisis de rendimiento Herramientas para medir tiempos de carga y optimizar tu configuración.
Carga bajo demanda (lazy-loading) Plugins se cargan solo cuando se necesitan, reduciendo carga inicial y memoria.
📝 ¿Qué y dónde cachea lazy.nvim?
Directorio Uso específico por lazy.nvim
~/.cache/nvim/luac/ Cache de bytecode Lua. Compila tu configuración en Lua a .luac, para que Neovim no tenga que interpretarla cada vez.
~/.local/share/nvim/lazy/ Instalación real de los plugins. Los plugins ya descargados no necesitan revalidarse ni reinstalarse.
~/.local/state/nvim/lazy/ Cache de estado: versiones exactas de los plugins, commits, fechas, hashes. Así lazy.nvim sabe si algo cambió.

¿Por qué migrar de vim-plug?

Los números duros

Tabla Comparativa de Repositorios lazy.vim vs vim-plug

La tabla de arriba muestra que

  • Si bien ambos son repositoorios populares, vim-plug (que es un proyecto más longevo) supera a lazy.nvim en este aspecto.
  • Ambos proyectos están activos.
  • El repo lazy.nvim tiene más colaboradores.

En este aspecto salen bastante empatados.

Aspectos ventajosos desde el punto de vista técnico

  • Para sysadmins: Rendimiento y carga mínima: se puede configurar de manera natural los plugins que realmente necesitás en tu entorno (por ejemplo, se pueden configurar plugins para que solamente se carguen al usar ssh) y una configuración más clara: todo en Lua, más fácil de mantener con backups dotfiles/scripts.
  • Para desarrolladores: Carga por filetype y herramientas específicas y mayor control sobre dependencias y versiones.
Funcionalidad vim-plug lazy.nvim Nota / Matiz
Gestión de plugins (install/update) Ambos permiten instalar, actualizar y remover plugins fácilmente
Lazy loading de plugins Sí (manual, limitado) Sí (declarativo y avanzado) vim-plug requiere configuración manual con on, for, cmd
Cache de estado (lockfiles, hashes) Parcial (:PlugSnapshot) Sí (lazy-lock.json) vim-plug permite snapshot, pero no lo gestiona ni lo aplica automáticamente
Cache de bytecode Lua (.luac) No lazy.nvim compila módulos Lua para acelerar el arranque
Arranque optimizado Parcial (con lazy manual) Sí (caching + carga bajo demanda) lazy.nvim acelera usando cache + lazy loading automático
Integración con configuración Lua No (Vimscript-first) Sí (nativo en Lua) vim-plug puede usarse con hacks en Lua, pero no está diseñado para eso

Conceptos fundamentales para usar lazy


1. Comentarios

-- Esto es un comentario

2. Variables

local nombre = "Neovim"
local numero = 14

3. Tablas (como diccionarios o listas)

local opciones = {
  number = true,
  relativenumber = true
}

4. Funciones

local function saludar()
  print("Hola desde Lua")
end

5. Requiriendo otros archivos (modularización)

require("usuario.options")
require("usuario.plugins.lazy")

Ejemplo concreto de migración

Usamos como punto de partida el archivo ~/.config/nvim/plugins.vim del post anterior:

Camino a lazy.nvim

"Plugins (Plug)
call plug#begin('~/.vim/plugged')

Plug 'itchyny/lightline.vim'
Plug 'nyngwang/NeoTerm.lua'
Plug 'NLKNguyen/papercolor-theme'

call plug#end()

lua << EOF                                                       
require("neo-term").setup {
  exclude_filetypes = { "oil" }
}                          
EOF

nnoremap <F4> :NeoTermToggle<CR>
tnoremap <F4> <C-\><C-n>:NeoTermToggle<CR>
tnoremap <Esc> <C-\><C-n>:NeoTermEnterNormal<CR>

Clonar el repo

git clone https://github.com/folke/lazy.nvim.git ~/.local/share/nvim/lazy/lazy.nvim

Prepara el entorno

Creamos un directorio para la configuración de los plugins y otro para la configuración de lazy.nvim:

mkdir ~/.config/nvim/lua/lplugins  # Aquí estarán los archivos de configuración de los plugins
mkdir ~/.config/nvim/lua/config/

Configuración inicial

Partimos de este archivo:

-- Cargamos módulos

local commands = require('utils.commands')
local extracommands = require('utils.extracommands')
local keymaps = require('keymaps')
local opciones = require('opciones')

-- Mantenemos por ahora la configuración de plugins en Vim script
vim.cmd('source ~/.config/nvim/plugins.vim')

Y hacemos las siguientes modificaciones:

-- Cargamos módulos

local commands = require('utils.commands')
local extracommands = require('utils.extracommands')
local keymaps = require('keymaps')
local opciones = require('opciones')

-- Mantenemos por ahora la configuración de plugins en Vim script
-- vim.cmd('source ~/.config/nvim/plugins.vim')
-- require("config.lazy")

¿Qué hicimos? Deshabilitar vim-plug y por ahora dejar comentada la línea que llamará al archivo ~/.config/nvim/lua/config/lazy.lua.

Luego en dicho archivo pondremos lo siguiente:

-- Bootstrap lazy.nvim
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not (vim.uv or vim.loop).fs_stat(lazypath) then
  local lazyrepo = "https://github.com/folke/lazy.nvim.git"
  local out = vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath })
  if vim.v.shell_error ~= 0 then
    vim.api.nvim_echo({
      { "Failed to clone lazy.nvim:\n", "ErrorMsg" },
      { out, "WarningMsg" },
      { "\nPress any key to exit..." },
    }, true, {})
    vim.fn.getchar()
    os.exit(1)
  end
end
vim.opt.rtp:prepend(lazypath)

-- Make sure to setup `mapleader` and `maplocalleader` before
-- loading lazy.nvim so that mappings are correct.
-- This is also a good place to setup other settings (vim.opt)
vim.g.mapleader = " "
vim.g.maplocalleader = "\\"

-- Setup lazy.nvim
require("lazy").setup({
  spec = {
    -- import your plugins
    { import = "lplugins" },
  },
  -- Configure any other settings here. See the documentation for more details.
  -- colorscheme that will be used when installing plugins.
  install = { colorscheme = { "habamax" } },
  -- automatically check for plugin updates
  checker = { enabled = true },
Explicación
require("lazy").setup({ ... })

Es la función principal que inicia y configura los plugins en lazy.nvim.

spec =

Es el campo que indica la especificación de los plugins. Es el lugar para definir qué plugins cargar.

spec = {
  { import = "lplugins.ui" },
}
  • Cada { import = "..." } carga los plugins definidos en otros archivos lua.
  • En este caso, usamoos una configuración modular:

  • ~/.config/nvim/lua/lplugins/ui.lua tendrá la especificación del plugin papercolor-theme.

  • ~/.config/nvim/lua/lplugins/terminal.lua tendrá las especificaciones de los plugins lightline y Neoterm.
install = { colorscheme = { "habamax" } }

Establece un esquema de colores que se aplicará automáticamente en la interfaz del gestor de plugins.

checker =

Activa el verificador automático de actualizaciones. Cabe aclarar que esta configuración no los no los actualiza automáticamente, pero te avisa para que los actualices mediante el comando en modo ex (:Lazy update).

En la configuración de partida teníamos solamente 3 plugins, pero decidimos dividirlos en dos categorías, a medida que vamos instalando más plugins podemos crear más archivos lua para clasificarlos.

Especificaciones de plugins

Todos los archivos donde clasificás plugins deben tener la keyword return para que cada uno de ellos debe devuelva una tabla Lua con los plugins que querés que lazy.nvim cargue desde esos archivos.

La siguiente es una plantilla de archivo en la cual se especifican plugins:

return {
  {
    "autor/repositorio",  --  Reemplazá con el nombre del autor y nombre del repositorio
    -- lazy = false,         --  true para carga diferida, false para cargar al inicio
    -- priority = 1000,      --  Opcional. Útil para temas de colores
    -- event = nil,          --  Reemplazá con evento si usás lazy = true (ej: "BufReadPre")
    -- cmd = nil,            --  Reemplazá si querés cargar al ejecutar un comando
    -- dependencies = {},    --  Lista de plugins que este necesita (si aplica)
    -- config = function()
      -- Poné acá la configuración del plugin
    -- end
  }
}

Para echar un poco de 💡 a esta cuestión de los campos:

Campo ¿Obligatorio? ¿Qué hace?
"autor/repositorio" Identifica el plugin (por ejemplo "NLKNguyen/papercolor-theme")
config = function() No, pero común Configura el plugin al cargarlo
lazy = true/false Opcional Define si se carga de forma diferida o al inicio
priority = número Opcional Da prioridad de carga (útil para temas de colores)
event = "InsertEnter" Opcional Carga el plugin al ocurrir cierto evento
cmd = "Comando" Opcional Carga el plugin cuando se ejecuta un comando
dependencies = {} Opcional Especifica otros plugins requeridos

Vamos a los ejemplos concretos 💪

Archivo ui.lua
return {

  {
    "NLKNguyen/papercolor-theme",
    priority = 1000,  -- para que se cargue antes que otros
    lazy = false,     -- para que se cargue en el arranque
    config = function()                                                                                                                                       
      vim.cmd("colorscheme PaperColor")
    end
  }
}

Esto significa:

» Devuelvo una lista (tabla) con un solo plugin. Este plugin es NLKNguyen/papercolor-theme y quiero que se cargue al inicio, con prioridad alta, y que cuando se cargue, aplique el esquema de colores PaperColor.

Archivo terminal.lua
return {
  { -- Plugin 1: lightline.vim
    "itchyny/lightline.vim",
    config = function()
      vim.g.lightline = {
        colorscheme = 'solarized', -- <- podés cambiar por "jellybeans","OldHope", "wombat", "PaperColor", etc.
      }
    end,
  }, -- Separador de items en la lista

  { -- Plugin 2: NeoTerm.lua
    "nyngwang/NeoTerm.lua",
    config = function()
      require("neo-term").setup {
        exclude_filetypes = { "oil" }, -- evita que se use en buffers del tipo "oil"
      }

      -- Atajos de teclado:
      vim.keymap.set("n", "<F4>", ":NeoTermToggle<CR>", { silent = true })              -- F4 en modo normal: alterna el terminal
      vim.keymap.set("t", "<F4>", "<C-\\><C-n>:NeoTermToggle<CR>", { silent = true })   -- F4 en modo terminal: lo mismo
      vim.keymap.set("t", "<Esc>", "<C-\\><C-n>:NeoTermEnterNormal<CR>", { silent = true }) -- Esc en terminal: pasa a modo normal
    end
  }, -- Separador final, no es obligatorio pero conveniente
}

Este archivo configura dos plugins:

  • lightline.vim: para una línea de estado personalizada.
  • NeoTerm.lua: para trabajar con terminales flotantes o integrados, y define atajos con F4 y Esc para manejarlos fácilmente.

Habilitar lazy.nvim

Ya estamos casi listos, solamente falta quitar el comentario en el archivo ~/.config/nvim/init.lua:

require("config.lazy")

Eso es todo, la próxima vez, al entrar al editor, lazy.nvim se encargará de instalar los plugins especificados.

Es importante ejecutar el comando :checkhealth lazy el cual hará un diagnóstico de la instalación y configuración:

checkhealth

Sacándole provecho a lazy.nvim

Vamos a instalar el plugin which-key el cual sirve para mostrar de una manera amigable los atajos de teclado configurados.

Editamos el archivo de configuración ~/.config/nvim/lua/lplugins/ui.luasiguiendo la plantilla mencionada anteriormente:

return {

  {
    "NLKNguyen/papercolor-theme",
    priority = 1000,  -- para que se cargue antes que otros
    lazy = false,     -- para que se cargue en el arranque
    config = function()                                                                                                                                       
      vim.cmd("colorscheme PaperColor")
    end,                  
  },                      

{                         
  "folke/which-key.nvim", 
  event = "VeryLazy",     
  opts = {},              
  keys = {
    { "<leader>ff", "<cmd>edit ~/.config/nvim/init.lua<cr>", desc = "Edit init.lua" },
    { "<leader>fr", "<cmd>e #<cr>", desc = "Open recent file" },
    { "<leader>tt", "<cmd>terminal<cr>", desc = "Open terminal" },
    { "<leader>?", function() require("which-key").show({ global = false }) end, desc = "Buffer Local Keymaps" },
    { "<leader>q", "<cmd>q<cr>", desc = "Quit" },
    { "<leader>w", "<cmd>w<cr>", desc = "Save" },
    -- Grupos visibles (aunque no hacen nada por sí mismos)
    { "<leader>f", name = "+file" },
    { "<leader>t", name = "+terminal" },
  },
}

}

Este plugin sirve para que al teclar:

  • Espacioff Abrirá el archivo /.config/nvim/init.lua.
  • Espaciofr Abrirá el archivo más reciente.

... y así con cada uno de los atajos definidos, pero además veremos una ayuda en pantalla.

Vamos a verlo en acción:

Ejemplo usando which-key

  • 1 Al presionar y ....
  • 2 Muestra que es Yank que en el contexto de Vi/Vim/Neovim es copiar...
  • 3 Aparecen automágicamente las teclas que pueden acompañar a este comando 💪

Y listo.... el resto es cuestión de usar la UI de Lazy, y familiarizarse con sus subcomandos en modo Ex.

Lazy UI

Conclusión

Old but even new and fresh

  • vim-plug sigue siendo una opción robusta y popular, especialmente para usuarios de Vim clásico o entornos donde se necesita algo probado y ampliamente documentado.

  • Sin embargo, lazy.nvim es una solución moderna y centrada en Neovim, con alta participación comunitaria y buena agilidad en el mantenimiento. Ideal para setups nuevos o si des#eas aprovechar la asincronía y mejoras de Lua en Neovim.

Siempre que puedas

  • Consultá el README oficial
  • Buscá ejemplos en GitHub o Dotfiles de otros usuarios
  • Explorá el código fuente si sabés Lua

Estos tres artículos no han servidor para comenzar a usar Neovim, modernizar la configuración y utilizar un gestor de plugins nativo en Lua. wSiempre que agregues un plugin, revisa su README y especifica las dependencias manualmente si no estás seguro. Lazy puede resolver muchas automáticamente, pero declararlas te da más control y claridad.

Detrás de la fachada antigua, Neovim es un editor que adaptó su arquitectura a los nuevos tiempos.

¡Felicitaciones si llegaste hasta acá?

Fuentes y más recursos

Comentarios

Comments powered by Disqus