Plusieurs curseurs à l'emplacement souhaité


13

J'utilise le plugin vim-multiple-cursors .

Je voudrais placer les curseurs exactement où je veux. Par exemple ( [x]sont les positions du curseur):

Lorem ipsum dolor sit amet[1], consectetur adipiscing elit, 
sed do eiusmod tempor incididunt ut labore et dolore magna[2]
aliqua.

Dans Sublime Text, je mettrais normalement le premier curseur, puis j'allais à la position suivante avec les touches fléchées et je mettrais le second.

Y a-t-il quelque chose de similaire dans VIM? Avec ce plugin ou un autre.

ÉDITER

Suite à un commentaire, mon intérêt à le faire est apparu lorsque j'ai essayé d'écrire
\section[My first section in this book]{My first section in this book}
dans un .texfichier. Ma première réaction a été d'écrire \section[]{}puis de mettre deux curseurs afin d'écrire la même chose à l'intérieur du []et {}.

Un autre exemple serait d'ajouter _someStuffaprès plusieurs noms de variables différents. Par exemple, tournez ceci:

variable1 = 2
my_variable2 = 12
var3 = 14

en cela:

variable1_someStuff = 2
my_variable2_someStuff = 12
var3_someStuff = 14

Avec plusieurs curseurs, je peux le faire en sélectionnant un curseur de colonne, puis en allant à la fin du mot, puis en insérant, etc. Mais je suppose que je serais facile de choisir exactement où je veux que les curseurs soient.



1
Je pense qu'une question importante à poser est pourquoi voulez-vous faire cela? Qu'essayez-vous de faire? Utiliser plusieurs curseurs n'est pas vraiment "suivre la voie de Vim", il existe probablement une manière différente de faire ce que vous voulez, au moins aussi efficace, en utilisant les fonctionnalités intégrées.
statox

@statox. Voir modifier. J'ai donné deux exemples qui me sont venus à l'esprit. Le deuxième que je peux accomplir avec le plugin vim-multiple-cursors, mais le premier que je ne peux pas, au moins de manière simple.
tomasyany

@ Nobe4. Merci, le deuxième script a réussi.
tomasyany

Réponses:


29

Utiliser plusieurs curseurs n'est pas une chose Vimmer

Comme je l'ai dit dans les commentaires, utiliser plusieurs curseurs (même avec un plugin) n'est pas vraiment "suivre la voie Vim", je comprends parfaitement que cela soit attrayant pour quelqu'un qui vient de Sublime-Text mais vous pouvez souvent trouver des alternatives qui sont au moins aussi efficace avec les fonctionnalités intégrées de Vim.

Bien sûr, trouver ces solutions alternatives n'est pas toujours facile et parfois cela prend du temps mais cela deviendra plus facile avec votre expérience Vim et vous verrez qu'avec le temps, plusieurs curseurs vous sembleront totalement inutiles.

C'est cool mais comment trouver une alternative?

Il n'y a pas de réponse universelle car cela dépend beaucoup de ce que vous essayez de faire, je vais juste essayer de donner quelques conseils sur les premières choses à essayer:


La commande dot .

La commande Dot est probablement l'un des outils les plus puissants de Vim, elle nous permet simplement de répéter la dernière modification. Je ne pourrais pas l'expliquer mieux que Drew Neil dans son Practical Vim . Je pense que chaque Vimmer devrait envisager de lire ce livre.

La force de cette commande est que la dernière modification peut être une action sur un caractère, une ligne ou un fichier entier. Par exemple, un changement peut être délimité par le moment où vous entrez en mode insertion et le moment où vous revenez en mode normal.

