En Vim, ¿hay alguna forma de eliminar sin poner texto en el registro?

470

Con Vim, a menudo quiero reemplazar un bloque de código con un bloque que acabo de quitar.

Pero cuando elimino el bloque de código que se va a reemplazar, ese bloque entra en el registro que borra el bloque que acabo de quitar. Así que tengo la costumbre de tirar, luego insertar, y luego eliminar lo que no quería, pero con grandes bloques de código, esto se vuelve complicado al tratar de mantener el bloque insertado y el bloque para eliminar por separado.

Entonces, ¿cuál es la forma más ingeniosa y rápida de reemplazar texto en Vim?

  • ¿Hay alguna manera de eliminar texto sin ponerlo en el registro?
  • ¿hay alguna manera de decir, por ejemplo, "reemplazar la siguiente palabra" o "reemplazar hasta el siguiente párrafo"
  • ¿O es la mejor manera de utilizar de alguna manera la función de registro múltiple?
Edward Tanguay
fuente
1
vim-easyclip ( github.com/svermeulen/vim-easyclip ) está diseñado para abordar este problema exacto
Steve Vermeulen
1
Hice una pregunta, sin saberlo (en ese momento) duplicado de su problema real , pero no tanto de la pregunta del título. TL; DR: reemplácelo con lo que usó viwp(para word).
OJFord

Respuestas:

429

Para eliminar algo sin guardarlo en un registro, puede usar el "registro de agujeros negros":

"_d

Por supuesto, también puede usar cualquiera de los otros registros que no tienen nada que le interese.

Christian Berg
fuente
44
Al principio pensé que este comando no funcionaba correctamente. Entonces me di cuenta de que estaba usando una versión de "teclas muertas" del teclado americano. Con este diseño de teclado tengo que escribir "<space>_d. El espacio es necesario para escribir ".
Sebastián Grignoli
44
¿Alguna idea sobre hacer esto selectivamente solo en líneas vacías? (Si dden una línea vacía va al agujero negro, de lo contrario ddes normal).
Jonathan Dumaine
66
Para eliminar un personaje, intente:"_x
kenorb
54
Esta es un área donde gana un editor de texto estándar. Simplemente presione la tecla Eliminar.
Vince Panuccio
22
También puede tirar algo con yyo '3yy' (o lo que sea), lo que lo coloca en el registro sin nombre, pero también en 0. Luego puede seguir pegándolo "0p, a pesar de haberlo usado ddespués de eso.
Halfgaar
102

Sí. Es un poco más complicado que eliminar primero el texto "antiguo", pero:

Empiezo con ...

line1
line2
line3
line4

old1
old2
old3
old4

I shift+ vselecciono la línea 1, la línea 2, 3 y 4, y las elimino con el dcomando

Luego borro las viejas líneas 1-4 de la misma manera.

Entonces hazlo

"2p

Eso pegará las penúltimas líneas arrancadas (línea 1-4). "3phará el penúltimo, y así sucesivamente.

Así que termino con

line1
line2
line3
line4

Referencia: documentación de Vim en registro numerado

dbr
fuente
Si selecciona líneas con <Shift-v> las elimina con solo d, no con dd
Heikki Naski el
31
1 a 9 obras para eliminaciones. Para pegar la última cosa realmente arrancada (con 'y') debe usar "0p. Eso es útil en los casos en que primero tira de algo con la intención de reemplazar otra cosa, pero luego otra cosa sobrescribe el registro de pegado predeterminado.
Rafael de F. Ferreira
Para obtener más sofisticación de deshacer, consulte el script Gundo (gráfico de deshacer) .
Lumi
@ RafaeldeF.Ferreira: Su comentario no es una respuesta a esta pregunta, pero en realidad resuelve probablemente el problema real que llevó al OP a hacer la pregunta en primer lugar. Para mí, ese era el verdadero problema.
0xc0de
76

