Più cursori nella posizione desiderata


13

Sto usando il plugin vim-multiple-cursors .

Vorrei mettere i cursori esattamente dove voglio. Ad esempio ( [x]sono le posizioni del cursore):

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

In Sublime Text normalmente posizionerei il primo cursore, quindi andrei alla posizione successiva con i tasti freccia e posizionerei il secondo.

C'è qualcosa di simile in VIM? Con questo plugin o un altro.

MODIFICARE

A seguito di un commento, il mio interesse a farlo è apparso quando ho provato a scrivere
\section[My first section in this book]{My first section in this book}
in un .texfile. La mia prima reazione è stata quella di scrivere \section[]{}e poi inserire due cursori per scrivere la stessa cosa all'interno di []e {}.

Un altro esempio potrebbe essere quello di aggiungere _someStuffdiversi nomi di variabili. Ad esempio, girare questo:

variable1 = 2
my_variable2 = 12
var3 = 14

in questo:

variable1_someStuff = 2
my_variable2_someStuff = 12
var3_someStuff = 14

Con più cursori posso farlo selezionando un cursore a colonna e poi andando alla fine della parola, quindi inserendo, ecc. Ma immagino che sarebbe facile scegliere esattamente dove voglio che siano i cursori.



1
Penso che una domanda importante da porsi sia: perché vuoi farlo? Cosa stai cercando di fare? L'uso di più cursori non è in realtà "seguendo il modo di Vim", probabilmente c'è un modo diverso di fare quello che vuoi, almeno altrettanto efficiente, usando le funzionalità integrate.
statox

@statox. Vedi modifica. Ho dato due esempi che mi sono venuti in mente. Il secondo che posso realizzare con il plug-in vim-multiple-cursors, ma il primo non posso, almeno in modo semplice.
tomasyany,

@ Nobe4. Grazie, la seconda sceneggiatura ce l'ha fatta.
tomasyany,

Risposte:


29

L'uso del cursore multiplo non è una cosa Vimmer

Come ho detto nei commenti usare i multi cursori (anche con un plugin) non è in realtà "seguire la via di Vim", capisco perfettamente che è attraente per qualcuno che proviene da Sublime-Text ma spesso puoi trovare alternative che sono almeno altrettanto efficiente con le funzionalità integrate di Vim.

Certo, trovare queste soluzioni alternative non è sempre facile e a volte ci vuole tempo ma con la tua esperienza Vim sarà più facile e vedrai che col tempo più cursori ti sembreranno totalmente inutili.

È bello, ma come posso trovare un modo alternativo?

Non esiste una risposta universale poiché dipende molto da ciò che stai cercando di fare, cercherò solo di dare alcuni suggerimenti sulle prime cose da provare:


Il comando punto .

Il comando Dot è probabilmente uno degli strumenti più potenti di Vim, ci consente semplicemente di ripetere l'ultima modifica. Non potrei spiegarlo meglio di Drew Neil nel suo Practical Vim . Penso che ogni Vimmer dovrebbe prendere in considerazione la lettura di questo libro.

Il punto di forza di questo comando è che l'ultima modifica può essere un'azione che lavora su un personaggio, una linea o un intero file. Ad esempio, una modifica può essere delimitata dal momento in cui si accede alla modalità di inserimento e dal momento in cui si ritorna alla modalità normale.

