Twój problem z Vimem polega na tym, że nie grokujesz vi .
Wspominasz o cięciu yy
i narzekasz, że prawie nigdy nie chcesz przecinać całych linii. W rzeczywistości programiści, edytując kod źródłowy, bardzo często chcą pracować na całych liniach, zakresach linii i blokach kodu. Jest to jednak yy
tylko jeden z wielu sposobów wciągnięcia tekstu do anonimowego bufora kopii (lub „rejestracji”, jak to się nazywa w vi ).
„Zen” vi polega na tym, że mówisz językiem. Inicjał y
jest czasownikiem. Oświadczenie yy
jest synonimem y_
. y
Jest podwojona do ułatwienia pisania, ponieważ jest to takie wspólne działanie.
Można to również wyrazić jako dd
P
(usuń bieżący wiersz i wklej kopię z powrotem na miejsce; pozostawiając kopię w rejestrze anonimowym jako efekt uboczny). Te y
i d
„Czasowniki” wziąć każdy ruch jako „podmiot”. Zatem yW
„ciągnij stąd (kursor) do końca bieżącego / następnego (dużego) słowa” i y'a
„ciągnij stąd do wiersza zawierającego znak o nazwie„ a ”.
Jeśli rozumiesz tylko podstawowe ruchy kursora w górę, w dół, w lewo i w prawo, vi nie będzie dla ciebie bardziej produktywne niż kopia „notatnika”. (W porządku, nadal będziesz miał podświetlanie składni i możliwość obsługi plików większych niż piddling ~ 45 KB lub więcej; ale pracuj tutaj ze mną).
vi ma 26 „znaków” i 26 „rejestrów”. Znak jest ustawiany w dowolnym miejscu kursora za pomocą m
polecenia. Każdy znak jest oznaczony pojedynczą małą literą. W ten sposób ma
ustawia znak „ a ” na bieżącą lokalizację i mz
ustawia znak „ z ”. Możesz przejść do wiersza zawierającego znak, używając polecenia '
(pojedynczy cudzysłów). W ten sposób 'a
przechodzi na początek linii zawierającej znak „ a ”. Możesz przejść do dokładnej lokalizacji dowolnego znaku za pomocą polecenia `
(cudzysłów). W ten sposób `z
przejdzie bezpośrednio do dokładnej lokalizacji znaku „ z ”.
Ponieważ są to „ruchy”, można je również wykorzystać jako tematy innych „stwierdzeń”.
Tak więc jednym ze sposobów wycinania dowolnego tekstu byłoby upuszczenie znaku (zwykle używam „ a ” jako mojego „pierwszego” znaku, „ z ” jako mojego następnego znaku, „ b ” jako innego, a „ e ” jako innego jeszcze inny (nie przypominam sobie, aby kiedykolwiek interaktywnie używać więcej niż czterech znaków w ciągu 15 lat używania vi ; jeden tworzy własne konwencje dotyczące używania znaków i rejestrów przez makra, które nie zakłócają interaktywnego kontekstu). na drugim końcu pożądanego tekstu; możemy zacząć od drugiego końca, to nie ma znaczenia. Następnie możemy po prostu użyć d`a
do wycięcia lub .y`a
kopiowania. W ten sposób cały proces ma narzut 5 naciśnięć klawiszy (sześć, jeśli zaczęliśmy od „insert” „tryb i potrzebneEsctryb komend out). Po wycięciu lub skopiowaniu wklejanie kopii jest jednym naciśnięciem klawisza:p
Mówię, że jest to jeden ze sposobów wycinania lub kopiowania tekstu. Jest to jednak tylko jeden z wielu. Często możemy bardziej zwięźle opisać zakres tekstu bez przesuwania kursora i upuszczania znaku. Na przykład, jeśli jestem w akapicie tekstu, mogę użyć {
i }
przejść odpowiednio na początek lub koniec akapitu. Aby przenieść akapit tekstu, wycinam go {
d}
(3 naciśnięcia klawiszy). (Jeśli zdarzyło mi się być w pierwszej lub ostatniej linii akapitu, mogę po prostu użyć odpowiednio d}
lub d{
.
Pojęcie „akapit” domyślnie przyjmuje coś, co zwykle jest intuicyjnie uzasadnione. Dlatego często działa zarówno dla kodu, jak i dla prozy.
Często znamy jakiś wzorzec (wyrażenie regularne), który oznacza jeden lub drugi tekst, który nas interesuje. Wyszukiwanie do przodu lub do tyłu to ruchy w vi . Dlatego mogą być również używane jako „podmioty” w naszych „oświadczeniach”. Więc mogę użyć, d/foo
aby wyciąć z bieżącej linii do następnej linii zawierającej ciąg „foo” i y?bar
skopiować z bieżącej linii do najnowszej (poprzedniej) linii zawierającej „pasek”. Jeśli nie chcę całych linii, nadal mogę korzystać z ruchów wyszukiwania (jako własnych instrukcji), porzucić moje znaki i używać `x
poleceń w sposób opisany wcześniej.
Oprócz „czasowników” i „przedmiotów” vi ma także „przedmioty” (w gramatycznym znaczeniu tego terminu). Do tej pory opisałem tylko użycie anonimowego rejestru. Jednak mogę użyć dowolnego z 26 rejestrów „nazwanych”, poprzedzając odwołanie do „obiektu” "
(modyfikatorem podwójnego cudzysłowu). Zatem jeśli "add
używam, wycinam bieżącą linię do rejestru „ a ”, a jeśli "by/foo
używam, szarpię kopię tekstu stąd do następnego wiersza zawierającego „foo” do rejestru „ b ”. Aby wkleić z rejestru po prostu poprzedzić pastę z tej samej sekwencji Modyfikator: "ap
wkleja Kopię „ ” zarejestrować”"bP
wkleja kopię z „ b ” do przed bieżącą linią.
To pojęcie „przedrostków” dodaje także analogi gramatyczne „przymiotniki” i „przysłówki” do naszego języka „manipulacji tekstem”. Większość poleceń (czasowników) i ruchów (czasowników lub obiektów, w zależności od kontekstu) może również przyjmować przedrostki numeryczne. 3J
oznacza „połącz trzy kolejne wiersze” i d5}
„usuń z bieżącego wiersza do końca piątego akapitu stąd”.
To wszystko poziom pośredni vi . Żaden z nich nie jest specyficzny dla Vima i istnieją vi bardziej zaawansowane sztuczki w vi, jeśli jesteś gotowy, aby się ich nauczyć. Jeśli opanujesz tylko te pośrednie pojęcia, prawdopodobnie odkryjesz, że rzadko musisz pisać makra, ponieważ język manipulacji tekstem jest wystarczająco zwięzły i ekspresyjny, aby robić większość rzeczy z łatwością za pomocą „rodzimego” języka edytora.
Próbki bardziej zaawansowanych sztuczek:
Istnieje wiele :
poleceń, w szczególności :% s/foo/bar/g
technika globalnego zastępowania. (To nie jest zaawansowane, ale :
mogą być inne polecenia). Cały :
zestaw poleceń historycznie odziedziczył poprzednie wcielenia vi jako narzędzia ed (edytor linii), a później ex (rozszerzony edytor linii). W rzeczywistości vi jest tak nazwany, ponieważ jest to interfejs wizualny ex .
:
polecenia zwykle działają nad wierszami tekstu. ed i ex zostały napisane w czasach, gdy ekrany terminali były rzadkie, a wiele terminali było urządzeniami typu „teletype” (TTY). Dlatego często drukowano kopie tekstu przy użyciu poleceń za pomocą bardzo zwięzłego interfejsu (częste prędkości połączenia wynosiły 110 bodów lub mniej więcej 11 znaków na sekundę - co jest wolniejsze niż szybka maszyna do pisania; opóźnienia występowały często na interaktywne sesje dla wielu użytkowników; dodatkowo często motywowano się do oszczędzania papieru).
Tak więc składnia większości :
poleceń obejmuje adres lub zakres adresów (numer linii), po którym następuje polecenie. Oczywiście można użyć literalnych numerów linii: :127,215 s/foo/bar
aby zmienić pierwsze wystąpienie „foo” na „słupek” na każdej linii między 127 a 215. Można również użyć niektórych skrótów, takich jak .
lub odpowiednio $
dla bieżącej i ostatniej linii. Można również użyć względnych prefiksów +
i -
odnieść się do przesunięć odpowiednio przed lub przed linią bieżącą. A zatem: :.,$j
oznacza „od bieżącej linii do ostatniej linii, połącz je wszystkie w jedną linię”. :%
jest synonimem :1,$
(wszystkie linie).
:... g
I :... v
polecenia ponieść jakieś wytłumaczenie, ponieważ są one bardzo silne. :... g
jest prefiksem dla „globalnie” zastosowania kolejnego polecenia do wszystkich wierszy, które pasują do wzorca (wyrażenie regularne), podczas gdy :... v
stosuje takie polecenie do wszystkich wierszy, które NIE pasują do danego wzorca („v” z „conVerse”). Podobnie jak w przypadku innych komend ex , można je poprzedzić adresowaniem / odniesieniami zakresu. Oznacza :.,+21g/foo/d
to zatem „usuń wszystkie wiersze zawierające ciąg„ foo ”z bieżącego do kolejnych 21 wierszy”, a jednocześnie :.,$v/bar/d
„od tego miejsca do końca pliku usuń wszystkie wiersze, które NIE zawierają ciągu„ pasek ”.
Interesujące jest to, że popularna komenda uniksowa grep została zainspirowana tym poleceniem ex (i nosi nazwę po sposobie, w jaki została udokumentowana). Ex komenda :g/re/p
(grep) był sposób udokumentowane, jak „globalnie” „Drukuj” linie zawierające „wyrażenia regularnego” (RE). Kiedy użyto ed i ex , :p
polecenie było jednym z pierwszych, które ktokolwiek się nauczył, i często pierwszym, którego użyto podczas edycji dowolnego pliku. W ten sposób wydrukowałeś bieżącą zawartość (zwykle tylko jedną stronę zapełnioną na raz za pomocą :.,+25p
lub jakąś taką).
Zauważ, że :% g/.../d
lub (jego odpowiednik reVerse / conVerse: :% v/.../d
są najczęstszymi wzorcami użytkowania. Istnieje jednak kilka innych ex
poleceń, o których warto pamiętać:
Możemy używać m
do przesuwania linii i j
łączenia linii. Na przykład, jeśli masz listę i chcesz oddzielić wszystkie elementy pasujące (lub odwrotnie NIE pasujące do jakiegoś wzoru) bez ich usuwania, możesz użyć czegoś takiego: :% g/foo/m$
... i wszystkie linie „foo” zostaną przeniesione do koniec pliku. (Zwróć uwagę na drugą wskazówkę dotyczącą używania końca pliku jako miejsca na zarysowania). Pozwoli to zachować względną kolejność wszystkich wierszy „foo”, po wyodrębnieniu ich z reszty listy. (Byłoby to równoważne z zrobieniem czegoś takiego: 1G!GGmap!Ggrep foo<ENTER>1G:1,'a g/foo'/d
(skopiuj plik do własnego ogona, przefiltruj ogon grep
i usuń wszystkie rzeczy z głowy).
Aby połączyć linie zwykle, mogę znaleźć wzór dla wszystkich linii, które muszą być połączone z ich poprzednikiem (na przykład wszystkie linie, które zaczynają się od „^” zamiast „^ *” na niektórych listach punktowanych). W takim przypadku użyłbym: :% g/^ /-1j
(dla każdej pasującej linii, przejdź o jedną linię w górę i dołącz do nich). (BTW: na listach kulach próbuje szukać linii kulach i przystąpić do następnego nie praca dla paru powodów ... może przyłączyć jedną linię kula do drugiego, a nie będzie dołączyć dowolną linię kula do wszystkich z jego kontynuacje; będzie działać tylko parami na meczach).
Prawie nie trzeba wspominać, że możesz użyć naszego starego przyjaciela s
(zamiennik) z poleceniami g
i v
(global / converse-global). Zwykle nie musisz tego robić. Zastanów się jednak nad przypadkiem, w którym chcesz wykonać podstawienie tylko w wierszach pasujących do innego wzorca. Często możesz użyć skomplikowanego wzorca z przechwytywaniem i użyć referencji wstecznych, aby zachować fragmenty linii, których NIE chcesz zmienić. Jednak często łatwiej będzie oddzielić dopasowanie od podstawienia: :% g/foo/s/bar/zzz/g
- dla każdej linii zawierającej „foo” zamień wszystkie „bar” na „zzz”. (Coś jak:% s/\(.*foo.*\)bar\(.*\)/\1zzz\2/g
działałby tylko w przypadkach tych przypadków „bar”, które WSTĘPNE były przez „foo” w tej samej linii; jest już dość niewygodny i musiałby zostać zmasakrowany, aby złapać wszystkie przypadki, w których „bar” poprzedzał „foo”)
Chodzi o to, że istnieje więcej niż tylko p
, s
i d
linii w ex
zestawie poleceń.
Te :
adresy mogą również odnosić się do znaków. Zatem możesz użyć: :'a,'bg/foo/j
do połączenia dowolnej linii zawierającej ciąg foo z kolejną linią, jeśli leży ona między liniami między znakami „ a ” i „ b ”. (Tak, wszystkie powyższe ex
przykłady poleceń można ograniczyć do podzbiorów wierszy pliku, poprzedzając je tego rodzaju wyrażeniami adresującymi).
To dość niejasne (użyłem czegoś takiego tylko kilka razy w ciągu ostatnich 15 lat). Przyznam jednak, że często robiłem rzeczy iteracyjnie i interaktywnie, co prawdopodobnie można by zrobić bardziej efektywnie, gdybym poświęcił czas na wymyślenie właściwej inkantacji.
Innym bardzo przydatnym poleceniem vi lub ex jest :r
odczytanie zawartości innego pliku. Zatem: :r foo
wstawia zawartość pliku o nazwie „foo” w bieżącym wierszu.
Potężniejsze jest :r!
polecenie. To odczytuje wyniki polecenia. To tak samo, jak zawieszanie sesji vi , uruchamianie polecenia, przekierowywanie danych wyjściowych do pliku tymczasowego, wznawianie sesji vi i wczytywanie zawartości z temp. plik.
Jeszcze bardziej potężny jesteś !
(huk) i :... !
( ex huk) poleceń. Wykonują one również zewnętrzne polecenia i odczytują wyniki w bieżącym tekście. Jednak filtrują również zaznaczenie naszego tekstu za pomocą polecenia! W ten sposób możemy posortować wszystkie wiersze w naszym pliku za pomocą 1G!Gsort
( G
jest to polecenie vi „goto”; domyślnie przechodzi do ostatniego wiersza pliku, ale może być poprzedzone numerem wiersza, takim jak 1, pierwszy wiersz). Jest to równoważne wariantowi ex:1,$!sort
. Pisarze często używają !
uniksowych narzędzi fmt lub fold do przekształcania lub „zawijania tekstu” zaznaczeń tekstu. Bardzo częstym makrem jest{!}fmt
(ponownie sformatuj obecny akapit). Programiści czasami używają go do uruchamiania kodu lub tylko jego części za pomocą wcięć lub innych narzędzi do formatowania kodu.
Użycie poleceń :r!
i !
oznacza, że każde zewnętrzne narzędzie lub filtr można traktować jako rozszerzenie naszego edytora. Czasami używałem ich ze skryptami, które wyciągały dane z bazy danych, lub z poleceniami wget lub lynx , które ściągały dane ze strony internetowej, lub poleceniami ssh , które wyciągały dane ze zdalnych systemów.
Innym przydatnym poleceniem ex jest :so
(skrót od :source
). Czyta zawartość pliku jako serię poleceń. Kiedy zaczynasz vi normalnie, domyślnie, wykonuje on :source
na ~/.exinitrc
pliku (a Vim zwykle robi to na ~/.vimrc
, oczywiście). Wykorzystanie tego polega na tym, że możesz zmienić profil edytora w locie, po prostu pozyskując nowy zestaw makr, skrótów i ustawień edytora. Jeśli jesteś podstępny, możesz nawet użyć tego jako sztuczki do przechowywania sekwencji poleceń ex edycji, aby zastosować je do plików na żądanie.
Na przykład mam plik z siedmioma wierszami (36 znaków), który uruchamia plik przez wc i wstawia komentarz w stylu C u góry pliku zawierającego dane o liczbie słów. Mogę zastosować to „makro” do pliku za pomocą polecenia takiego jak:vim +'so mymacro.ex' ./mytarget
( +
Opcja vi i Vim z wiersza poleceń jest zwykle używana do rozpoczęcia sesji edytowania pod danym numerem wiersza. Jednak mało znany jest fakt, że można podążać +
za dowolnym prawidłowym poleceniem / wyrażeniem ex , takim jak polecenie „źródło” jako Zrobiłem to tutaj; dla prostego przykładu mam skrypty, które wywołują: vi +'/foo/d|wq!' ~/.ssh/known_hosts
aby usunąć wpis z mojego znanego pliku hostów SSH w sposób nieinteraktywny, gdy ponownie obrazuję zestaw serwerów).
Zazwyczaj o wiele łatwiej jest pisać takie „makra” przy użyciu Perla, AWK, sed (co w rzeczywistości przypomina grep, narzędzie zainspirowane poleceniem ed ).
@
Komenda jest prawdopodobnie najbardziej niejasny vi poleceń. Od czasu do czasu ucząc zaawansowanych kursów administracji systemów przez prawie dekadę, spotkałem bardzo mało osób, które kiedykolwiek z nich korzystały. @
wykonuje zawartość rejestru tak, jakby to była komenda vi lub ex .
Przykład: często używam: :r!locate ...
do znalezienia jakiegoś pliku w moim systemie i odczytania jego nazwy do mojego dokumentu. Stamtąd usuwam wszelkie obce trafienia, pozostawiając tylko pełną ścieżkę do pliku, który mnie interesuje. Zamiast żmudnego Tabprzeszukiwania każdego elementu ścieżki (lub gorzej, jeśli utknąłem na komputerze bez obsługi uzupełniania tabulacji w kopii vi ) Używam po prostu:
0i:r
(aby zmienić bieżącą linię w poprawną komendę : r ),
"cdd
(aby usunąć wiersz z rejestru „c”) i
@c
wykonać to polecenie.
To tylko 10 naciśnięć klawiszy (a wyrażenie "cdd
@c
to dla mnie makro palca, więc mogę wpisać je prawie tak szybko, jak każde zwykłe sześcioliterowe słowo).
Trzeźwa myśl
Podszedłem tylko na powierzchnię mocy vi i nic z tego, co tu opisałem, nie jest nawet częścią „ulepszeń”, od których pochodzi vim ! Wszystko, co tu opisałem, powinno działać na każdej starej kopii vi sprzed 20 lub 30 lat.
Są ludzie, którzy wykorzystali znacznie więcej mocy vi niż kiedykolwiek.