Saltar al contenido

Registros y marcas a nivel experto

Los registros son decenas de ranuras con nombre, no un portapapeles: el anillo de borrados, el registro cero, el agujero negro, el de expresión, y el tipo —caracteres, líneas o bloque— que decide cómo pega cada uno. Las marcas locales, globales, numeradas y automáticas, y por qué son mociones como cualquier otra.

Un registro no es «el portapapeles»: es una ranura con nombre donde cabe texto, y hay más de cuarenta. Las marcas son lo mismo para posiciones. Juntos son la memoria de trabajo del editor —lo que copias, lo que borras, dónde estabas, qué buscaste, qué comando ejecutaste— y casi todo el mundo usa dos de las cuarenta cosas que ofrecen, porque el resto está detrás de una sintaxis de una comilla que nadie explica. Esta lección abre las cuarenta. Sin plugins, sin configuración.

  • Usar los registros que Neovim rellena solo, y por qué "0 elimina una categoría entera de errores.
  • Recorrer el anillo de borrados "1–"9 con un truco que rompe la regla del punto.
  • Distinguir el tipo de un registro —caracteres, líneas o bloque— y predecir cómo va a pegar.
  • Pegar respetando la indentación con ]p y dejando el cursor bien con gp.
  • Entender la relación entre "+, "* y el portapapeles del sistema, incluso por SSH.
  • Poner marcas locales, globales y numeradas, y usarlas como mociones con un operador.

Un registro es una ranura con nombre

Antepón "x a un yank, un delete o un paste y estarás usando el registro x en vez del de por defecto.

Texto
"ayy    copia la línea al registro a"ap     pega lo que haya en el registro a"add    borra la línea, guardándola en a

:registers te los enseña todos con su contenido —y :reg a0+ solo los tres que le pidas—. Ábrelo ahora: verás que la mayoría están llenos sin que tú hayas hecho nada.

Lee el diagrama por el color: todo —copiar y borrar— pasa por el registro sin nombre, que es el rojo. Por eso p a secas es impredecible en cuanto haces algo entre medias. Y fíjate en que el yank es el único que además va al verde.

Registro Contenido
"a–"z los tuyos
"A–"Z los mismos, pero añadiendo en vez de reemplazar
"" el sin nombre: lo último que copiaste o borraste, sea lo que sea
"0 el último yank — los borrados no lo tocan
"1–"9 el anillo de los últimos borrados grandes
"- el último borrado pequeño (menos de una línea)
"_ el agujero negro: traga y no guarda
"+ el portapapeles del sistema
"* la selección primaria de X11; en macOS y Windows es igual que "+
"% el nombre del fichero actual
"# el fichero alterno
": el último comando ejecutado
"/ el último patrón buscado
". el último texto insertado
"= el registro de expresión: evalúa

Los cuatro de solo lectura del final valen más de lo que parecen. "/ te deja reutilizar la búsqueda que acabas de hacer dentro de una sustitución sin volver a escribirla, y ". te devuelve lo último que tecleaste en Insertar aunque ya no esté en pantalla.

Son los mismos registros de las macros

Cuando grabas una macro con qa, las teclas van al registro a. Por eso "ap pega una macro como texto y :reg a te la enseña. No hay dos sistemas: hay uno, y una macro es texto guardado en él. Lo verás en la lección 1.5, y ahí lo aprovecharás para editar una macro que salió casi bien.

"0: el yank que sobrevive

Este resuelve el fallo más frecuente de todo el editor.

Copias una línea con yy, te mueves, borras la línea que quieres sustituir con dd, pegas con p… y pegas lo que acabas de borrar. Porque dd machacó el registro sin nombre.

"0 guarda solo los yanks. Ningún borrado lo toca.

Texto
yy          copia (va al sin nombre Y al "0)dd          borra (machaca el sin nombre, NO toca "0)"0p         pega lo que copiaste

Interioriza «pegar es siempre 0p»