Con questo in mente è facile fare quello che volevi fare con il multicursore:

  • Innanzitutto impostiamo il nostro ambiente: scriviamo come hai suggerito

    \section[]{}

  • Quindi apporta una modifica ripetibile. Il cursore è ora attivo }, premi F[per tornare indietro sul [personaggio. Quindi inserire la modalità di inserimento con ie digitare My first section in this booke tornare alla modalità normale con ESC:

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

  • Ed ecco che arriva la parte magica: digitiamo f{per posizionare il cursore sul {personaggio e premiamo .per ripetere l'ultima modifica:

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

Tutta la sfida del comando punto è imparare a fare cambiamenti ripetibili: arriverà con grokking Vim ma la base è capire come effettuare il cambiamento in modo ripetibile.

Ad esempio, per inserire un punto e virgola alla fine di una riga, preferirai utilizzare A;invece di $a;. Perché?

Perché A;crea un'azione atomica, quindi quando la utilizzerai .su un'altra linea, non importa dove ti trovi nella linea, inserirai il punto e virgola alla fine. Considerando che quando si utilizza $a;dividere la modifica in due parti $ae l'inserimento di ;così se si utilizza .inserirà i punti e virgola sulla posizione corrente del cursore.

NOTA La formula magica in Vim è n.. Un flusso di lavoro davvero interessante è:

  • cerca il luogo con cui desideri effettuare una modifica /pattern
  • fai la tua modifica ripetibile
  • usare nper andare al posto successivo per modificare
  • usare .per ripetere la modifica
  • ripeti gli ultimi due passaggi: sei il re del mondo (o almeno delle modifiche)

macro

Le macro sono un altro strumento estremamente importante in Vim poiché ti consentono di registrare una sequenza di tasti e ripeterlo come se lo avessi digitato di nuovo.

Userò, ad esempio, il tuo secondo caso d'uso:

variable1 = 2
my_variable2 = 12
var3 = 14

Ancora una volta, l'importante è imparare a rendere efficienti le tue macro (ti darò un esempio di esempio subito dopo):

  • Posiziona il cursore sulla parola variable1e inizia a registrare la tua macro con qq. Questo significa "iniziare a registrare tutte le mie future battiture nel registro denominato q".

  • Inizia a scrivere la tua modifica:

    • 0 andare all'inizio della riga
    • e andare alla fine della prima parola
    • a da aggiungere dopo il cursore
    • .someStuff per aggiungere il testo desiderato
    • <Esc> per interrompere l'inserimento
    • j per passare alla riga successiva
    • q per interrompere la registrazione della macro
  • Otterrai:

variable1.someStuff = 2
my_variable2 = 12
var3 = 14
  • Ora puoi utilizzare la macro per ripetere la modifica. Dato che sei sulla riga giusta da modificare, puoi semplicemente eseguire la macro con @q. Poiché vogliamo eseguirlo due volte, puoi utilizzarlo 2@qe otterrai il seguente risultato:
variable1.someStuff = 2
my_variable2.someStuff = 12
var3.someStuff = 14

NOTA 1 Come avrai notato, l'uso 0eaall'inizio della macro era davvero importante. In effetti, se avessi posizionato il cursore alla fine della prima parola prima di registrare la macro ed eseguirla nuovamente, il risultato sarebbe stato:

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

Come cursore, il testo sarebbe stato inserito nella posizione del cursore dopo aver cambiato linea (cioè la fine della linea in questo caso)

NOTA 2 Le macro sono estremamente potenti e puoi persino creare macro ricorsive quando ti senti a tuo agio. Qui la tua macro avrebbe potuto essere:

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

Il finale @qavrebbe chiamato la macro da sola invece di usare 2@q; avresti appena usato @qe tutto il lavoro sarebbe stato fatto.


blocco visivo

Ecco un altro trucco che non si applica direttamente al tuo caso d'uso ma può essere davvero utile per modificare un gran numero di linee contemporaneamente. Otteniamo questo estratto di codice 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'); }

E se spostassi gli sprite da imagesa components?

Bene, puoi posizionare il cursore su idi imagese premere <C-v>. Ciò avvierà la modalità blocco visivo che consente di selezionare i blocchi. Ora puoi digitare t/ per selezionare la parola che desideri modificare e 2jper selezionare tutte le occorrenze della parola.

Dopodiché devi semplicemente digitare cper cambiare la parola e poi components. Quando uscirai dalla modalità di inserimento vedrai:

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'); }

Il comando globale

Il comando globale è uno strumento che consente di applicare un comando ex mode su linee corrispondenti a un modello, ancora una volta è un buon modo per applicare la stessa modifica in luoghi diversi senza bisogno di più cursori.

La sintassi è la seguente:

:[range] g / pattern / command

Per maggiori dettagli sul [range]parametro, consultare :h :range. Non lo descriverò in dettaglio qui, ricorderò semplicemente che %rappresenta l'intero file, '<,'> rappresenta l'ultima selezione e 1,5rappresenta le righe da 1 a 5 del file.

Questo parametro definisce le linee che verranno trattate dal comando globale. Se non viene specificato alcun intervallo, il comando globale utilizzerà %per impostazione predefinita.

L'argomento [modello] è un modello di ricerca utilizzato per il motore di ricerca. Poiché integra la cronologia delle ricerche, puoi lasciare vuoto questo campo e il comando globale utilizzerà quindi l'ultimo modello di ricerca nella cronologia delle ricerche.

Infine, il parametro [command] è un comando ex come probabilmente sei abituato.

Ora il comportamento del comando globale è piuttosto semplice:

  • Scorrere tutte le linee definite nel parametro [range]
  • Se la riga corrente corrisponde al modello definito, applicare il comando

Dato che il parametro [comando] è un comando ex, puoi fare molte cose. Prendiamo il seguente pseudo codice che non è abbastanza interessante e contiene molti messaggi di debug:

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"

Ora diciamo che sei sicuro che questo codice funzioni e che desideri eliminare queste echodichiarazioni inutili :

  • È possibile applicare il comando globale sull'intero file in modo da dover anteporre il comando con %(o con nulla poiché %l'intervallo predefinito è).

  • Sai che le linee che vuoi eliminare tutte corrispondono allo schema echo

  • Vuoi eliminare queste righe, quindi dovrai usare il comando :delete che può anche essere abbreviato comed

Quindi dovrai semplicemente usare la seguente funzione:

:%global/echo/delete

Che può anche essere abbreviato come

:g/echo/d

Si noti che %scomparso, globalè abbreviato come ge deletecome d. Come puoi immaginare, il risultato è:

var myList  = null
var i       = 0

myList = new List()

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

NOTA 1 Un punto importante che mi è occorso un po 'di tempo per capire è che il normalcomando è un comando ex, il che significa che è possibile utilizzarlo con il comando globale. Può essere davvero potente: diciamo che voglio duplicare tutte le righe che contengono l'eco, non ho bisogno di una macro o nemmeno della formula magica n.. Posso semplicemente usare

:g/echo/normal YP

E voilà:

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"

NOTA 2 "Ehi, e se volessi usare il mio comando su linee che non corrispondono a uno schema specifico?"

globalha un comando opposto vglobalabbreviato vche funziona esattamente come globalse non fosse che il comando verrà applicato su righe che non corrispondono al parametro [pattern]. In questo modo se applichiamo

:v/echo/d

Nel nostro esempio precedente otteniamo:

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

Il deletecomando è stato applicato su righe non contenute echo.


Qui spero che quei pochi suggerimenti possano darti idee su come sbarazzarti del tuo plugin multi cursore e usare Vim in modo Vim ;-)

