Wiele kursorów w wybranej lokalizacji

14

Korzystam z wtyczki vim-multiple-cursors .

Chciałbym umieścić kursory dokładnie tam, gdzie chcę. Na przykład ( [x]są to pozycje kursora):

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

W Sublime Text zwykle umieszczam pierwszy kursor, a następnie przechodzę do następnej pozycji za pomocą klawiszy strzałek i umieszczam drugi.

Czy w VIM jest coś podobnego? Z tą wtyczką lub inną.

EDYTOWAĆ

Po komentarzu moje zainteresowanie pojawiło się podczas próby zapisu
\section[My first section in this book]{My first section in this book}
w .texpliku. Moją pierwszą reakcją było napisanie, \section[]{}a następnie umieszczenie dwóch kursorów, aby napisać to samo w []i {}.

Innym przykładem byłoby dodanie _someStuffpo kilku różnych nazwach zmiennych. Na przykład obróć to:

variable1 = 2
my_variable2 = 12
var3 = 14

zaangażowany w to:

variable1_someStuff = 2
my_variable2_someStuff = 12
var3_someStuff = 14

Z wieloma kursorami mogę to zrobić, wybierając kursor kolumny, a następnie przechodząc do końca słowa, a następnie wstawiając itd. Ale chyba łatwo byłoby wybrać dokładnie to, gdzie powinny być kursory.

tomasyany
źródło
1
Myślę, że ważnym pytaniem jest, dlaczego chcesz to zrobić? Co próbujesz zrobić? Używanie wielu kursorów nie jest tak naprawdę „zgodne ze sposobem Vima”, prawdopodobnie istnieje inny sposób robienia tego, co chcesz, przynajmniej tak wydajne, przy użyciu wbudowanych funkcji.
statox
@statox. Zobacz edycję. Podałem dwa przykłady, które przyszły mi do głowy. Drugi mogę wykonać za pomocą wtyczki vim-multiple-cursors, ale pierwszy nie mogę, przynajmniej w łatwy sposób.
tomasyany
@ Nobe4. Dzięki, drugi skrypt się udało.
tomasyany

Odpowiedzi:

30

Używanie wielu kursorów nie jest rzeczą Vimmer

Jak powiedziałem w komentarzach, używanie wielu kursorów (nawet z wtyczką) tak naprawdę nie „podąża drogą Vima”, całkowicie rozumiem, że jest atrakcyjne dla kogoś, kto pochodzi z Sublime-Text, ale często można znaleźć alternatywy, które są przynajmniej równie wydajny dzięki wbudowanym funkcjom Vima.

Oczywiście znalezienie tych alternatywnych rozwiązań nie zawsze jest łatwe i czasem zajmuje dużo czasu, ale będzie łatwiejsze dzięki doświadczeniu Vima i zobaczysz, że z czasem wiele kursorów będzie dla ciebie zupełnie bezużytecznych.

Fajnie, ale jak mogę znaleźć alternatywny sposób?

Nie ma uniwersalnej odpowiedzi, ponieważ zależy to w dużej mierze od tego, co próbujesz zrobić, postaram się tylko dać kilka wskazówek na temat pierwszych rzeczy do wypróbowania:


Polecenie kropki .

Polecenie Kropka jest prawdopodobnie jednym z najpotężniejszych narzędzi w Vimie, po prostu pozwala nam powtórzyć ostatnią zmianę. Nie potrafiłem tego lepiej wyjaśnić niż Drew Neil w jego Practical Vim . Myślę, że każdy Vimmer powinien rozważyć przeczytanie tej książki.

Siłą tego polecenia jest to, że ostatnią zmianą może być akcja działająca na znaku, linii lub całym pliku. Na przykład zmianę można oddzielić od momentu przejścia do trybu wstawiania i powrotu do trybu normalnego.