Muchos usuarios veteranos ya no usan p a secas para pegar algo que copiaron: usan "0p por sistema. Se escribe un carácter más y elimina de raíz una categoría entera de errores, porque deja de importar cuántas cosas hayas borrado entre medias.

Si el gesto te resulta incómodo, mapéalo cuando llegues al Nivel 2: <leader>p a "0p es de los atajos que más se agradecen a los seis meses.

El anillo de borrados "1–"9

Cada borrado de una línea o más entra en "1, y empuja lo que había: lo de "1 pasa a "2, lo de "2 a "3, y así hasta que "9 se cae por el borde. Tienes las últimas nueve cosas que borraste, en orden.

Texto
"1p    pega el último borrado"2p    el anterior

Y aquí está el truco que casi nadie conoce:

Texto
"1p    pega el último borradou.     deshace y repite... pero con "2u.     ...ahora con "3

Después de un "1p, el . no repite el mismo pegado: avanza al registro siguiente. Es una de las poquísimas excepciones al comportamiento del punto, y existe exactamente para esto: recorrer el anillo sin acordarte de en qué número ibas.

Los borrados pequeños —menos de una línea, como dw o x— no entran en el anillo: van a "-. Si borras una palabra y la quieres de vuelta, "-p.

El agujero negro "_

Todo lo que mandes ahí desaparece sin tocar ningún otro registro.

Texto
"_dd    borra la línea sin machacar nada"_diw   borra la palabra sin machacar nada

El caso donde es imprescindible es pegar sobre una selección. En modo Visual, p sustituye lo seleccionado y se lleva lo sustituido al registro, así que si intentas pegar lo mismo en tres sitios, el segundo pegado ya es otra cosa.

Texto
viw"_dP    borra la palabra al agujero negro y pega, conservando tu copia

Es tan frecuente que en el Nivel 2 lo mapearás. Y "0p en modo Visual también lo esquiva, porque "0 no se toca al sustituir.

El tipo de un registro decide cómo pega

Esta es la parte que explica un comportamiento que parece caprichoso y no lo es. Un registro no guarda solo texto: guarda también de qué clase es.

Tipo Se llena con Y al pegar…
caracteres yiw, y$, yi( se inserta dentro de la línea, en el cursor
líneas yy, dd, yap abre líneas nuevas encima o debajo
bloque Ctrl-v y y se inserta como rectángulo, empujando columnas

Por eso yiw seguido de p pega la palabra a la derecha del cursor, y yy seguido de p abre una línea nueva debajo. No es que p haga dos cosas: es que el registro que le llega es de dos clases distintas.

:registers te lo enseña: mira la columna de la izquierda, donde pone c, l o b.

Y se puede forzar

Si necesitas pegar como línea algo que copiaste como caracteres —o al revés—, se cambia el tipo del registro sin tocar su contenido:

VIM
:call setreg('a', getreg('a'), 'V')   " fuerza que el registro a sea de líneas:call setreg('a', getreg('a'), 'v')   " de caracteres

Es raro necesitarlo a mano, y deja de ser raro en cuanto empieces a rellenar registros desde Lua en el Nivel 10.

Pegar mejor: ]p, gp y zp

p y P no son las únicas, y las otras resuelven dos molestias diarias.

]p y [p pegan por líneas ajustando la indentación a la de la línea donde estás. Copias tres líneas de dentro de un if y las pegas en un bloque anidado más adentro: con p te llevas la indentación original y tienes que reindentar; con ]p llegan ya alineadas.

gp y gP pegan igual que p y P pero dejan el cursor justo después de lo pegado, en vez de al principio. Cuando vas a pegar varias cosas seguidas, gp te deja ya colocado para la siguiente; con p tienes que saltar al final cada vez.

Texto
]p     pega respetando la indentación de aquígp     pega y deja el cursor detrás"0]p   las dos cosas: el yank de verdad, bien indentado

Acumular con mayúsculas

La versión en mayúscula de un registro añade en vez de reemplazar. Sirve para recolectar trozos dispersos:

