Neovim: de noob a DIOS
No vas a memorizar teclas: vas a aprender un lenguaje de edición. Pocas reglas que generan miles de comandos, edición a la velocidad del pensamiento.
No vas a memorizar teclas. Vas a aprender un lenguaje de edición: pocas reglas que generan miles de comandos. La meta no es teclear rápido, es que la distancia entre lo que quieres hacer y lo que tecleas sea cero.
A lo largo de la guía las teclas van con color según su rol: operador (verbo), motion (movimiento), text-object (estructura), count (número), registro y insert.
Nivel 0 · El terreno: por qué existe la edición modal
NOOBLa cadena histórica explica el diseño. Cada eslabón heredó las ideas del anterior, y : todavía te mete en el editor de líneas subyacente.
flowchart LR ed["ed · 1969<br/>Ken Thompson<br/>editor de líneas"] --> ex["ex<br/>Bill Joy + Haley<br/>editor extendido"] ex --> vi["vi · 1979<br/>modo visual de ex<br/>pantalla completa"] vi --> vim["Vim · 1991<br/>Bram Moolenaar<br/>undo, scripts"] vim --> nvim["Neovim · 2014<br/>Lua, async<br/>LSP, treesitter"]
Bill Joy escribió vi en una terminal ADM-3A sobre un módem de 300 baudios. Por
eso hjkl mueven el cursor
(las flechas estaban pintadas ahí) y Esc estaba donde hoy tienes Tab.
Saberlo importa: cuando entiendes que : abre el editor de líneas de
ex, los comandos de dos puntos dejan de ser magia.
Nivel 1 · Los modos y cómo moverte entre ellos
NOOB| Modo | Para qué | Cómo entras |
|---|---|---|
| NORMAL | Reposo. Comandos, operadores, motions. | Esc · <C-[> |
| INSERT | Insertar texto. | i I a A o O |
| VISUAL | Selección: char (v), línea (V), bloque (<C-v>). | v V <C-v> |
| COMMAND-LINE | Comandos Ex, búsqueda, filtros. | : / ? ! |
| OPERATOR-PENDING | Estado efímero tras un operador, esperando motion/objeto. | tras d c y… |
| TERMINAL | Emulador de terminal dentro de un buffer. | :terminal |
| Entrar a Insert | Dónde queda el cursor |
|---|---|
| i / a | antes / después del cursor |
| I / A | primer no-blanco / fin de línea |
| o / O | línea nueva abajo / arriba |
| gi | donde paraste de insertar la última vez |
Salir de Insert: Esc, <C-[> (idéntico, más cómodo) o <C-c>. Para reemplazar un solo carácter sin cambiar de modo: rchar. Para sobrescribir continuo: R.
Nivel 2 · Navegación dentro del archivo
NOOB| Motion | Qué hace |
|---|---|
| w W | inicio de la siguiente word / WORD (separada por espacios) |
| b e | inicio anterior / fin de la palabra |
| 0 ^ $ | columna 0 / primer no-blanco / fin de línea |
| fx tx | salta a / justo antes del carácter x — ; repite, , invierte |
| { } | párrafo anterior / siguiente |
| % | salta al paréntesis/llave/corchete pareja |
| gg G nG | inicio / fin del archivo / línea n |
| H M L | top / middle / bottom de la pantalla |
| <C-d> <C-u> | media pantalla abajo / arriba |
| zz zt zb | recentra cursor al medio / arriba / abajo |
Nivel 3 · La gramática: operador + motion + count
PROLa fórmula completa es:
[count] operador [count] {motion | text-object}
3 d w → borra 3 palabras
c i" → cambia lo que hay entre comillas
2 > j → indenta 2 líneas hacia abajo
| Operador | Verbo |
|---|---|
| d c y | borrar / cambiar (borra + Insert) / copiar (yank) |
| > < = | indentar / desindentar / reindentar (auto) |
| gu gU g~ | minúscula / mayúscula / alternar caso |
| gq gc | reformatear a textwidth / comentar (Neovim 0.10+) |
Reglas que cambian todo
- Doblar el operador → opera la línea entera: dd yy >> cc
- Los counts se multiplican: 2d3w borra 6 palabras
- Tras operar, el cursor queda al inicio del texto operado
¿Por qué dw ≠ de?
Los motions tienen tipo. w es exclusive (no borra el carácter destino); e es inclusive (sí lo borra). Puedes forzar el tipo tras el operador: v charwise, V linewise, <C-v> blockwise.
Nivel 4 · Text objects: “inner” vs “around”
PROLa regla i / a
i = inner: solo el contenido, sin delimitadores. · a = around: incluye delimitadores o espacio.
Regla de Drew Neil: usa a para borrar (te llevas el delimitador) e i para cambiar (dejas los delimitadores intactos).
| Objeto | inner / around | Caso de uso |
|---|---|---|
| palabra | iw aw | ciw renombra un identificador entero |
| comillas | i” a” | ci” cambia un valor de atributo / string |
| paréntesis | i( a( | ci( cambia argumentos de función |
| llaves | i{ a{ | ci{ cambia el cuerpo de función (C/Rust/Swift) |
| corchetes | i[ a[ | di[ vacía un índice/array |
| etiqueta HTML | it at | cit cambia contenido de div · dat borra la etiqueta entera |
| párrafo | ip ap | dap borra el bloque |
Nivel 5 · Repetición: el dot-command y el diseño repetible
PROflowchart LR A["A…Esc<br/>añade ; al final"] --> B["j<br/>baja una línea"] B --> C[".<br/>repite el cambio"] C --> D["j<br/>baja"] D --> E[".<br/>repite"]
A (no $a) es la clave: compone $a en una tecla, así el cursor puede estar en cualquier parte de la línea y el dot sigue funcionando. Cada comando compuesto regala pulsaciones al dot:
| Atajo | Equivale a |
|---|---|
| A I | $a / ^i |
| C D S s | c$ / d$ / cc / cl |
| o O | nueva línea abajo / arriba en Insert |
El combo asesino: cgn
Busca con /patrón (o * sobre la palabra bajo el cursor). Luego cgntextoEsc cambia la siguiente coincidencia. A partir de ahí, solo . . . va cambiando una a una — tú decides cuáles saltándolas con n. Es renombrar con control total, sin plugins.
Nivel 6 · Registros: el portapapeles múltiple
PRO| Registro | Qué guarda |
|---|---|
| ” unnamed | el por defecto. Todo d/c/s/x/y lo actualiza |
| ”0 yank | solo el último yank — no se pisa con borrados. Truco oro: “0p pega lo último copiado aunque hayas borrado después |
| ”1–“9 | historial de borrados de ≥1 línea (1 = más reciente) |
| “a–“z | los controlas tú. “A (mayúscula) = append sin pisar |
| ”_ black hole | el /dev/null. “_dd borra sin contaminar lo copiado |
| ”+ “* | portapapeles del sistema / selección X11 |
| ”= expression | evalúa: en Insert <C-r>=2+2 inserta 4 |
| ”% ”. “/ | solo-lectura: nombre de archivo / último texto insertado / último patrón |
El problema clásico
“Copio una palabra, borro otra para reemplazarla, y al pegar sale lo borrado.” Tres soluciones: (a) pega con “0p (registro yank), (b) borra con black hole “_d y luego p, o (c) en Visual selecciona y p (pegar sobre selección).
En Insert: <C-r>a inserta el registro a · <C-r>0 el yank · <C-r>% el nombre de archivo. Ver todos: :reg.
Nivel 7 · Marks, jumplist y changelist
PRO| Comando | Qué hace |
|---|---|
| ma-z / mA-Z | marca local al buffer / global (entre archivos) |
| `x / ‘x | salta a la posición exacta / al inicio de esa línea |
| “ | posición previa al último salto |
.</Kbd> <Kbd mo>^ | último cambio / última posición de Insert |
{'<'}</Kbd> <Kbd mo>> | inicio/fin de la última selección visual (por eso aparece '<,'> en rangos) |
| <C-o> <C-i> | jumplist: retrocede / avanza por saltos grandes (entre archivos) |
| g; g, | changelist: retrocede / avanza por cambios |
| <C-^> | alterna con el archivo anterior (header↔impl, comp↔test) |
¿Qué cuenta como "salto"?
G, /, n, %, { }, saltos a marks y tags sí entran al jumplist. Pero j/k/4j no — mientras que 42G sí. Cada ventana tiene su propio jumplist. Lista: :jumps.
Nivel 8 · Búsqueda, sustitución y regex de Vim
PRO| Búsqueda | |
|---|---|
| /foo ?foo | buscar adelante / atrás · n repite, N invierte |
| * # | palabra bajo cursor adelante / atrás |
| /foo/e | search offset: deja el cursor al final del match |
| :noh | limpia el resaltado |
Sustitución :s
La forma general:
:[rango]s/patrón/reemplazo/[flags]Flags: g todas de la línea · c confirmar · i ignora caso · n solo contar.
Rangos: % todo · .,$ de aquí al final · '<,'> selección visual · 5,10 líneas 5-10.
En el reemplazo: \1…\9 grupos · & todo el match · \u \U caso · \r salto de línea (¡no \n!) · \= evalúa Vimscript.
| Magic / regex | |
|---|---|
| \v very magic | ( ) | + ? funcionan como PCRE. Recomendado. |
| \zs \ze | marcan inicio/fin real del match: foo\zsbar matchea solo “bar” precedido de “foo”. Más simple que lookaround |
| %V | restringe el match al área seleccionada |
| _. | el prefijo \_ hace que un átomo también matchee fin de línea (multilínea) |
Ejemplos:
:%s/\v(\w+)\s+(\w+)/\2 \1/ " intercambia dos palabras
:%s/foo//gn " cuenta ocurrencias
:%s/\d\+/\=submatch(0)+1/ " incrementa cada número
Nivel 9 · Ex commands, :g, :normal y macros
DIOSRangos y manipulación de líneas
| % . $ | todo / línea actual / última · combinables: .,$ 'a,'b |
| :mdir | mover líneas: :m0 al inicio, :m$ al final |
| :t / :co | copiar líneas: :t. duplica la actual, :3,5t10 |
| :j :sort | unir / ordenar líneas |
:g — el martillo neumático
Forma: :[rango]g/patrón/comando. Dos pasadas: marca las líneas que matchean,
luego ejecuta el comando Ex en cada una. :v (= :g!)
actúa sobre las que NO matchean.
:g/console/d " borra todas las líneas con "console"
:v/foo/d " borra todo lo que NO contenga "foo"
:g/^$/d " borra líneas vacías
:g/TODO/t$ " copia todas las líneas TODO al final
:g/error/y A " acumula en el registro a (mayúscula = append):normal — el puente a modo Normal
Ejecuta comandos de modo Normal desde la command-line, acepta rango. Usa
:normal! para ignorar tus mappings.
:%normal A; " añade ; al final de TODAS las líneas
:'<,'>normal I// " comenta la selección
:g/console/normal A; " :g + :normal → ; solo en líneas con "console"Macros — grabar acciones arbitrarias
| qa … q | graba en el registro a · qA añade al final |
| @a @@ 5@a | ejecuta a · repite el último · 5 veces · 99@a “hasta fallar” |
:g/patrón/normal @a | el mejor patrón: aplica el macro a cada línea que matchea |
Un macro ES un registro de texto: lo ves con :reg a, lo editas en una línea y lo recargas. Recursivo: vacía con qaq, graba acciones + llamada a sí mismo @a, termina con q; se autodetiene cuando un motion falla (p. ej. j al final).
Nivel 10 · Buffers, ventanas y tabs: el modelo correcto
PROflowchart TB B1["buffer<br/>main.rs"] --> W1["window 1"] B2["buffer<br/>lib.rs"] --> W2["window 2"] W1 --> T["TAB<br/>layout de ventanas"] W2 --> T B3["buffer cargo.toml<br/>cargado, sin ventana"]
Buffers (los archivos cargados)
- Abrir un archivo = cargar un buffer en memoria
- :ls lista los buffers · :b nombre<Tab> salta a uno
- :bn / :bp siguiente / anterior · <C-^> alterna con el último
- :bd descarga un buffer (cerrar la ventana NO lo borra)
Windows (vistas sobre buffers)
- :sp / :vs divide horizontal / vertical
- <C-w>hjkl salta entre ventanas · <C-w>w cicla
- <C-w>c cierra · <C-w>o deja solo la actual · <C-w>= iguala
- <C-w>HJKL recoloca · <C-w>+ / <C-w>- redimensiona
Tabs = espacios de trabajo, NO pestañas de archivos
:tabnew crea una · gt/gT siguiente/anterior · <C-w>T manda la ventana actual a una tab nueva. Úsalas como layouts distintos (código / tests / debug), no como “un archivo por pestaña” — para eso ya tienes los buffers.
El error clásico de quien viene de VS Code
Crees que cada pestaña = un archivo. En Neovim los “archivos abiertos” son buffers (una pila invisible que ves con :ls); las tabs son solo layouts. Por eso :q a veces parece “cerrar el archivo” pero en realidad cierra la ventana: el buffer sigue cargado.
Nivel 11 · El flujo real: el sistema de archivos con mindset Neovim
PROEl corazón: buscar, no navegar
- Telescope find_files (<leader>ff): teclea 3-4 letras del nombre y saltas. Reemplaza el 90% del navegar carpetas
- Telescope live_grep (<leader>fg): busca por contenido en todo el proyecto
- Picker de buffers para lo que ya tienes abierto
Los tres exploradores de archivos
| Opción | Qué es / cuándo |
|---|---|
| netrw (integrado) | El explorador integrado (0 instalación). Su poder extra es editar archivos remotos por scp/sftp (:e scp://host//ruta), pero en el día a día lo usas como explorador local. Su modo árbol es buggy: no lo uses como barra lateral fija |
| oil.nvim (recomendado) | Editas el directorio como un buffer normal: crear = teclear una línea, renombrar = cw, borrar = dd, mover = cortar y pegar. La misma gramática que ya aprendiste |
| neo-tree / nvim-tree (estilo IDE) | La barra lateral clásica con iconos, git y diagnostics. kickstart ya trae neo-tree configurado |
La terminal: tres formas
<C-z> suspende Neovim y vuelves a la shell (job control de Unix);
regresas con fg. · :terminal abre una shell dentro de un buffer. ·
tmux (lo más común en flujos serios): Neovim en un panel, shell en otro al lado
— ahí haces git, mkdir, mv, cp y scripts.
El flujo que te recomiendo
- Saltar a archivo conocido → Telescope find_files
- Buscar por contenido → Telescope live_grep
- Rebotar entre archivos activos → buffers (<C-^>) / harpoon
- Estructura + operaciones de archivo → oil.nvim (o neo-tree para barra lateral)
- Git, comandos, scripts → terminal / tmux
Nivel 12 · Insert avanzado, autocompletado nativo, folding
PROInsert avanzado
- <C-r>reg inserta un registro · <C-r>= evalúa expresión
- <C-w> borra palabra previa · <C-u> borra hasta inicio de línea
- <C-o> ejecuta UN comando Normal y vuelve (<C-o>zz recentra)
- <C-t> / <C-d> indenta / desindenta en Insert
Autocompletado nativo <C-x>
- <C-x><C-n> palabra del archivo · <C-x><C-f> rutas
- <C-x><C-o> omni-completion (en Neovim, el cliente LSP)
- <C-x><C-l> línea entera · <C-n>/<C-p> navegan opciones
Folding (z = papel doblado)
Un fold oculta líneas; el texto no cambia. zfmotion crea (zfip) · za togglea · zo/zc abre/cierra · zR/zM abre/cierra todos · zj/zk salta entre folds.
Indentar y números
= reindenta (gg=G todo el archivo) · >>/<< desplazan · <C-a>/<C-x> incrementa/decrementa el número bajo el cursor · en Visual g<C-a> crea secuencias 1,2,3…
Nivel 13 · DIOS: composición + multi-archivo + Neovim sin plugins
DIOSPrincipios del maestro
- Componer, no memorizar: toda tarea = verbo + objeto
- Diseñar para el dot: ¿cómo lo hago para que . lo repita?
- Escalar la herramienta: 1 cambio → directo · repetir en vista → . · en archivo → :g/macro · en proyecto → :cdo
- Minimizar tiempo en Insert: salir por reflejo
- No reteclees: registros + <C-r> + completado
- Operar a distancia: si describes la línea por patrón, no navegues hasta ella
Edición en columna (Visual Block)
- <C-v>jjItextoEsc inserta al inicio de N líneas
- <C-v>jj$A;Esc añade al final (aunque tengan distinta longitud)
- <C-v>jjd borra una columna · c la cambia
Edición masiva en múltiples archivos
:args **/*.rs " define un conjunto de archivos (arglist)
:argdo %s/old/new/g | update " ejecuta y guarda en CADA archivo
:grep TODO src/ " llena la quickfix list
:copen | :cnext | :cprev " abre y navega la lista
:cdo s/foo/bar/g | update " aplica a CADA entrada de quickfix del proyecto
Principio común — define el grupo, ejecuta, guarda: :argdo (arglist), :bufdo (buffers), :windo (ventanas), :tabdo (tabs), :cdo/:cfdo (quickfix).
Lo que Neovim añade sin plugins
| Función | Comandos por defecto |
|---|---|
| LSP nativo | grn rename · grr referencias · gri implementación · gra code action · K hover (0.10/0.11) |
| Diagnostics | ]d/[d siguiente/anterior · <C-w>d flotante |
| Treesitter | :Inspect grupos bajo cursor · :InspectTree el árbol |
| Comentar (0.10+) | gc operador · gcc línea · gcap párrafo — con dot-repeat |
| Terminal de 1ª clase | :terminal · i entra a Terminal mode · <C-\><C-n> sale a Normal |
| Defaults de calidad | Y=y$ · <C-l> limpia resaltado · Q repite último macro |
Desaprender malos hábitos
Lo que separa al avanzado del maestro a veces es dejar de hacer cosas, no aprender más.
✕ Las flechas
Te sacan de la fila de inicio y te entrenan a pensar carácter-a-carácter. Usa hjkl para micro-ajustes y motions reales (w/f/}/%) para todo lo demás.
✕ Martillear hjkl
Diez j = anti-patrón. Usa }, <C-d>, nG, /patrón, fx. Si repites una tecla, hay un motion mejor.
✕ El ratón
Saca las manos de la fila de inicio. Visual mode + motions hace toda la selección, más rápido.
✕ Vivir en Insert
El error #1 de quien viene de VS Code. Volver a Normal debe ser reflejo.
✕ Reescribir lo que puedes copiar
Registros y <C-r>. Y remapea Caps Lock → Esc/Ctrl desde el día 1.
Ruta de dominio
vimtutor → usar Neovim a diario 1 mes → Practical Vim (Drew Neil) a 1-2 tips/día → VimGolf para pulir → :help como referencia perpetua. Remapea Caps Lock a Esc/Ctrl desde el día 1.
- vimtutor — tutorial oficial interactivo (~30 min). El punto de partida obligatorio: escribe
vimtutoren tu terminal. :help {tema}— la documentación interna, exhaustiva y al día con tu versión.<C-]>sigue enlaces,<C-o>vuelve.- Practical Vim — Drew Neil — el libro canónico. 120+ tips. Enseña a pensar en Vim con el dot-command como columna vertebral.
- VimGolf — retos de “edita A → B en el mínimo de pulsaciones”. Entrena la composición y la economía de teclas.
- Learn Vim the Smart Way — Igor Irianto. Guía moderna y gratis en GitHub.
- Vimcasts · Vim Adventures — screencasts por tema y un juego para interiorizar motions.
Mappings por defecto citados: Neovim 0.11 (mar 2025) para
grn/grr/gri/gra; 0.10 paraK→hover,gc,]d. Verifica con:version.