Mając to na uwadze, łatwo jest robić to, co chciałeś zrobić z multikursorem:

  • Najpierw skonfiguruj nasze środowisko: napiszmy tak, jak sugerowałeś

    \section[]{}

  • Następnie dokonaj powtarzalnej zmiany Kursor jest teraz włączony }, naciśnij, F[aby wrócić do [postaci. Następnie wejdź w tryb wstawiania za pomocą ii wpisz My first section in this booki wróć do normalnego trybu za pomocą ESC:

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

  • I tu pojawia się magiczna część: piszmy, f{aby umieścić kursor na {postaci i naciśnij, .aby powtórzyć ostatnią zmianę:

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

Wszystkie wyzwania związane z poleceniem kropki polegają na nauczeniu się, jak wprowadzać powtarzalne zmiany: przyjdzie z grokkingiem Vima, ale podstawową sprawą jest zrozumienie, jak dokonać zmiany w powtarzalny sposób.

Na przykład, aby wstawić średnik na końcu linii, której wolisz używać A;zamiast $a;. Dlaczego?

Ponieważ A;tworzy akcję atomową, więc kiedy użyjesz .w innej linii, bez względu na to, gdzie jesteś w linii, wstawisz średnik na końcu. Podczas gdy podczas używania $a;dzielisz zmianę na dwie części, $aa wstawienie ;tak, jeśli .go użyjesz , wstawi średnik na bieżącej pozycji kursora.

UWAGA Magiczna formuła w Vimie to n.. Naprawdę fajny przepływ pracy to:

  • wyszukaj miejsce, w którym chcesz dokonać edycji /pattern
  • dokonaj powtarzalnej edycji
  • użyj, naby przejść do następnego miejsca do edycji
  • użyj, .aby powtórzyć edycję
  • powtórz dwa ostatnie kroki: Jesteś królem świata (lub przynajmniej zmian)

makra

Makra są kolejnym niezwykle ważnym narzędziem w Vimie, ponieważ pozwala nagrywać sekwencję naciśnięć klawiszy i powtarzać je tak, jakbyś pisał je ponownie.

Jako przykład użyję twojego drugiego przypadku użycia:

variable1 = 2
my_variable2 = 12
var3 = 14

Jeszcze raz ważne jest, aby dowiedzieć się, jak sprawić, by makra były wydajne (zaraz podam licznik):

  • Umieść kursor na słowie variable1i zacznij rejestrować makro qq. Oznacza to „rozpocznij rejestrowanie wszystkich moich przyszłych naciśnięć klawiszy w rejestrze o nazwie q”.

  • Zacznij pisać od edycji:

    • 0 iść na początku linii
    • e przejść na końcu pierwszego słowa
    • a dołączać za kursorem
    • .someStuff dodać żądany tekst
    • <Esc> aby zatrzymać wstawianie
    • j przejść do następnej linii
    • q aby zatrzymać nagrywanie makra
  • Dostaniesz:

variable1.someStuff = 2
my_variable2 = 12
var3 = 14
  • Teraz możesz użyć makra, aby powtórzyć edycję. Gdy jesteś w odpowiedniej linii do edycji, możesz po prostu uruchomić makro za pomocą @q. Ponieważ chcemy go wykonać dwukrotnie, możesz użyć 2@qi otrzymasz następujący wynik:
variable1.someStuff = 2
my_variable2.someStuff = 12
var3.someStuff = 14

UWAGA 1 Jak być może zauważyłeś, użycie 0eana początku makra było bardzo ważne. Rzeczywiście, gdybyś umieścił kursor na końcu pierwszego słowa przed zarejestrowaniem makra i ponownym uruchomieniem go, wynik byłby następujący:

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

Jako kursor tekst zostałby wstawiony w miejscu kursora po zmianie linii (w tym przypadku na końcu linii)

UWAGA 2 Makra są niezwykle wydajne i możesz nawet tworzyć makra rekurencyjne, gdy czujesz się z nimi dobrze. Tutaj twoje makro mogło być:

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

Finał sam @qwywołałby makro zamiast używać 2@q; po prostu użyłbyś @qi cała praca zostałaby wykonana.


blok wizualny

Oto kolejna sztuczka, która nie dotyczy bezpośrednio twojego przypadku użycia, ale może być naprawdę przydatna do edycji dużej liczby wierszy jednocześnie. Pobierzmy fragment kodu 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'); }

Co jeśli przeniósł ikonek z imagesdo components?

Cóż można umieścić kursor na iod imagesi prasie <C-v>. Spowoduje to uruchomienie trybu bloków wizualnych, który pozwala wybierać bloki. Teraz możesz wpisać, t/ aby wybrać słowo, które chcesz zmienić, i 2jwybrać wszystkie wystąpienia tego słowa.

Następnie wystarczy wpisać, caby zmienić słowo, a następnie components. Po wyjściu z trybu wstawiania zobaczysz:

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

Globalne polecenie

Globalne polecenie jest narzędziem, które pozwala zastosować polecenie trybu ex na liniach pasujących do wzorca, to kolejny dobry sposób na zastosowanie tej samej zmiany w innym miejscu bez potrzeby używania wielu kursorów.

Składnia jest następująca:

:[range] g / pattern / command

Aby uzyskać więcej informacji na temat [range]parametru, zobacz :h :range. Nie będę go tutaj szczegółowo, przypomnę tylko, że %reprezentuje cały plik, '<,'> reprezentuje ostatni wybór i 1,5reprezentuje wiersze od 1 do 5 pliku.

Ten parametr określa linie, które będą traktowane przez polecenie globalne. Jeśli nie zostanie określony żaden zakres, %domyślnie zostanie użyte globalne polecenie .

Argument [wzorzec] to wzorzec wyszukiwania używany w wyszukiwarce. Ponieważ integruje historię wyszukiwania, możesz pozostawić to pole puste, a polecenie globalne użyje ostatniego wzorca wyszukiwania w historii wyszukiwania.

Na koniec parametr [polecenie] jest poleceniem ex, do czego prawdopodobnie jesteś przyzwyczajony.

Teraz zachowanie globalnego polecenia jest dość proste:

  • Iteruj przez wszystkie linie zdefiniowane w parametrze [zakres]
  • Jeśli bieżąca linia odpowiada zdefiniowanemu wzorowi, zastosuj polecenie

Ponieważ parametr [polecenie] jest poleceniem ex, możesz robić wiele rzeczy. Weźmy następujący pseudo kod, który nie jest całkiem interesujący i mamy wiele komunikatów do debugowania:

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"

Powiedzmy teraz, że masz pewność, że ten kod działa i chcesz usunąć te bezużyteczne echoinstrukcje:

  • Możesz zastosować globalną komendę do całego pliku, więc będziesz musiał poprzedzić komendę %(lub bez, ponieważ %jest to domyślny zakres).

  • Wiesz, że wszystkie wiersze, które chcesz usunąć, pasują do wzorca echo

  • Chcesz usunąć te wiersze, więc będziesz musiał użyć polecenia, :delete które można również skrócić jakod

Musisz po prostu użyć następującej funkcji:

:%global/echo/delete

Który można również skrócić jako

:g/echo/d

Zauważ, że %zniknął, globaljest skracany jako gi deletejako d. Jak możesz sobie wyobrazić wynik jest następujący:

var myList  = null
var i       = 0

myList = new List()

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

UWAGA 1 Ważną kwestią, która zajęła mi trochę czasu, było uświadomienie sobie, że normalpolecenie jest poleceniem ex, co oznacza, że ​​można go używać z poleceniem globalnym. To może być naprawdę potężne: powiedzmy, że chcę powielić wszystkie linie zawierające echo, nie potrzebuję makra ani nawet magicznej formuły n.. Mogę po prostu użyć

:g/echo/normal YP

I voila:

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"

UWAGA 2 „Hej, co jeśli chcę użyć polecenia w wierszach, które nie pasują do określonego wzorca?”

globalma vglobalskrócone polecenie przeciwne, vktóre działa dokładnie tak samo, globalz tym wyjątkiem, że polecenie zostanie zastosowane do linii, które nie pasują do parametru [wzorzec]. W ten sposób, jeśli się ubiegamy

:v/echo/d

W naszym poprzednim przykładzie otrzymujemy:

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

deleteKomenda została zastosowana na liniach, które nie zawartych echo.


Mam nadzieję, że te kilka wskazówek da ci pomysły, jak pozbyć się wtyczki z wieloma kursorami i używać Vima w sposób Vima ;-)

Jak możesz sobie wyobrazić, przykłady te są dość proste i mają na celu jedynie zademonstrowanie, że kiedy podążasz drogą Vima, naprawdę rzadko potrzebujesz kilku kursorów. Moja rada byłaby wtedy, gdy napotkasz sytuację, w której uważasz, że byłoby to przydatne, zapisz ją i poświęć trochę czasu na znalezienie lepszego rozwiązania. 99% czasu ostatecznie znajdziesz szybszy / bardziej wydajny sposób na zrobienie tego.

Powtórzę się jeszcze raz, ale naprawdę zachęcam do przeczytania Practical Vim autorstwa Drew Neila, ponieważ ta książka nie mówi o „Jak to zrobić ani o tym w Vimie”, ale o „Jak nauczyć się myśleć w sposób Vima” co pozwoli Ci w dobry sposób zbudować własne rozwiązanie przyszłych problemów.


PS Specjalne podziękowania dla @Alex Stragies za jego pracę edytorską i poprawki, które wprowadził do tego długiego postu.

statox
źródło
Bardzo kompletna odpowiedź. Właściwie znałem wszystkie te polecenia, ale nigdy nie myślałem o użyciu ich w ten sposób ... Chyba potrzebuję więcej praktyki. Muszę jednak powiedzieć, że czasami „vim-way” zajmuje więcej czasu niż użycie jakiejś wtyczki (na przykład, twój przykład CSS można zrobić znacznie szybciej dzięki wspomnianej wtyczce), a czasem zajmuje znacznie krótszy czas (w rzeczywistości przeważnie vim jest szybszy niż jakikolwiek edytor tekstu, jeśli jest właściwie używany).
tomasyany
Przy okazji, myślę, że twoja odpowiedź jest już dość kompletna. Zaakceptuję to, ale jeśli chcesz dodać więcej szczegółów, proszę, a chętnie je przeczytam.
tomasyany
1
@tomasyany: Rzeczywiście czasem używanie „vim way” może wydawać się dłuższe (nie mogę policzyć, ile razy spędzam więcej czasu na tworzeniu działającego makra, niż gdybym robił zmiany ręcznie), ale z praktyką w końcu staje się to szybsze. Używam Vima od zaledwie jednego roku i jestem (bardzo) daleki od bycia ekspertem, ale czuję, że moja edycja ciągle się poprawia podczas ćwiczeń.
statox
1
Prawdopodobnie powinien również wspomnieć o gnobiekcie tekstowym. Dotyczy niektórych przypadków użycia wielu kursorów. Wyszukaj za pomocą /, następnie dgnlub cgn, a następnie powtórz za pomocą ..
Justin M. Keyes,
@Justin Nie jestem do końca zaznajomiony z gn, spróbuję dodać go później. Dzięki za awans!
statox
5

Podane mi przypadki użycia brzmią tak, jakbyś chciał poznać .polecenie klawisza (powtórz ostatnie polecenie edycji)

  • Idź do pierwszego miejsca, naciśnij i, wstaw tekst,<ESC>
  • przejdź do lokalizacji 2, naciśnij .(Kropka) ==> Wstawiono identyczny tekst
  • Aby przejść tutaj o jedną linię w dół i wstawić ponownie (przy wstawianiu do kolejnych linii), naciśnij <ALT>-j.

Twój przykładowy tekst dla mnie rozwiązuje:

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

Alex Stragies
źródło
To całkiem fajne rozwiązanie. Znałem doskonale .kluczowe polecenie, ale nigdy nie myślałem o takim użyciu. Zgadzam się, że to dobry sposób. Ale twoja odpowiedź tak naprawdę nie odnosi się do prawdziwego pytania, więc chyba nie należy go akceptować.
tomasyany
1
Cóż, twoje pytanie (po dodaniu pożądanych przypadków użycia) przypomniało mi: „Naprawdę lubię moje nożyczki i chcę dokręcić nimi śrubę. Powiedz mi, jak”. A ja wskazuję ci sprytne użycie śrubokręta;) (dodałem jako odpowiedź, ponieważ nie wiem, jak formatować w komentarzach)
Alex Stragies
4

Więcej sposobów Vima.

Pierwsze zadanie:

\section[foobar baz]{foobar baz}

Przepływ pracy:

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

Drugie zadanie:

variable1 = 2
my_variable2 = 12
var3 = 14

Komenda:

3:norm ea_somestuff

Wynik:

variable1_somestuff = 2
my_variable2_somestuff = 12
var3_somestuff = 14
romainl
źródło