Vim: Remplacement d'une ligne par une autre tirée avant

112

Au moins une fois par jour, j'ai la situation suivante:

A: This line should also replace line X
...
X: This is line should be replaced

Je crois que je n'effectue pas cette tâche efficacement.

Ce que je fais:

  • Aller à la ligne A: AG
  • Yank ligne A: yy
  • Aller à la ligne X: XG
  • Coller la ligne A: P
  • Passer à l'ancienne ligne: j
  • Supprimer l'ancienne ligne: dd

Cela présente l'inconvénient supplémentaire que la ligne X est maintenant dans le registre par défaut, ce qui est gênant si je trouve une autre ligne qui devrait être remplacé par A. Emmener à coller à partir d' un registre supplémentaire ( « ayy , » aP ) rend cette tâche simple , même moins efficace.

Mes questions:

  • Ai-je manqué une commande Vim intégrée pour remplacer une ligne tirée auparavant?
  • Sinon, comment puis-je lier ma propre commande qui laisse (ou restaure) la ligne tirée dans le registre par défaut?
croustillant
la source
2
C'est mon plus gros problème avec le modèle d'édition de Vim. J'adorerais connaître une solution. Un éditeur CUA fait la distinction entre couper et supprimer, vous n'avez donc qu'à couper du texte, puis vous pouvez supprimer et coller tout ce que vous voulez. Avec Vim, toute suppression que vous faites efface votre texte coupé. Vous finissez par utiliser beaucoup plus de frappes que vous le feriez avec un autre éditeur.
Mud
3
YankRing
ajreal
@Mud apprendre :moveet le trou noir registre ( _) (ou en fait, seulement registres)
sehe
2
@sehe Je connais parfaitement les registres, mais cela ajoute 4 frappes par opération de couper / coller et demande plus de prévoyance. Lorsque vous effectuez beaucoup de modifications, cela s'additionne rapidement.
Mud
Outre la sauvegarde de quelques octets de mémoire, y a-t-il un avantage à utiliser le registre du trou noir par rapport à tout autre registre? Je dirais que tout registre peut être un registre de trou noir si vous ne le relisez pas.
sleblanc

Réponses:

91

Ce que je ferais:

  1. aG
  2. Y
  3. xG
  4. Vp

Vous ne devez pas quitter le mode normal, mais il ne Yank la ligne. Vous pouvez cependant utiliser V"0pqui mettra toujours la ligne tirée à l'étape 2.

la glace
la source
11
@duddle: oui, Yest synonyme deyy
icecrime
8
Les étapes 1 et 2 peuvent être combinées en utilisant: ay [Ex: 20y] Suivi par Vp devrait faire l'affaire. Vous n'avez pas besoin d'aller à une ligne pour le retirer.
Bharad
2
Si vous écrasez des lignes supplémentaires avec ccCTRL + r0ESC au lieu de V "0p, toutes les lignes suivantes peuvent être remplacées par juste. (Le répéteur)
Jordan Morris
Yest un synonyme de yy, mais je suggère de le remapper y$pour correspondre à Det C.
mgold
Consultez la réponse de Jordan Morris stackoverflow.com/users/970673/jordan-morris ci-dessous - utilise vraiment les commandes vim au maximum en vous permettant de répéter la commande plusieurs fois.
JESii
105

Vp: sélectionnez la ligne, collez ce qui a été retiré

Dorian
la source
3
VPfonctionne tout aussi bien, ce qui est pratique car vous pouvez maintenir Shift enfoncé pendant toute la séquence.
George Hilliard
24
très belle astuce, même si cela vaut la peine de noter une mise en garde (peut-être) importante: cela provoque la mise à jour du registre yank avec le contenu de la ligne qui est en cours d'écrasement, donc il se peut qu'il ne joue pas bien avec certaines tâches - par exemple si vous voulez écraser la même ligne sur plusieurs destinations.
underscore_d
8
@underscore_d, il joue bien si vous le faites V"0p, ce qui colle à partir du dernier registre copié.
timblaktu
@timblaktu Pouvez-vous expliquer ce que V"0pfait? V passe en mode ligne de ligne visuelle et p est pour coller. Quels sont "et 0 pour Merci?
theprogrammer
43