Texto
"ayy    la primera línea al registro a… te mueves …"Ayy    AÑADE esta… te mueves …"Ayy    y esta"ap     pega las tres juntas

Funciona con cualquier operador: "Ayi( va acumulando el interior de paréntesis de sitios distintos. Es la forma nativa de hacer «copia esto, y esto, y esto, y ahora pégalo todo junto», que en otros editores no existe.

Vaciar un registro

qaq graba cero teclas en a y lo deja vacío. Es la forma rápida de empezar a acumular limpio, y la misma que necesitarás para grabar macros recursivas en la lección 1.5.

El portapapeles del sistema

"+ es el portapapeles normal —el de Ctrl-c— y "* es la selección primaria de X11, esa que en Linux se pega con el botón central. En macOS y en Windows los dos son lo mismo.

Texto
"+yy     copia la línea al portapapeles del sistema"+p      pega lo que haya en el portapapeles del sistema"+yi(    copia el interior de los paréntesis al sistema

Neovim no habla con el portapapeles por sí mismo: llama a un programa externo. En Linux es wl-copy/wl-paste en Wayland o xclip/xsel en X11; en macOS y Windows viene resuelto. Si "+y no hace nada, la respuesta está en :checkhealth vim.provider, en la sección de portapapeles.

Y por SSH también funciona, gracias a una secuencia de escape de 1979

Este es uno de esos casos en los que la solución llega desde un sitio inesperado.

El problema es viejo y lo has sufrido: editas en un servidor por SSH, copias con "+y, y no pasa nada. Es lógico —no hay portapapeles en la máquina remota, o lo hay y es el suyo, no el tuyo—. La solución habitual era seleccionar con el ratón y dejar que el emulador de terminal copiase lo pintado, con lo que te llevabas los números de línea y los saltos donde no tocaba.

La solución real se llama OSC 52, y es una secuencia de escape: el programa remoto le dice a tu terminal, a través de la misma conexión por la que viajan los caracteres, «mete esto en el portapapeles». El terminal, que corre en tu máquina, obedece. Neovim la usa automáticamente cuando detecta que estás en una sesión SSH y no encuentra herramienta de portapapeles; está documentada en :h clipboard-osc52.

Lo interesante es de dónde sale. Los códigos OSC —Operating System Command— son parte del estándar de terminales que la industria lleva arrastrando desde los años setenta, y llevaban décadas ahí sin que casi nadie los usara para esto. No hubo que inventar un protocolo, ni abrir un puerto, ni instalar un demonio: hubo que darse cuenta de que el canal ya existía. La misma tubería que transporta tu ls transporta también un mensaje al portapapeles, porque el diseño del terminal siempre contempló que el programa remoto pudiera pedirle cosas al local.

Es un patrón que conviene reconocer, porque se repite: los problemas de integración más molestos rara vez se resuelven añadiendo un canal nuevo. Se resuelven encontrando qué canal ya está abierto y qué permite decir. Los metadatos en las cabeceras HTTP, las variables de entorno como interfaz entre procesos, los códigos de salida, stderr frente a stdout, o el propio protocolo LSP viajando por la entrada y la salida estándar en vez de por un socket —que verás en el Nivel 19— son todos la misma idea. Antes de construir una tubería nueva, mira qué cabe por la que ya tienes.

La decisión de clipboard=unnamedplus, que tomarás en el Nivel 2

Existe una opción, 'clipboard', que fusiona el registro sin nombre con el del sistema: puesta a unnamedplus, un yy copia al portapapeles y un p pega de él, sin escribir "+.

Es cómodo y tiene un coste que casi nadie te cuenta: todo lo que borres también va al portapapeles del sistema. Un dd para eliminar una línea basura te machaca lo que tuvieras copiado del navegador. Y x sobre una letra, también.