Documentos VIM: el registro numerado 0 contiene el texto del comando de extracción más reciente, a menos que el comando especifique otro registro con ["x].

Por ejemplo, tiramos "foo" y eliminamos "bar" - ¡el registro 0 todavía contiene "foo"! Por lo tanto, "foo" se puede pegar usando"0p

alex2k8
fuente
53

Es útil tener un mapeo fácil que le permite reemplazar la selección actual con búfer.

Por ejemplo, cuando pones esto en tu .vimrc

vmap r "_dP       // it's a capital 'p' on the end

luego, después de copiar algo en el registro (es decir, con 'y'), puede seleccionar el texto que desea reemplazar y simplemente presionar 'r' en su teclado. La selección se sustituirá con su registro actual.

Explicación:

vmap - mapping for visual mode
"_d - delete current selection into "black hole register"
P - paste
João Portela
fuente
1
Para una versión más avanzada, consulte: stackoverflow.com/questions/290465/…
Luc Hermitte
Me gustaría usarvmap <C-P> "_dP
Harry Lee
77
Simplemente puede poner el texto sin eliminar la selección. Por ejemplo, Vpreemplaza su línea actual con la arrancada de inmediato.
Bobby Marinoff
Esta solución no soluciona el problema, ya dque a menudo se usa para eliminar.
Victor Yarema
35

Puse lo siguiente en mi vimrc:

noremap  y "*y
noremap  Y "*Y
noremap  p "*p
noremap  P "*P
vnoremap y "*y
vnoremap Y "*Y
vnoremap p "*p
vnoremap P "*P

Ahora lo saco y lo coloco desde el registro del portapapeles, y no tengo que preocuparme por lo que sucede con el registro predeterminado. Un beneficio adicional es que puedo pegar desde otras aplicaciones con una molestia mínima. Estoy perdiendo algo de funcionalidad, lo sé, pero de todos modos no puedo rastrear más de un registro / portapapeles.

Magnus
fuente
66
En lugar de todas esas reasignaciones, también podría set clipboard=unnamedo set clipboard=unnamedplus, lo que cambia el portapapeles predeterminado a *o +, respectivamente.
Steve
55
@Steve Si haces eso, entonces d sobrescribirá el último tirón en el registro del portapapeles también, que es lo que la pregunta intenta evitar.
79E09796
1
@ 79E09796, no quise dar a entender que lo haría; Estaba comentando esta respuesta y no la pregunta original.
Steve
1
Puse estos en mi .vimrc y ahora tirar no funciona. ¿Alguna idea de por qué?
tba
2
@tba reemplaza noremap con nnoremap (dos n) y debería funcionar bien.
Meain
24

Para el ejemplo específico que dio, si entiendo la pregunta, entonces esto podría funcionar:

*Highlight what you want to put somewhere else
*delete (d)
*Highlight the code that you want it to replace
*paste (p)
EBGreen
fuente
66
Esto funciona bien, excepto cuando desea pegar en varias selecciones.
23

Todas las operaciones de extracción y eliminación escriben en el registro sin nombre de forma predeterminada. Sin embargo, el yank más reciente y la eliminación más reciente siempre se almacenan (por separado) en los registros numerados. El registro 0contiene el tirón más reciente. Los registros 1-9contienen las 9 eliminaciones más recientes ( 1siendo las más recientes).

En otras palabras, una eliminación sobrescribe el tirón más reciente en el registro sin nombre, pero todavía está allí en el 0registro. El truco del registro de agujeros negros ( "_dd) mencionado en las otras respuestas funciona porque evita sobrescribir el registro sin nombre, pero no es necesario.

Usted hace referencia a un registro utilizando comillas dobles, por lo que puede pegar el último texto eliminado de la siguiente manera:

"0p

Esta es una excelente referencia:

Wayne
fuente
16

Para enfatizar lo que dijo EBGreen :

Si pega mientras selecciona texto, el texto seleccionado se reemplaza con el texto pegado.

Si desea copiar un texto y luego pegarlo en varias ubicaciones, use "0ppara pegar. El registro numerado 0 contiene el texto del comando de extracción más reciente.


Además, puede enumerar el contenido de todos sus registros:

:registers

Ese comando hace que sea más fácil averiguar qué registro desea al hacer algo como la respuesta de dbr . También verá los registros /,%, #. (Ver también :help registers)


Y finalmente, revise cWy cWcambie una palabra que incluya y no incluya un espacio final. (El uso del capital Wincluye puntuación).

idbrii
fuente
10

Si está utilizando Vim, tendrá el modo visual, que es como seleccionar, pero con los modos de separación es la base de vi / vim.

Lo que desea hacer es usar el modo visual para seleccionar la fuente, luego tirar, luego usar el modo visual nuevamente para seleccionar el alcance del destino y luego pegar en el texto desde el búfer predeterminado.

Ejemplo:

En un archivo de texto con:

1 | qwer
2 | asdf
3 | zxcv
4 | poiu

con la siguiente secuencia: ggVjyGVkpterminarás con:

1 | qwer
2 | asdf
3 | qewr
4 | asdf

Explicado:

  • gg: ir a la primera línea
  • V: iniciar el modo visual con líneas enteras
  • j: ir hacia abajo una línea (con la selección iniciada en las líneas anteriores, esto aumenta la selección una línea hacia abajo)
  • y: tira al búfer predeterminado (las dos líneas seleccionadas, y automáticamente sale del modo visual)
  • G: ir a la última línea
  • V: iniciar el modo visual (igual que antes)
  • k: sube una línea (como antes, con el modo visual habilitado, esto aumenta la selección una línea)
  • p: pegar (con la selección en las dos últimas líneas, reemplazará esas líneas con lo que haya en el búfer, las 2 primeras líneas en este caso)

Esto tiene el pequeño inconveniente de que coloca el último bloque en el búfer, por lo que de alguna manera no es deseable para pegados repetidos de la misma cosa, por lo que querrá guardar la fuente en un búfer con nombre como "ay(a un búfer llamado "a ") y pegar con algo como "ap(pero si estás programando, probablemente no quieras pegar varias veces sino crear una función y llamarla, ¿verdad? ¿ DERECHO ?).

Si solo usa vi, entonces tendrá que usar marcas invisibles en lugar del modo visual, :he markpara más información sobre esto, lo siento, pero no soy muy bueno con esta cosa de las marcas invisibles, estoy bastante contaminado con el modo visual.

maeghith
fuente
10

Para 'reemplazar palabra', intente cwen modo normal.

Para 'reemplazar párrafo', intente capen modo normal.

Swaroop CH
fuente
1
Para 'reemplazar hasta el siguiente párrafo', intente c}en modo normal.
jabirali
¿Por qué "cap" hace esto? ¿No es "a" y "p" significa "agregar" y "pegar"?
WiSaGaN
2
@WiSaGaN "ap" significa "un párrafo": vimhelp.appspot.com/motion.txt.html#object-select
Swaroop CH
9

Una solución mínimamente invasiva para los perezosos:

Registrarse 0siempre contiene el último yank (como ya han mencionado Rafael , alex2k8 e idbrii ). Desafortunadamente, seleccionar registrar 0todo el tiempo puede ser bastante molesto, por lo que sería bueno si se pusa "0por defecto. Esto se puede lograr poniendo las siguientes líneas en su .vimrc:

noremap p "0p
noremap P "0P
for s:i in ['"','*','+','-','.',':','%','/','=','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
    execute 'noremap "'.s:i.'p "'.s:i.'p'
    execute 'noremap "'.s:i.'P "'.s:i.'P'
endfor

La primera línea asigna cada ptrazo a "0p. Sin embargo, esto evita el pacceso a otros registros. Por lo tanto todosp trazos con un registro seleccionado explícitamente se asignan a la expresión de línea de comandos equivalente dentro del ciclo for. Lo mismo se hace para P.

De esta forma se conserva el comportamiento estándar, excepto el implícito py los Ptrazos, que ahora usan el registro0 por defecto.

Sugerencia 1: el comando de corte ahora es en "0dlugar de solo d. Pero como soy flojo, esto es demasiado largo para mí;) Por lo tanto, estoy usando la siguiente asignación:

noremap <LEADER>d "0d
noremap <LEADER>D "0D

La clave líder es \predeterminada, por lo que puede cortar fácilmente el texto escribiendo \do \D.

Sugerencia 2: El tiempo de espera predeterminado para las asignaciones de teclas múltiples es bastante corto. Es posible que desee aumentarlo para tener más tiempo al seleccionar un registro. Ver :help timeoutlenpara más detalles, estoy usando:

set timeout timeoutlen=3000 ttimeoutlen=100
Torben
fuente
7

Bueno, primero haz este comando:

:h d

Entonces se dará cuenta de que puede eliminar en un registro específico. De esa manera no alterará lo que está en su registro predeterminado.

EBGreen
fuente
1
["x]d{motion} Delete text that {motion} moves over [into register x]- Vim:h d
Wes Turner
5

Mi situación: en el Normalmodo, cuando elimino caracteres usando la xpulsación de tecla, esas eliminaciones sobrescriben mi último registro, lo que complica las ediciones donde quiero eliminar caracteres usando xy pego algo que tengo en mi registro más reciente (por ejemplo, pegar el mismo texto a las dos o más lugares)

Intenté la sugerencia en la respuesta aceptada ( "_d), pero no funcionó.

Sin embargo, de la respuesta / comentarios aceptados en /vi/122/performing-certain-operations-without-clearing-register , agregué esto a mi ~/.vimrc, que funciona (puede que tenga que reiniciar Vim ):

nnoremap x "_x

Es decir, ahora puedo hacer mis comandos normales de yank ( y), delete ( d) y paste ( p), y los caracteres que elimino xya no rellenan los registros más recientes.

Victoria Stuart
fuente
4

El texto eliminado, mientras está en modo de inserción, no entra en el registro predeterminado.


fuente
2
pero borrar cualquier cantidad significativa de texto en modo predeterminado es LENTO
Hamish Downer
3

Las dos soluciones que uso en los contextos correctos son;

  • resalte lo que desea reemplazar usando el VISUALmodo Vims y luego pegue el registro.

Utilizo esto principalmente por costumbre, ya que solo encontré la segunda solución mucho más tarde, por ejemplo

yiw   " yank the whole word
viwp  " replace any word with the default register
  • YankRing . Con este complemento, puede usar la combinación <ctrl>+<p>de teclas para reemplazar el registro numerado anterior por el que acaba de pegar.

Básicamente, vas a pegar como lo harías, pero cuando te das cuenta de que has sobrescrito el registro predeterminado y pierdes lo que realmente querías pegar, puedes <C-P> y pierdes buscar y reemplazar del historial de YankRing.

Uno de esos debe tener complementos ...

chico expulsado
fuente
2

En la versión de Windows (probablemente también en Linux), puede utilizar el búfer de copiar / pegar del sistema utilizando "*y (es decir, precediendo su comando de extracción con comillas dobles y asterisco).

Luego puede eliminar las líneas reemplazables normalmente y pegar el texto copiado usando "*p.

JayG
fuente
2

A menudo cometo un error al seguir los comandos para 'tirar' y luego '' _d 'eliminar en un agujero negro y luego' pegar '. Prefiero' tirar ', luego borrar como quiera, luego' "0p 'de el registro 0, que es donde se empuja el último texto copiado.

Despistado
fuente
2

Para los usuarios de emacs-evil, la función (evil-paste-pop)se puede activar después de pegar, y recorre las entradas anteriores en el ring de eliminación. Suponiendo que lo vincula <C-p>(predeterminado en Spacemacs), presionaría pseguido de tantos <C-p>como sea necesario.

Adrien Vakili
fuente
1

Para los usuarios de Dvorak, un método muy conveniente es simplemente eliminar el texto innecesario en el "registro 1 en lugar del registro" _ agujero negro, aunque solo sea porque puede presionar "+ 1 con la misma tecla Mayús y un movimiento meñique rápido ya que 1 es la clave inmediatamente arriba "en Dvorak (MÁS d está en la otra mano, lo que hace que todo el comando sea rápido como el infierno).

Entonces, por supuesto, el registro "1 podría usarse para otras cosas debido a su conveniencia, pero a menos que tenga un propósito más común que reemplazar el texto, diría que es un uso bastante bueno del registro.

Vic Goldfeld
fuente
1

Para aquellos de ustedes que están interesados ​​principalmente en no sobrescribir el registro sin nombre cuando reemplazan un texto mediante selección virtual y pegan.

Puede usar la siguiente solución, que es fácil y funciona mejor para mí:

xnoremap <expr> p 'pgv"'.v:register.'y'

Es de las respuestas (y comentarios) aquí: Cómo pegar sin sobrescribir el registro

Primero pasa la selección, luego la selección con el nuevo texto se selecciona nuevamente (gv). Ahora el registro que se utilizó por última vez en modo visual (normalmente el registro sin nombre, pero también funciona sin efectos secundarios si usa otro registro para pegar). Y luego tire el nuevo valor al registro nuevamente.

PD: si necesita una variante más simple que funcione también con la simulación vim intellj idea plugin, puede tomar esta (inconveniente: sobrescribir el registro sin nombre incluso si se dio otro registro para pegar):

vnoremap p pgvy

chasquido
fuente
0

La preferencia ocasional de Vim por la complejidad sobre la practicidad carga al usuario con la aplicación de registros para copiar / eliminar acciones: cuando la mayoría de las veces, uno solo quiere pegar lo que se copió y "olvidar" lo que se eliminó.

Sin embargo, en lugar de combatir los complicados registros de vim, haga que sean más convenientes: elija un registro "predeterminado" para almacenar su última eliminación. Por ejemplo, envíe eliminaciones al registro d (dejando ac abierto para uso ad-hoc; d es un buen mnemónico):

nnoremap d "dd           "send latest delete to d register
nnoremap D "dD           "send latest delete to d register 
nnoremap dd "ddd         "send latest delete to d register
nnoremap x "_x           "send char deletes to black hole, not worth saving
nnoremap <leader>p "dp   "paste what was deleted
nnoremap <leader>P "dP   "paste what was deleted

Este enfoque evita que las eliminaciones golpeen los yanks PERO no pierde el registro de la eliminación: se puede pegar (volver) lo que se eliminó en lugar de perderlo en un agujero negro (como en la respuesta aceptada). En el ejemplo anterior, esta recuperación se realiza con dos asignaciones de p líderes. Un beneficio de este enfoque es que le brinda la posibilidad de elegir qué pegar: (a) lo que se acaba de quitar, o (b) lo que se acaba de eliminar.

Gregory
fuente
0

registrar 0 a 9 son las últimas cosas que tira o corta, etc., y NO incluye cosas eliminadas, etc. Por lo tanto, si tira / corta algo, también está en el registro 0, incluso si dice cosas borradas todo el día después de eso, registre 0 sigue siendo lo último que arrancaste / cortaste.

yiw # va al registro predeterminado y al registro 0

tira de la palabra en la que está el cursor

las cosas eliminadas, etc. irán al registro predeterminado, pero NO registrarán 0

en modo estándar:

"0p # ingrese el contenido del registro 0

en modo de inserción:

ctrl-r 0 # ingrese el contenido del registro 0

También tuve un amigo que siempre tiraba / cortaba para registrarse x lol.

Beto
fuente