Dans Vim, existe-t-il un moyen de supprimer sans mettre de texte dans le registre?


470

En utilisant Vim, je veux souvent remplacer un bloc de code par un bloc que je viens de tirer.

Mais quand je supprime le bloc de code à remplacer, ce bloc lui-même va dans le registre qui efface le bloc que je viens de tirer. J'ai donc l'habitude de tirer, puis d'insérer, puis de supprimer ce que je ne voulais pas, mais avec de gros blocs de code, cela devient compliqué d'essayer de garder le bloc inséré et le bloc à supprimer séparément.

Quelle est donc la manière la plus simple et la plus rapide de remplacer du texte dans Vim?

  • existe-t-il un moyen de supprimer du texte sans le mettre dans le registre?
  • existe-t-il un moyen de dire, par exemple, "remplacer le mot suivant" ou "remplacer jusqu'au paragraphe suivant"
  • ou est-ce la meilleure façon d'utiliser la fonction multi-registres?

1
vim-easyclip ( github.com/svermeulen/vim-easyclip ) est conçu pour résoudre ce problème exact
Steve Vermeulen

1
J'ai posé une question, sans le savoir (à l'époque), un double de votre problème réel , mais pas tellement de la question du titre. TL; DR - remplacez par ce que vous avez utilisé viwp(pour word).
OJFord

Réponses:


429

Pour supprimer quelque chose sans l'enregistrer dans un registre, vous pouvez utiliser le "registre des trous noirs":

"_d

Bien sûr, vous pouvez également utiliser n'importe quel autre registre qui ne contient rien de ce qui vous intéresse.


4
Au début, je pensais que cette commande ne fonctionnait pas correctement. Puis j'ai réalisé que j'utilisais une version "touches mortes" du clavier américain. Avec cette disposition de clavier, je dois taper "<space>_d. L'espace est nécessaire pour taper réellement le ".
Sebastián Grignoli