Las dos posturas son defendibles. Sin la opción, escribes "+ cuando cruzas la frontera del editor, y todo lo demás queda dentro. Con ella, ganas comodidad y necesitas el agujero negro "_ mucho más a menudo. Lo importante hoy es que sepas que esa fusión existe y qué implica, para que en el Nivel 2 la elijas en lugar de heredarla de una configuración copiada.

Usar registros sin salir de Insertar

Ctrl-r seguido de una letra pega ese registro mientras escribes:

En modo Insertar Pega
Ctrl-r a el registro a
Ctrl-r 0 el último yank
Ctrl-r % el nombre del fichero actual
Ctrl-r Ctrl-w la palabra que hay bajo el cursor
Ctrl-r Ctrl-a el WORD bajo el cursor

Ctrl-r``Ctrl-w es sorprendentemente útil: estás escribiendo una llamada y necesitas el identificador que tienes justo debajo. No hace falta salir, copiarlo y volver.

Y lo mismo funciona en la línea de comandos, que es donde más rinde: :%s/ seguido de Ctrl-r``Ctrl-w mete la palabra bajo el cursor en la sustitución. En la lección siguiente lo vas a usar constantemente.

El registro de expresión "=

Evalúa una expresión y pega el resultado.

Texto
En Insertar:  Ctrl-r =  24*60  Enter          →  inserta 1440En Insertar:  Ctrl-r =  strftime('%Y-%m-%d')  →  inserta la fecha de hoyEn Normal:    "=line('$')  Enter  p           →  pega el número de líneas

Acepta cualquier expresión de Vimscript, y con luaeval("…") también Lua. Es una calculadora y un generador de texto dentro del editor.

Escribir un registro desde fuera

VIM
:let @a = 'texto que quieres tener a mano':let @+ = expand('%:p')          " la ruta absoluta del fichero, al portapapeles
LUA
vim.fn.setreg('a', 'texto que quieres tener a mano')

Es como se dejan macros preparadas o plantillas que usas a diario. En el Nivel 2 pondrás alguna en tu configuración.

Marcas

Una marca es una posición guardada. m seguida de una letra la pone. Para volver hay dos formas, y la diferencia importa:

Vuelves con A dónde
`a (backtick) la posición exacta: línea y columna
'a (apóstrofo) al principio de esa línea
Marca Qué es
a–z locales al fichero, las pones tú
A–Z globales: guardan también el fichero, así que cruzan buffers
0–9 los últimos ficheros que cerraste, puestas por el shada
`. dónde fue el último cambio
`^ dónde estaba el cursor la última vez que insertaste
`" dónde estabas al cerrar este fichero la última vez
`[ `] principio y final del último texto copiado o pegado
`< `> principio y final de la última selección visual
`` (dos backticks) de donde vienes: alterna entre dos posiciones

:marks las lista todas. :delmarks a borra una, :delmarks! borra todas las locales del buffer.

Las numeradas son un regalo que nadie usa: `0 te lleva al fichero y la posición en la que estabas la última vez que cerraste Neovim, `1 a la anterior, y así. Abre el editor en un directorio cualquiera y pulsa `0: estás donde lo dejaste ayer.

Marcas globales como espacio de trabajo

Cuando entres en una tarea que toca cuatro ficheros, ponle una marca global a cada uno: mR en el router, mM en el modelo, mT en los tests, mC en la configuración.

A partir de ahí, `R te lleva al router desde cualquier sitio del proyecto, esté abierto o no. Es un conjunto de anclas con nombre que dura toda la sesión y sobrevive a cerrar y abrir ficheros, porque las globales viven en el shada.

Y son solo veintiséis. Esa escasez es una virtud: te obliga a marcar lo que de verdad importa, en vez de acumular treinta pestañas «por si acaso».

Una marca es una moción, con su tipo

Aquí se cierra el círculo con la lección 0.4. Una marca no es solo un sitio al que ir: es un complemento que acepta cualquier operador.