Cela présente l'inconvénient supplémentaire que la ligne X est maintenant dans le registre par défaut, ce qui est ennuyeux si je trouve une autre ligne qui devrait être remplacée par A.

Pour supprimer du texte sans affecter les registres normaux, vous pouvez utiliser le registre du trou noir "_:

"_dd
Eugène Yarmash
la source
10
J'ai ajouté quelques applications à mon .vimrc faire det ddtoujours utiliser le trou noir et xet xxfaire ce que la plupart des éditeurs appellent un « cut » (suppression et enregistrez -le registre par défaut):noremap x d noremap xx dd noremap d "_d noremap dd "_dd
IMSoP
2
Je me méfie du remappage des choses dans VIM, car cela peut ne pas être facile sur d'autres ordinateurs, ou dans des plugins de style VIM pour les IDE. Les concepteurs de VIM ont également tendance à avoir résolu des problèmes avec les mappages par défaut si vous creusez vraiment.
Jordan Morris
15

En m'appuyant sur les réponses qui suggèrent d'utiliser Vpou VPde coller sur une ligne - pour éviter de changer le contenu du registre yank, je trouve que la commande la plus ergonomique est simplement:

VPY

RichardW
la source
Il s'agit de la solution la plus simple qui laisse le contenu de l'extraction inchangé. Merci beaucoup!
heylookltsme
14
  1. yy
  2. j (placez-vous sur la ligne que vous souhaitez remplacer), puis
  3. Vp (v majuscule puis p, remplacera par le contenu copié)
Mariano Anaya
la source
impressionnant! Très court en effet et permet de sélectionner facilement plusieurs lignes avec le mode visuel. Il garde également le tampon de pâte intact. C'est ennuyeux quand dd écrase ce tampon ...
Aktau
@Aktau cela ne laisse pas le tampon intact.
Jordan Morris
9

J'utiliserais le mode ligne de commande (Ex) et ferais les deux commandes suivantes

:XmA
:Ad

Cela déplace simplement la ligne X juste sous A, puis la suppression de A déplace cette ligne vers le haut

Par exemple

:7m3
:3d
Ericgamliel
la source
Pouvez-vous donner un exemple? Quand j'appuie par exemple sur 50Gm30G, Vim passe à la ligne 50, puis au bas et c'est tout. Aussi: l'annonce ne fait rien pour A = 50 ou A = 50G
croustillant le
7
  1. Déplacez-vous au début de la première ligne.

  2. y, $- copier la ligne sans le saut de ligne à la fin

  3. Déplacez-vous au début de la ligne cible.

    1. V, p- remplacer une seule ligne cible

    2. c, c, Ctrlr, 0, Esc- remplacer la ligne de cible avec le coup sec d' origine

  4. Passez au début de la ligne cible suivante.

  5. . - répète la commande émise en 4.2.

Remarques:

  • 4.1 est y, $parce que si vous le faites y, you Yvous copierez le linebreak et Ctrlr0ajoute en fait le saut de ligne en dessous de votre ligne cible.

  • 4.2 remplace V p, ce qui ne fonctionne pas avec la répétition car techniquement la dernière action est la suppression, donc .supprimerait simplement une ligne.

  • Si quelqu'un sait comment lancer «remplacer la ligne actuelle par le registre» à partir du mode EX (ligne de commande), j'aimerais avoir de vos nouvelles (et savoir où vous avez trouvé la documentation). Il peut y avoir une commande EX répétable qui est plus rapide que 4.2 et / ou qui n'a pas la mise en garde de saut de ligne.

Jordan Morris
la source
1
L'étape 4.2 est le tueur ici, car vous pouvez maintenant répéter tout le processus avec la commande dot comme dans 4.3 - c'est ce que vim est tout!
JESii
1
Je ne comprends pas ça. «AG» met mon créateur à la fin de la ligne, entre en mode insertion et entre un «G». Qu'est-ce que je ne comprends pas?
gustafbstrom
@gustafbstrom juste critique - désolé le A était censé représenter le numéro de ligne, mais je n'ai pas réussi à le souligner. Édité.
Jordan Morris
5