Dans cet esprit, il est facile de faire ce que vous vouliez faire avec le multicurseur:

  • Commençons par configurer notre environnement: écrivons comme vous l'avez suggéré

    \section[]{}

  • Effectuez ensuite un changement reproductible. Le curseur est maintenant activé }, appuyez sur F[pour revenir sur le [personnage. Entrez ensuite en mode insertion avec iet tapez My first section in this booket revenez en mode normal avec ESC:

    \section[My first section in this book]{}

  • Et voici la partie magique: tapez f{pour placer le curseur sur le {personnage et appuyez sur .pour répéter le dernier changement:

    \section[My first section in this book]{My first section in this book}

Tout le défi de la commande dot est d'apprendre à faire des changements reproductibles: elle viendra avec grokking Vim mais l'essentiel est de comprendre comment faire votre changement de manière reproductible.

Par exemple, pour insérer un point-virgule à la fin d'une ligne, vous préférerez utiliser à la A;place de $a;. Pourquoi?

Parce que A;crée une action atomique, donc lorsque vous utiliserez .sur une autre ligne, peu importe où vous êtes sur la ligne, vous insérerez le point-virgule à la fin. Alors que lors de l'utilisation, $a;vous divisez votre modification en deux parties $aet l'insertion de ;si vous l'utilisez .insérera le point-virgule sur la position actuelle du curseur.

REMARQUE La formule magique de Vim est n.. Un flux de travail vraiment cool est:

  • recherchez l'endroit avec lequel vous souhaitez effectuer une modification /pattern
  • faire votre montage répétable
  • utiliser npour aller à l'endroit suivant pour éditer
  • utiliser .pour répéter l'édition
  • répétez les deux dernières étapes: vous êtes le roi du monde (ou au moins des modifications)

macros

Les macros sont un autre outil extrêmement important dans Vim car il vous permet d'enregistrer une séquence de frappes et de la répéter comme si vous l'aviez tapée à nouveau.

Je vais utiliser, à titre d'exemple, votre deuxième cas d'utilisation:

variable1 = 2
my_variable2 = 12
var3 = 14

Encore une fois, l'important est d'apprendre à rendre vos macros efficaces (je vais vous donner un exemple de compteur juste après):

  • Placez votre curseur sur le mot variable1et commencez à enregistrer votre macro avec qq. Cela signifie "commencer à enregistrer toutes mes futures frappes dans le registre nommé q".

  • Commencez à faire votre saisie:

    • 0 aller au début de la ligne
    • e aller à la fin du premier mot
    • a ajouter après votre curseur
    • .someStuff pour ajouter le texte voulu
    • <Esc> pour arrêter l'insertion
    • j aller sur la ligne suivante
    • q pour arrêter l'enregistrement de la macro
  • Tu auras:

variable1.someStuff = 2
my_variable2 = 12
var3 = 14
  • Vous pouvez maintenant utiliser la macro pour répéter votre modification. Comme vous êtes sur la bonne ligne pour éditer, vous pouvez simplement exécuter la macro avec @q. Comme nous voulons l'exécuter deux fois, vous pouvez l'utiliser 2@qet vous obtiendrez le résultat suivant:
variable1.someStuff = 2
my_variable2.someStuff = 12
var3.someStuff = 14

REMARQUE 1 Comme vous l'avez peut-être remarqué, l'utilisation 0eaau début de la macro était vraiment importante. En effet, si vous aviez placé votre curseur à la fin du premier mot avant d'enregistrer la macro et de l'exécuter à nouveau, votre résultat aurait été:

variable1.someStuff = 2
my_variable2 = 12.someStuff
var3 = 14.someStuff

Comme votre curseur, le texte aurait été inséré à la position du curseur après le changement de ligne (c'est-à-dire la fin de la ligne dans ce cas)

REMARQUE 2 Les macros sont extrêmement puissantes et vous pouvez même créer des macros récursives lorsque vous êtes à l'aise avec elles. Ici, votre macro aurait pu être:

`0ea.someStuff<Esc>j@q`

La finale @qaurait appelé la macro seule au lieu d'utiliser 2@q; vous auriez juste utilisé @qet tout le travail aurait été fait.


bloc visuel

Voici une autre astuce qui ne s'applique pas directement à votre cas d'utilisation, mais qui peut être très utile pour modifier un grand nombre de lignes en même temps. Obtenons cet extrait de code CSS:

li.one   a{ background-image: url('/images/sprite.png'); }
li.two   a{ background-image: url('/images/sprite.png'); }
li.three a{ background-image: url('/images/sprite.png'); }

Et si vous déplaciez les sprites de imagesvers components?

Eh bien , vous pouvez mettre votre curseur sur la ide imageset appuyez sur <C-v>. Cela lancera le mode de bloc visuel qui permet de sélectionner des blocs. Vous pouvez maintenant taper t/ pour sélectionner le mot que vous souhaitez modifier et 2jpour sélectionner toutes les occurrences du mot.

Après cela, vous devez simplement taper cpour changer le mot, puis components. Lorsque vous sortirez du mode insertion, vous verrez:

li.one   a{ background-image: url('/components/sprite.png'); }
li.two   a{ background-image: url('/components/sprite.png'); }
li.three a{ background-image: url('/components/sprite.png'); }

La commande globale

La commande globale est un outil qui permet d'appliquer une commande en mode ex sur des lignes correspondant à un motif, encore une fois, c'est un bon moyen d'appliquer le même changement à un endroit différent sans avoir besoin de plusieurs curseurs.

La syntaxe est la suivante:

:[range] g / pattern / command

Pour plus de détails sur le [range]paramètre, veuillez consulter :h :range. Je ne le détaillerai pas ici, je rappellerai simplement que %représente le fichier entier, '<,'> représente la dernière sélection et 1,5représente les lignes 1 à 5 du fichier.

Ce paramètre définit les lignes qui seront traitées par la commande globale. Si aucune plage n'est spécifiée, la commande globale utilisera %par défaut.

L'argument [pattern] est un modèle de recherche que vous utilisez habituellement avec le moteur de recherche. Comme il intègre l'historique de recherche, vous pouvez laisser ce champ vide et la commande globale utilisera alors le dernier modèle de recherche de l'historique de recherche.

Enfin, le paramètre [command] est une commande ex comme vous en avez probablement l'habitude.

Maintenant, le comportement de la commande globale est assez simple:

  • Itérer sur toutes les lignes définies dans le paramètre [range]
  • Si la ligne actuelle correspond au modèle défini, appliquez la commande

Comme le paramètre [command] est une commande ex, vous pouvez faire beaucoup de choses. Prenons le pseudo-code suivant qui n'est pas assez intéressant et contient beaucoup de messages de débogage:

var myList  = null
var i       = 0

myList = new List()
echo "List instantiated"

for (i=0; i<10; i++)
    myList.Add(i)
    echo i . " added to the list"

echo "end of for loop"

Supposons maintenant que vous êtes sûr que ce code fonctionne et que vous souhaitez supprimer ces echoinstructions inutiles :

  • Vous pouvez appliquer votre commande globale sur l'ensemble du fichier, vous devrez donc ajouter la commande %(ou rien car %la plage par défaut).

  • Vous savez que les lignes que vous souhaitez supprimer correspondent toutes au modèle echo

  • Vous souhaitez supprimer ces lignes, vous devrez donc utiliser la commande :delete qui peut également être abrégée end

Vous devrez donc simplement utiliser la fonction suivante:

:%global/echo/delete

Qui peut également être abrégé en

:g/echo/d

Notez que %disparu, globalest abrégé au fur get à deletemesure d. Comme vous pouvez l'imaginer, le résultat est:

var myList  = null
var i       = 0

myList = new List()

for (i=0; i<10; i++)
    myList.Add(i)

NOTE 1 Un point important qui m'a pris du temps à réaliser est que la normalcommande est une commande ex ce qui signifie que vous pouvez l'utiliser avec la commande globale. Cela peut être vraiment puissant: disons que je veux dupliquer toutes les lignes qui contiennent de l'écho, je n'ai pas besoin d'une macro ou même de la formule magique n.. Je peux simplement utiliser

:g/echo/normal YP

Et le tour est joué:

var myList  = null
var i       = 0

myList = new List()
echo "List instantiated"
echo "List instantiated"

for (i=0; i<10; i++)
    myList.Add(i)
    echo i . " added to the list"
    echo i . " added to the list"

echo "end of for loop"
echo "end of for loop"

NOTE 2 "Hé, et si je veux utiliser ma commande sur des lignes qui ne correspondent pas à un modèle spécifique?"

globala une commande opposée vglobalabrégée vqui fonctionne exactement comme globalsauf que la commande sera appliquée sur les lignes qui ne correspondent pas au paramètre [pattern]. De cette façon, si nous appliquons

:v/echo/d

Sur notre exemple précédent, nous obtenons:

echo "List instantiated"
    echo i . " added to the list"
echo "end of for loop"

La deletecommande a été appliquée sur des lignes qui ne contenaient pas echo.


Ici, j'espère que ces quelques conseils vous donneront des idées sur la façon de se débarrasser de votre plugin multi-curseur et d'utiliser Vim à la manière de Vim ;-)

Comme vous pouvez l'imaginer, ces exemples sont assez simples et sont juste faits pour démontrer que lorsque vous suivez la voie Vim, vous avez vraiment rarement besoin de plusieurs curseurs. Mon conseil serait de rencontrer une situation où vous pensez que ce serait utile, de l'écrire et de prendre un peu de temps plus tard pour trouver une meilleure solution. 99% du temps, vous finirez par trouver un moyen plus rapide / plus efficace de le faire.

Je vais également me répéter une fois de plus, mais je vous encourage vraiment à lire Practical Vim de Drew Neil parce que ce livre ne traite pas de "Comment faire cela ou cela à Vim", il s'agit de "Comment apprendre à penser à la manière de Vim" ce qui vous permettra de construire votre propre solution à vos problèmes futurs dans le bon sens.


PS Un merci spécial à @Alex Stragies pour son travail d'édition et les corrections qu'il a apportées à ce long post.


Réponse très complète. En fait, je connaissais toutes ces commandes, mais je n'ai jamais pensé à les utiliser comme ça ... Je suppose que j'ai besoin de plus de pratique. Cependant, je dois dire que parfois le 'vim-way' prend plus de temps que d'utiliser simplement un plugin (par exemple, votre exemple CSS peut être fait beaucoup plus rapidement avec le plugin que j'ai mentionné), et parfois cela prend beaucoup plus court (en fait, le vaste la plupart du temps, vim est plus rapide que n'importe quel éditeur de texte, s'il est utilisé correctement).
tomasyany

Btw, je pense que votre réponse est déjà assez complète. Je l'accepterai, mais si vous souhaitez ajouter plus de détails, veuillez le faire et je serai heureux de les lire.
tomasyany

1
@tomasyany: En effet, parfois, utiliser la "méthode vim" peut sembler plus long (je ne peux pas compter combien de fois je passe plus de temps à créer une macro de travail que si j'avais fait les modifications manuellement) mais avec la pratique, cela finit par devenir plus rapide. J'utilise Vim depuis seulement un an et je suis (très) loin d'être un expert mais je sens que mon montage s'améliore continuellement au fur et à mesure que je pratique.
statox

1
Devrait probablement également mentionner l' gnobjet texte. Il traite de certains cas d'utilisation de plusieurs curseurs. Recherchez avec /, puis dgnou cgn, puis répétez avec ..
Justin M. Keyes

@Justin que je ne connais pas vraiment, gnje vais essayer et l'ajouter après. Merci pour la tête haute!
statox

5

Vos cas d'utilisation donnés me semblent vouloir connaître le .raccourci clavier (répéter la dernière commande d'édition)

  • Accédez à la première place, appuyez sur i, insérez votre texte,<ESC>
  • passer à l'emplacement 2, appuyez sur .(Dot) ==> Le texte identique est inséré
  • Pour descendre d'une ligne ici et réinsérer (lors de l'insertion dans des lignes consécutives), appuyez sur <ALT>-j.

Votre exemple tex pour moi est résolu par:

I\section[]{}<ESC>hhiMy first Sec...<ESC>lll.


C'est une assez bonne solution. Je connaissais parfaitement le .commandement clé, mais je n'ai jamais pensé à l'utiliser de cette façon. Je suis d'accord que c'est une belle façon. Mais votre réponse ne fait pas réellement référence à la vraie question, il ne serait donc pas approprié de l'accepter, je suppose.
tomasyany

1
Eh bien, votre question (après avoir ajouté les cas d'utilisation souhaités) m'a rappelé "j'aime vraiment mes ciseaux et je veux serrer une vis avec eux. Dites-moi comment". Et moi, je vous pointe vers une utilisation astucieuse pour un tournevis;) (J'ai ajouté comme réponse, parce que je ne sais pas, comment faire le formatage dans les commentaires)
Alex Stragies

4

Plus de façons Vim.

Première tâche:

\section[foobar baz]{foobar baz}

Flux de travail:

\section[]{}
hh
ifoobar baz<Esc>
$.

Deuxième tâche:

variable1 = 2
my_variable2 = 12
var3 = 14

Commander:

3:norm ea_somestuff

Résultat:

variable1_somestuff = 2
my_variable2_somestuff = 12
var3_somestuff = 14
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.