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.

  • #neovim
  • #vim
  • #editores
  • #productividad

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

NOOB

La 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
ModoPara quéCómo entras
NORMALReposo. Comandos, operadores, motions.Esc · <C-[>
INSERTInsertar texto.i I a A o O
VISUALSelección: char (v), línea (V), bloque (<C-v>).v V <C-v>
COMMAND-LINEComandos Ex, búsqueda, filtros.: / ? !
OPERATOR-PENDINGEstado efímero tras un operador, esperando motion/objeto.tras d c y
TERMINALEmulador de terminal dentro de un buffer.:terminal
Entrar a InsertDónde queda el cursor
i / aantes / después del cursor
I / Aprimer no-blanco / fin de línea
o / Olínea nueva abajo / arriba
gidonde 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
MotionQué hace
w Winicio de la siguiente word / WORD (separada por espacios)
b einicio anterior / fin de la palabra
0 ^ $columna 0 / primer no-blanco / fin de línea
fx txsalta a / justo antes del carácter x — ; repite, , invierte
{ }párrafo anterior / siguiente
%salta al paréntesis/llave/corchete pareja
gg G nGinicio / fin del archivo / línea n
H M Ltop / middle / bottom de la pantalla
<C-d> <C-u>media pantalla abajo / arriba
zz zt zbrecentra cursor al medio / arriba / abajo

Nivel 3 · La gramática: operador + motion + count

PRO

La 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
OperadorVerbo
d c yborrar / cambiar (borra + Insert) / copiar (yank)
> < =indentar / desindentar / reindentar (auto)
gu gU g~minúscula / mayúscula / alternar caso
gq gcreformatear 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”

PRO

La 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).

Objetoinner / aroundCaso de uso
palabraiw awciw renombra un identificador entero
comillasi” a”ci” cambia un valor de atributo / string
paréntesisi( a(ci( cambia argumentos de función
llavesi{ a{ci{ cambia el cuerpo de función (C/Rust/Swift)
corchetesi[ a[di[ vacía un índice/array
etiqueta HTMLit atcit cambia contenido de div · dat borra la etiqueta entera
párrafoip apdap borra el bloque

Nivel 5 · Repetición: el dot-command y el diseño repetible

PRO
flowchart 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:

AtajoEquivale a
A I$a / ^i
C D S sc$ / d$ / cc / cl
o Onueva 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
RegistroQué guarda
unnamedel por defecto. Todo d/c/s/x/y lo actualiza
”0 yanksolo el último yank — no se pisa con borrados. Truco oro: “0p pega lo último copiado aunque hayas borrado después
”1“9historial de borrados de ≥1 línea (1 = más reciente)
“a“zlos controlas tú. “A (mayúscula) = append sin pisar
”_ black holeel /dev/null. “_dd borra sin contaminar lo copiado
”+ “*portapapeles del sistema / selección X11
”= expressionevalú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
ComandoQué hace
ma-z / mA-Zmarca local al buffer / global (entre archivos)
`x / xsalta 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 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 ?foobuscar adelante / atrás · n repite, N invierte
* #palabra bajo cursor adelante / atrás
/foo/esearch offset: deja el cursor al final del match
:nohlimpia 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 \zemarcan inicio/fin real del match: foo\zsbar matchea solo “bar” precedido de “foo”. Más simple que lookaround
%Vrestringe 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

DIOS

Rangos y manipulación de líneas

% . $todo / línea actual / última · combinables: .,$ 'a,'b
:mdirmover líneas: :m0 al inicio, :m$ al final
:t / :cocopiar líneas: :t. duplica la actual, :3,5t10
:j :sortunir / 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

qaqgraba en el registro a · qA añade al final
@a @@ 5@aejecuta a · repite el último · 5 veces · 99@a “hasta fallar”
:g/patrón/normal @ael 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

PRO
flowchart 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

PRO

El 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ónQué 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

PRO

Insert 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

DIOS

Principios 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ónComandos por defecto
LSP nativogrn 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 calidadY=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 vimtutor en 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 para K→hover, gc, ]d. Verifica con :version.