Voici ce que je ferais

  • Déplacer le début de la ligne A, AG(où A est évidemment un numéro de ligne)
  • Yank ligne vers un registre, par exemple a (sans nouvelle ligne). Type"ay$
  • Déplacer pour insérer une ligne, XG
  • Ligne de remplacement, S
  • Insérer du registre a, Ctrl-Ra
Brian Rasmussen
la source
4

Vous pouvez l'utiliser avec le mode visuel.

  • Allez à la ligne A: AG
  • Sélectionnez la ligne avec le mode visuel: VESC
  • aller à la ligne X: XG
  • Entrez en mode de remplacement pour la ligne: S
  • Collez la ligne que vous avez copiée: shift+ insert(ou tout autre mappage que vous avez pour coller à partir du presse-papiers).
Nathan Fellman
la source
Ah. Je ne savais pas V et S . Cependant, vos étapes ne fonctionnent pas pour moi car je ne tire pas sur le presse-papiers de mon système d'exploitation, qui est le seul auquel je peux accéder en mode insertion. Je devrais donc d'abord quitter le mode insertion.
croustillant
3

Vous pouvez également faire:

Vy (in normal mode at the line you want to copy)
Vp (in normal mode at the line you want to replace)
  • Ne crée pas d'espaces ni de fins de ligne.
  • Le curseur est placé au début du texte copié.

Les mêmes touches peuvent être utilisées pour copier / coller plus d'une ligne.

V (in normal mode at what you want to yank)
(use jk to move the selection)
y (to yank the selection)
V (in normal mode at where you want to paste)
(use jk to move the selection)
p (to replace the selection with the yanked lines)
Kozmonaut
la source
2

Vous pouvez utiliser ces commandes en mode normal:

:AmX | Xd

la mcommande est pour m[ove], qui déplace le numéro de ligne A après le numéro de ligne X, si vous voulez copier au lieu de déplacer la ligne, utilisez co[py]. la dcommande est pour d[elete].

Vous pouvez déplacer (copier en utilisant co) une plage de lignes en utilisant

:start,end m X
Nafaa Boutefer
la source
2

À la lumière du récent commentaire de cicld (merci!), Je vois que je n'ai pas bien saisi le problème d'origine. Le déplacement de la ligne n'est pas approprié, mais la copie l'est (puisque la ligne est tirée). Je la réviserais donc pour:

:1t20:20d_
  1. Copiez la 1ère ligne (la :tcommande est un alias pour :copy) après la ligne 20 (la placera sur la ligne 21)

  2. Supprimer la ligne 20, mettre la ligne supprimée dans le registre 'blackhole' ( _) (c'est-à-dire n'affectant pas le tampon de yank actuel)

Comme mentionné dans le commentaire récent, cela n'affectera pas la position actuelle du curseur.

nkalvi
la source
1
  1. : ay (où a est le numéro de ligne. Exemple: 20y). Cela tire une ligne (jeu de mots).
  2. Vp
Bharad
la source
1

Je trouve qu'il est plus facile d'utiliser la commande Ex pour cela; ex. pour déplacer la ligne 9 à 46:

 :46|9m.|-1d

Cela déplacera le curseur sur la ligne 46, déplacera la ligne 9 sous le courant, puis supprimera la ligne précédente (puisque la ligne déplacée est la ligne actuelle).

Ou en utilisant la (les) marque (s), en utilisant la marque 'a':

:46ma a|9m'a|'ad
nk3181544
la source
La beauté des commandes EX réside dans le fait que vous pouvez les exécuter où que se trouve votre curseur (en mode normal). Je préfère :1m20|.+1d(déplacer la ligne 1 à la ligne 20 et supprimer la ligne suivante, c'est-à-dire le texte qui était à la ligne 20 précédemment). Même idée cependant!
circld le
1

Je dois souvent y une ligne et la remplacer à plusieurs endroits, chacun ayant une valeur différente (ce qui signifie que je ne peux pas faire une regex).

Y pour extraire la ligne d'origine souhaitée

et ensuite sur chaque ligne que vous souhaitez remplacer, VpzeroY

Ron
la source
0

j'utiliserais simplement le registre "Trou noir":

donné:

nnoremap <Cd> "_dd

la solution serait:

<Cd> yy

j5shi
la source