Come puoi immaginare, questi esempi sono piuttosto semplici e sono fatti apposta per dimostrare che quando segui il modo di Vim raramente hai bisogno di diversi cursori. Il mio consiglio sarebbe quando incontri una situazione in cui pensi che sia utile, scrivila e prenditi un po 'di tempo dopo per trovare una soluzione migliore. Il 99% delle volte alla fine troverai un modo più veloce / più efficiente per farlo.

Inoltre mi ripeterò ancora una volta, ma ti incoraggio davvero a leggere Practical Vim di Drew Neil perché questo libro non parla di "Come fare questo o questo in Vim", si tratta di "Come imparare a pensare in modo Vim" che ti permetterà di costruire la tua soluzione ai tuoi problemi futuri in modo positivo.


PS Un ringraziamento speciale a @Alex Stragies per il suo lavoro di montaggio e le correzioni apportate a questo lungo post.


Risposta molto completa. In realtà conoscevo tutti quei comandi, ma non avrei mai pensato di usarli in quel modo ... Credo di aver bisogno di più pratica. Tuttavia, devo dire che a volte il 'vim-way' richiede più tempo del semplice utilizzo di alcuni plug-in (ad esempio, il tuo esempio CSS può essere fatto molto più rapidamente con il plug-in che ho citato), e talvolta richiede molto più breve (in realtà, il vasto la maggior parte delle volte vim è più veloce di qualsiasi editor di testo, se usato correttamente).
tomasyany,

A proposito, penso che la tua risposta sia già abbastanza completa. Lo accetterò, ma se vuoi aggiungere maggiori dettagli, per favore fallo e sarò lieto di leggerli.
tomasyany,

1
@tomasyany: In effetti a volte l'uso del "modo vim" potrebbe sembrare più lungo (non posso contare quante volte dedico più tempo alla creazione di una macro funzionante rispetto a se avessi apportato le modifiche manualmente) ma con la pratica alla fine diventa più veloce. Uso Vim da solo un anno e sono (molto) lungi dall'essere un esperto, ma sento che il mio editing migliora continuamente mentre pratico.
statox

1
Dovrebbe probabilmente menzionare anche l' gnoggetto di testo. Risolve alcuni casi d'uso di più cursori. Cerca con /, quindi dgno cgn, quindi ripeti con ..
Justin M. Keyes,

@Justin Non ho molta familiarità con gn, lo proverò e lo aggiungerò dopo. Grazie per il testa a testa!
statox

5

I tuoi casi d'uso per me sembrano voler conoscere il .comando da tastiera (ripeti l'ultimo comando di modifica)

  • Vai al primo posto, premi i, inserisci il tuo testo,<ESC>
  • passare alla posizione 2, premere .(Punto) ==> Il testo identico è inserito
  • Per spostarsi in basso di una riga qui e reinserirla (quando si inserisce in righe consecutive), premere <ALT>-j.

Il tuo esempio tex per me è risolto da:

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


È una soluzione molto carina. Conoscevo perfettamente il .comando chiave, ma non avrei mai pensato di usarlo in quel modo. Sono d'accordo che sia un bel modo. Ma la tua risposta in realtà non si riferisce alla vera domanda, quindi non sarebbe appropriato accettarla, immagino.
tomasyany,

1
Bene, la tua domanda (dopo aver aggiunto i casi d'uso desiderati) mi ha ricordato "Mi piacciono molto le mie forbici e voglio stringere una vite con loro. Dimmi come". E ti sto indicando un uso intelligente per un cacciavite;) (Ho aggiunto come risposta, perché non so, come fare la formattazione nei commenti)
Alex Stragies

4

Altri modi di Vim.

Primo compito:

\section[foobar baz]{foobar baz}

Flusso di lavoro:

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

Secondo compito:

variable1 = 2
my_variable2 = 12
var3 = 14

Comando:

3:norm ea_somestuff

Risultato:

variable1_somestuff = 2
my_variable2_somestuff = 12
var3_somestuff = 14
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.