Texto
d'a     borra desde aquí hasta la línea de la marca a — por LÍNEASd`a     borra desde aquí hasta la posición exacta — por CARACTERESy'a     copia esas líneas>'a     indenta ese rango!'a sort  ordena ese rango con sort

Fíjate en lo que acabas de aprender sin que nadie te lo enseñara: 'a es una moción de línea y `a es una moción de caracteres exclusiva. Son las tres categorías de la lección 0.4 otra vez, aplicadas a un complemento nuevo. Está en :h mark-motions.

Eso convierte a las marcas en la forma de operar sobre un rango arbitrario grande: te pones donde empieza, ma, te vas a donde acaba, y d'a.

Las automáticas, que pone el editor y nadie usa

  • `. te lleva al último cambio. Después de saltar a leer otra cosa, es la forma de volver a lo que estabas escribiendo.
  • `" es la que hace que al reabrir un fichero vuelvas a donde te quedaste.
  • `[ y `] delimitan lo último que pegaste, así que `[v`] selecciona exactamente lo pegado —útil para reindentarlo con = acto seguido— y =`] lo hace de un golpe.
  • `< y `> son los que usa gv para restaurar tu última selección, y los que escribes cuando pones :'<,'> delante de un comando. En la lección siguiente los vas a ver mucho.

Las dos listas que el editor lleva solo

En la lección 0.3 viste la jumplist con Ctrl-o y Ctrl-i. Merece verlas por dentro:

VIM
:jumps      " la lista de saltos, con el actual marcado con >:changes    " la lista de cambios, que recorren g; y g,

La jumplist guarda hasta cien posiciones por ventana y se conserva entre sesiones en el shada. La changelist es por buffer y recorre dónde editaste, no dónde saltaste.

Y `` —dos backticks— es el caso más pequeño y más usado: alterna entre tu posición actual y la anterior. Vas a mirar algo, dos backticks, vuelves. Otra vez, y estás allí de nuevo.

El editor llega a ti con yy y dd ya ejecutados (míralo en el HUD si reproduces la solución). "0 solo guarda yanks: los borrados no lo tocan, por muchos que hayan sido.

El agujero negro "_ se traga lo sustituido, así que tu copia sobrevive intacta para el siguiente pegado. Con p a secas, el segundo pegado ya sería «malo». (Y un matiz de veterano: este idioma quiere la palabra en medio del texto; sobre la última palabra de la línea, P cae un carácter antes de lo que esperas.)

"1p pega el último; u. deshace y avanza al siguiente del anillo. No hace falta acordarse del número.

]p ajusta la indentación de lo pegado a la de la línea actual.

Una marca es una moción: 'a opera por líneas —de ahí que caigan las cinco—; `a operaría por caracteres exactos.

Sin salir de Insertar, sin copiar, sin volver.

La marca ] es el final de lo pegado, y = es un operador que acepta mociones.

Multiplica tu memoria de trabajo

  1. Abre :registers y mira todo lo que Neovim guarda sin que se lo pidas. Localiza la columna del tipo: c, l o b.
  2. Copia una palabra con yiw y pégala con p; luego copia una línea con yy y pégala. Explica por qué una se inserta dentro de la línea y la otra abre una nueva.
  3. Copia una línea, borra otras tres, y recupera la copia con "0p.
  4. Recorre el anillo de borrados con "1p seguido de u. tres veces.
  5. Borra una palabra con "_diw y comprueba que tu copia sigue intacta.
  6. Recolecta cinco líneas dispersas con "ayy y cuatro "Ayy, y suéltalas juntas.
  7. Copia algo al portapapeles del sistema con "+yy y pégalo en otra aplicación. Si no funciona, ejecuta :checkhealth vim.provider y mira la sección del portapapeles.
  8. Pon marcas globales en tres ficheros y salta entre ellos con `R, `M y `T.
  9. Usa una marca como moción: ma, baja cincuenta líneas, y y'a. Compara el resultado con y`a.
  10. Cierra el editor, ábrelo en otro directorio, y pulsa `0. Estás donde lo dejaste.