4
Avez-vous des idées pour le faire de manière sélective sur des lignes vides uniquement? (Si je ddsur une ligne vide, il va dans le trou noir, sinon c'est ddcomme normal).
Jonathan Dumaine

6
Pour supprimer un personnage, essayez:"_x
kenorb

54
C'est un domaine où un éditeur de texte standard gagne. Vous appuyez simplement sur la touche Suppr.
Vince Panuccio

22
Vous pouvez également extraire quelque chose avec yyou '3yy' (ou autre), ce qui le place dans le registre sans nom, mais aussi dans 0. Vous pouvez ensuite continuer à le coller avec "0p, bien que vous l'ayez utilisé daprès cela.
Halfgaar

102

Oui. C'est un peu plus compliqué que de supprimer d'abord le "vieux" texte, mais:

Je commence par ..

line1
line2
line3
line4

old1
old2
old3
old4

I shift+ vsélectionnez la ligne 1, la ligne 2, 3 et 4, et supprimez-les avec la dcommande

Ensuite, je supprime les anciennes lignes 1-4 de la même manière.

Alors fais

"2p

Cela collera l'avant-dernière ligne tirée (ligne 1-4). "3pfera l'avant-dernier, et ainsi de suite ..

Je me retrouve donc avec

line1
line2
line3
line4

Référence: documentation Vim sur registre numéroté


Si vous sélectionnez des lignes avec <Shift-v> vous les supprimez avec juste d, pas dd
Heikki Naski

31
1 à 9 fonctionne pour les suppressions. Pour coller la dernière chose vraiment coupée (avec 'y'), vous devez utiliser "0p. C'est utile dans les cas où vous tirez d'abord quelque chose qui a l'intention de remplacer quelque chose d'autre, mais ensuite quelque chose d'autre écrase le registre de pâte par défaut.
Rafael de F. Ferreira

Pour plus de sophistication d'annulation, consultez le script Gundo (annulation graphique) .
Lumi

@ RafaeldeF.Ferreira: Votre commentaire n'est pas une réponse à cette question, mais il résout en fait probablement le problème réel qui a conduit le PO à poser la question en premier lieu. Pour moi, c'était le vrai problème.
0xc0de

76

Documents VIM: le registre numéroté 0 contient le texte de la commande yank la plus récente, sauf si la commande a spécifié un autre registre avec ["x].

Par exemple, nous tirons "foo" et supprimons "bar" - le registre 0 contient toujours "foo"! Par conséquent, "foo" peut être collé en utilisant"0p


53

Il est pratique d'avoir un mappage facile qui vous permet de remplacer la sélection actuelle par un tampon.

Par exemple, lorsque vous mettez cela dans votre .vimrc

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

puis, après avoir copié quelque chose dans le registre (c'est-à-dire avec 'y'), vous pouvez simplement sélectionner le texte que vous souhaitez remplacer, et appuyez simplement sur 'r' sur votre clavier. La sélection sera remplacée par votre registre actuel.

Explication:

vmap - mapping for visual mode
"_d - delete current selection into "black hole register"
P - paste

1
Pour une version plus avancée, consultez: stackoverflow.com/questions/290465/…
Luc Hermitte

Je voudrais utiliservmap <C-P> "_dP
Harry Lee

7
Vous pouvez simplement mettre le texte sans supprimer la sélection. Par exemple, Vpremplace votre ligne actuelle par celle immédiatement tirée.
Bobby Marinoff

Cette solution ne résout pas le problème dqui est souvent utilisé pour la suppression.
Victor Yarema

35

J'ai mis ce qui suit dans mon 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

Maintenant, je tire et insère dans le registre du presse-papiers, et je n'ai plus à me soucier de ce qui se passe avec le registre par défaut. Un avantage supplémentaire est que je peux coller à partir d'autres applications avec un minimum de tracas. Je suis en train de perdre certaines fonctionnalités, je sais, mais je ne peux tout simplement pas garder trace de plus d'un registre / presse-papiers de toute façon.


6
Au lieu de tous ces remappages, vous pouvez également set clipboard=unnamedou set clipboard=unnamedplus, ce qui change le presse-papiers par défaut en *ou +, respectivement.
Steve

5
@Steve Si vous faites cela, alors d remplacera également le dernier coup sec dans le registre du presse-papiers, ce que la question essaie d'éviter.
79E09796

1
@ 79E09796, je ne voulais pas laisser entendre que ce serait le cas; Je commentais cette réponse et non la question d'origine.
Steve

1
Je les mets dans mon .vimrc et maintenant le tirage ne fonctionne pas. Une idée pourquoi?
confirmer le

2
@tba remplace noremap par nnoremap (deux n) et cela devrait fonctionner correctement.
meain

24

Pour l'exemple spécifique que vous avez donné, si je comprends bien la question, cela pourrait fonctionner:

*Highlight what you want to put somewhere else
*delete (d)
*Highlight the code that you want it to replace
*paste (p)

6
Cela fonctionne bien, sauf lorsque vous souhaitez coller plusieurs sélections.

23

Toutes les opérations de retrait et de suppression écrivent par défaut dans le registre sans nom. Cependant, le retrait le plus récent et la suppression la plus récente sont toujours stockés (séparément) dans les registres numérotés. Le registre 0contient le dernier coup sec. Les registres 1-9contiennent les 9 suppressions les plus récentes ( 1la plus récente étant).

En d'autres termes, une suppression écrase le dernier tirage dans le registre sans nom, mais il est toujours là dans le 0registre.L'astuce du registre des trous noirs ("_dd ) mentionnée dans les autres réponses fonctionne car elle empêche d'écraser le registre sans nom, mais ce n'est pas nécessaire.

Vous référencez un registre en utilisant des guillemets doubles, donc coller le texte le plus récemment tiré peut être fait comme ceci:

"0p

Ceci est une excellente référence:


16

Pour souligner ce qu'EBGreen a dit :

Si vous collez pendant la sélection de texte, le texte sélectionné est remplacé par le texte collé.

Si vous souhaitez copier du texte, puis le coller à plusieurs emplacements, utilisez "0ppour coller. Le registre numéroté 0 contient le texte de la commande yank la plus récente.


Vous pouvez également répertorier le contenu de tous vos registres:

:registers

Cette commande permet de déterminer plus facilement le registre que vous voulez lorsque vous faites quelque chose comme la réponse de dbr . Vous verrez également les registres /,%, #. (Voir aussi :help registers)


Et enfin, vérifiez cWet cWpour changer un mot incluant ou non un espace de fin. (L'utilisation du capital Winclut la ponctuation.)


10

Si vous utilisez Vim, vous aurez le mode visuel, qui est comme la sélection, mais avec la chose des modes de séparation qui est la base de vi / vim.

Ce que vous voulez faire, c'est utiliser le mode visuel pour sélectionner la source, puis tirer, puis utiliser à nouveau le mode visuel pour sélectionner la portée de la destination, puis coller dans le texte à partir du tampon par défaut.

Exemple:

Dans un fichier texte avec:

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

avec la séquence suivante: ggVjyGVkpvous terminerez par:

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

Expliqué:

  • gg: aller à la première ligne
  • V: démarrer le mode visuel avec des lignes entières
  • j: descendre d'une ligne (avec la sélection commencée sur les lignes précédentes, la sélection augmente d'une ligne vers le bas)
  • y: tirez sur le tampon par défaut (les deux lignes sélectionnées, et il vous sort automatiquement du mode visuel)
  • G: aller à la dernière ligne
  • V: démarrer le mode visuel (comme précédemment)
  • k: remonter d'une ligne (comme précédemment, avec le mode visuel activé, cela augmente la sélection d'une ligne)
  • p: coller (avec la sélection sur les deux dernières lignes, il remplacera ces lignes par ce qu'il y a dans le tampon - les 2 premières lignes dans ce cas)

Cela a le petit inconvénient qui place le dernier bloc sur le tampon, donc ce n'est pas souhaitable pour les collages répétés de la même chose, donc vous voudrez enregistrer la source dans un tampon nommé avec quelque chose comme "ay(dans un tampon appelé "a ") et collez avec quelque chose comme "ap(mais alors si vous programmez, vous ne voudrez probablement pas coller plusieurs fois mais créer une fonction et l'appeler, non? DROIT ?).

Si vous n'utilisez que vi, vous devrez utiliser des marques invisibles à la place du mode visuel, :he markpour en savoir plus, je suis désolé mais je ne suis pas très bon avec cette chose des marques invisibles, je suis assez contaminé par le mode visuel.



9

Une solution invasive minimale pour les paresseux:

Le registre 0contient toujours le dernier coup sec (comme Rafael , alex2k8 et idbrii l' ont déjà mentionné). Malheureusement, la sélection du registre 0tout le temps peut être assez ennuyeuse, donc ce serait bien si elle était putilisée "0par défaut. Ceci peut être réalisé en mettant les lignes suivantes dans votre .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 première ligne associe chaque ptrait à "0p. Cependant, cela empêche pd'accéder à d'autres registres. Par conséquent, tous les ptraits avec un registre explicitement sélectionné sont mappés à l'expression de ligne de commande équivalente dans la boucle for. La même chose est faite pour P.

De cette façon, le comportement standard est préservé, à l'exception de l'implicite pet des Ptraits, qui utilisent désormais le registre 0par défaut.

Astuce 1: La commande cut est maintenant "0dau lieu de juste d. Mais comme je suis paresseux, c'est beaucoup trop long pour moi;) Par conséquent, j'utilise le mappage suivant:

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

La touche de repère est \par défaut, vous pouvez donc facilement couper du texte en tapant \dou \D.

Astuce 2: le délai d'expiration par défaut pour les mappages multi-touches est assez court. Vous voudrez peut-être l'augmenter pour avoir plus de temps lors de la sélection d'un registre. Voir :help timeoutlenpour plus de détails, j'utilise:

set timeout timeoutlen=3000 ttimeoutlen=100

7

Eh bien, commencez par cette commande:

:h d

Ensuite, vous vous rendrez compte que vous pouvez supprimer dans un registre spécifique. De cette façon, vous ne modifierez pas ce qui se trouve dans votre registre par défaut.


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

5

Ma situation: en Normalmode, lorsque je supprime des caractères à l'aide de la xtouche, ces suppressions écrasent mon dernier registre - compliquant les modifications où je veux supprimer des caractères en utilisant xet collant quelque chose que j'ai dans mon registre le plus récent (par exemple, coller le même texte à deux ou plus d'endroits).

J'ai essayé la suggestion dans la réponse acceptée ( "_d), mais cela n'a pas fonctionné.

Cependant, à partir de la réponse / des commentaires acceptés sur /vi/122/performing-certain-operations-without-clearing-register , je l'ai ajouté à mon ~/.vimrc, qui fonctionne (vous devrez peut-être redémarrer Vim ):

nnoremap x "_x

Autrement dit, je peux maintenant exécuter mes commandes normales yank ( y), delete ( d) et paste ( p) - et les caractères que je supprime en utilisant xne remplissent plus les registres les plus récents.


4

Le texte supprimé, en mode insertion, ne va pas dans le registre par défaut.


2
mais la suppression de toute quantité significative de texte en mode par défaut est LENTE
Hamish Downer

3

Les deux solutions que j'utilise dans les bons contextes sont;

  • mettez en surbrillance ce que vous voulez remplacer en utilisant le VISUALmode Vims puis collez le registre.

Je l'utilise principalement par habitude car je n'ai trouvé la deuxième solution que beaucoup plus tard, par exemple

yiw   " yank the whole word
viwp  " replace any word with the default register
  • YankRing . Avec ce plugin, vous pouvez utiliser le raccourci clavier <ctrl>+<p>pour remplacer le registre numéroté précédent par celui que vous venez de coller.

Fondamentalement, vous allez coller comme vous le feriez, mais lorsque vous réalisez que vous avez depuis écrasé le registre par défaut, perdant ainsi ce que vous vouliez réellement coller, vous pouvez <C-P>le trouver et le remplacer dans l'historique YankRing!

L'un d'eux doit avoir des plugins ...



2

Dans la version Windows (probablement sous Linux également), vous pouvez utiliser le tampon copier / coller du système en utilisant "*y(c'est-à-dire précédant votre commande yank avec des guillemets doubles et un astérisque).

Vous pouvez ensuite supprimer les lignes remplaçables normalement et coller le texte copié à l'aide de "*p.


2

Je fais souvent une erreur en suivant les commandes pour 'y'ank puis' "_d'elete dans un trou noir puis 'p'aste. Je préfère' y'ank, puis supprimer comme je veux, puis '" 0p' de le registre 0, où le dernier texte copié est poussé.


2

Pour les utilisateurs emacs-evil, la fonction (evil-paste-pop)peut être déclenchée après le collage et passe en revue les entrées précédentes dans le kill-ring. En supposant que vous l'ayez lié à <C-p>(par défaut dans Spacemacs), vous frapperiez psuivi par autant <C-p>que nécessaire.


1

Pour les utilisateurs de Dvorak, une méthode très pratique consiste à supprimer simplement le texte inutile dans le registre "1 au lieu du" _ registre de trou noir, ne serait-ce que parce que vous pouvez appuyer sur "+ 1 avec la même pression de décalage et un mouvement de petit doigt rapide puisque 1 est la clé juste au-dessus "dans Dvorak (PLUS d est d'autre part, ce qui rend toute la commande rapide comme l'enfer).

Alors bien sûr, le "1 registre pourrait être utilisé pour d'autres choses à cause de sa commodité, mais à moins que vous ayez un objectif plus courant que de remplacer du texte, je dirais que c'est une assez bonne utilisation du registre.


1

Pour ceux d'entre vous qui sont principalement intéressés à ne pas écraser le registre sans nom lorsque vous remplacez un texte via la sélection virtuelle et le coller.

Vous pouvez utiliser la solution suivante qui est facile et qui fonctionne le mieux pour moi:

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

C'est à partir des réponses (et commentaires) ici: Comment coller sans écraser le registre

Il a d'abord dépassé la sélection, puis la sélection avec le nouveau texte est à nouveau sélectionnée (gv). Maintenant, le dernier registre utilisé en mode visuel (normalement le registre sans nom mais fonctionne également sans effet secondaire si vous utilisez un autre registre pour le coller). Et puis tirez à nouveau la nouvelle valeur dans le registre.

PS: Si vous avez besoin d'une variante plus simple qui fonctionne également avec le plugin intellj idea vim-simulation, vous pouvez prendre celle-ci (inconvénient: écraser le registre sans nom même si un autre registre a été donné pour le collage):

vnoremap p pgvy



0

La préférence occasionnelle de Vim pour la complexité par rapport à l'aspect pratique contraint l'utilisateur à appliquer des registres pour copier / supprimer des actions - quand le plus souvent, on veut juste coller ce qui a été copié et "oublier" ce qui a été supprimé.

Cependant, au lieu de combattre les registres compliqués de vim, rendez-les plus pratiques: choisissez un registre "par défaut" pour stocker votre dernière suppression. Par exemple, envoyez des suppressions au registre d (en laissant ac ouvert pour une utilisation ad-hoc; d est un joli mnémonique):

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

Cette approche empêche les suppressions de secouer les MAIS, mais ne perd pas l'enregistrement de la suppression - on peut coller (revenir) ce qui a été supprimé au lieu de le perdre dans un trou noir (comme dans la réponse acceptée). Dans l'exemple ci-dessus, ce rappel est effectué avec deux mappages p de leader. Un avantage de cette approche est qu'elle vous donne la possibilité de choisir quoi coller: (a) ce qui vient d'être retiré, ou (b) ce qui vient d'être supprimé.


0

les registres 0 à 9 sont les dernières choses que vous tirez ou coupez, etc., et N'INCLUREZ PAS les choses supprimées, etc. Si vous tirez / coupez quelque chose, c'est également dans le registre 0, même si vous dites des choses supprimées toute la journée après cela, enregistrez 0 est toujours le dernier truc que vous avez tiré / coupé.

yiw # va au registre par défaut et au registre 0

il tire le mot dans lequel se trouve le curseur

les éléments supprimés, etc. iront au registre par défaut, mais PAS au registre 0

en mode standard:

"0p #put le contenu du registre 0

en mode insertion:

ctrl-r 0 #put le contenu du registre 0

J'avais aussi un ami qui tirait / coupait toujours pour enregistrer x lol.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.