Jak mogę zmapować d [count] d?

18

NB to nie duplikat Jak działa „d3fg” pracę polecenia? Proszę przeczytać przed głosowaniem, aby zamknąć!

Dochodzę do impasu w mojej misji, aby małe usunięcia działały jak duże . Problem, jaki mam, polega na tym, że nie mogę wymyślić, jak zmienić mapowanie poleceń d3d. W rzeczywistości nie mogę nawet zrozumieć, jak one działają, ani znaleźć wzmianki o nich w pomocy Vima. *

d3jjest prosty: stosuje doperatora do 3jruchu,

3ddjest również prosty: uruchamia ddpolecenie z „liczbą” 3.

d3d wygląda na to, że powinno być proste, stosuje doperatora do… ale co to jest 3d? To nie jest ruch. Jeśli 3dpiszesz sam, Vim traktuje go jako liczbę, po której następuje operator, i cierpliwie czeka na dalsze dane.

Nie można stosować operatorów do innych operatorów. ddnie jest opisany w pomocy jako ciąg dwóch operatorów. To osobne polecenie z dwoma naciśnięciami klawiszy. (por dc. nic nie robi).

Nie wydaje się również, aby pozycjonowanie licznika było elastyczne dla poleceń wymagających dwóch naciśnięć klawiszy: 2gjprzesuwa kursor w dół o dwie linie ekranu, ale g2jcałkowicie odrzuca pierwsze dwa naciśnięcia klawiszy i przesuwa kursor o jedną linię.

Jak to działa? Czy to tylko szczególny przypadek w wewnętrznym kodzie Vima? Czy jest jakiś sposób na stworzenie d[count]dmapowania?

EDYCJA : Czy to obiekt tekstowy? :h text-objectsnie obejmuje go na liście „text poleceń wyboru obiektu”, ale to nie to dd na liście delecji „zgrupowane od małych do dużych obiektów”. I d2awusuwa słowo pod kursorem i następne. Z drugiej strony c2dnic nie robi.

* Jestem pewien, że niektóre wzmianki o nich muszą istnieć, ale nie mogę ich znaleźć. Czytałem :help deleting, :help motion.txti spróbował :helpgrep dNddla wszystkich wartości N z 1-9 .

Bogaty
źródło
2
Myślę, że ostatnie ddziałania są potwierdzeniem; Więc to jest tak samo jak d3<CR>. y3ya c3ctakże działają tak samo ... Nie mogę znaleźć żadnych docs na to jednak zarówno w vim: pomoc, vi (1), nvi (1) lub specyfikacji POSIX ... To nie zachowują się tak samo w vii nvibtw .
Martin Tournoij
1
W pewnym sensie ddjest identyczny z d_. _przesuwa kursor do pierwszego niepustego [count]wiersza ( -1) linii w dół, ale jest liniowy, więc po sparowaniu z operatorem działa na całych liniach. Z tego powodu sensowne może być pojawienie się liczby między dwoma ds.
tommcdo

Odpowiedzi:

28

Tryb oczekiwania operatora

Pomiędzy wpisywanie operatora (jak d, club gU) oraz ruchu (takie jak w, i}lub /foo<CR>) vim w trybie operacji rozpatrywanym. Możesz tworzyć mapowania w tym celu za pomocą :omapi :onoremap.

W moich przykładach, idę do map Operator-pending ddo w. Jest to przypadkowy wybór, ponieważ nie wiem, do czego tak naprawdę chciałeś go użyć.

Utwórz omap

Utwórzmy mapowanie dw trybie oczekiwania operatora. Zakładam, że piszemy VimScript tutaj (np. W twoim .vimrc), więc pominę wiodące :s.

onoremap d w

To sprawia, że ddzachowujesz się jak dw. Sprawia również, że się d[count]dzachowuje d[count]w. Ale założę się, że nie chciałeś wpływać na zachowanie dd(tj. Brak w zestawie [count]).

Odwzorowania wyrażeń

Odwzorowania wyrażeń umożliwiają ocenę wyrażenia VimScript w celu utworzenia odwzorowania po prawej stronie. Wyrażenie powinno być traktowane jako ciąg. Odwzorowania wyrażeń są oznaczone <expr>słowem kluczowym.

Vim ma również wbudowane zmienne, które zapełniają się w różnych momentach i często są przydatne podczas mapowań. Jednym z nich jest v:count, który jest [count]dostarczany do operatora lub ruchu.

Złóżmy to wszystko razem. Jeśli nie [count]zostanie podany, v:countbędzie 0. dW takim przypadku możemy powiedzieć, że nasze mapowanie ma po prostu użyć .

onoremap <expr> d v:count == 0 ? 'd' : 'w'

Teraz ddzachowuje się jak domyślny (usuwa linię), ale d[count]dzachowuje się jak d[count]w. Chłodny!

Ogranicz go do użycia po doperatorze

Możesz jednak coś zauważyć. Teraz cdteż zachowuje się jak cw. Nie może to stanowić problemu, ale dla kompletności ograniczmy go, aby działał tylko po doperatorze.

Vim ma inną zmienną, v:operatorktóra zawiera ostatnio używany operator. Sprawdźmy to również przed zrobieniem czegoś specjalnego.

onoremap <expr> d (v:count == 0 \|\| v:operator != 'd') ? 'd' : 'w'

UWAGA: Ponieważ :mappolecenia można łączyć |, musimy uciec przed nimi w naszym wyrażeniu. Tak więc logiczny operator OR ||staje się \|\|.

Fajnie, więc cdi c[count]dwróciliśmy do robienia nic, tak jak kiedyś. Jest to dobre, aby inne wtyczki mogły zdefiniować cd.

Nie chcę po prostu usunąć innego ruchu

Jeśli chcesz zmapować d[count]dcoś zupełnie innego, co nie ma nic wspólnego z usuwaniem tekstu, możemy to zrobić.

Kiedy wpisujesz polecenia w trybie normalnym i zaczynasz wpisywać polecenie przez pomyłkę, możesz nacisnąć przycisk, <Esc>aby anulować to polecenie. To samo dotyczy twoich mapowań.

Zróbmy d[count]dzmienić bieżącą linię, co [count]jest.

onoremap <expr> d (v:count == 0 \|\| v:operator != 'd') ? 'd' : '<Esc>cc' . v:count . '<Esc>'

Ostatnia część mapowania jest wyrażeniem VimScript: <Esc>cc' . v:count . '<Esc>'. To <Esc>anuluje oczekujące dpolecenie, następnie cczmienia bieżący wiersz, v:countwpisuje wartość [count](w trybie wstawiania) i <Esc>powraca do trybu normalnego. Należy pamiętać, że budujemy ciąg tutaj za pomocą operatora konkatenacji VimScript, ..


Rzeczywisty przypadek użycia będzie prawdopodobnie inny niż ten, który tu opisałem, ale mam nadzieję, że pomoże ci to przetoczyć piłkę.

Happy Vimming!

tommcdo
źródło
Świetna odpowiedź! Pozytywne. Na początku pytania umieściłem link do mojego przypadku użycia (również na vi.SE), ale chyba nie mogłeś tego przegapić. Zasadniczo muszę zrobić :omap d d(!), Ale niestety tryb oczekiwania operatora nigdy nie został osiągnięty z powodu mojego mapowania dla d, które ustawia niestandardową funkcję operatora. Mamy jednak nadzieję, że można tak dostosować rzeczy, aby d3ddziałały tak, jak powinny. (Daj mi znać, jeśli masz jakieś pomysły lub napisz kompletne rozwiązanie drugiego pytania, jeśli wolisz.) Jeśli nie będę w stanie szybko tego zrozumieć, zaakceptuję to i opublikuję kolejne, bardziej szczegółowe pytanie. Dzięki!
Bogaty
1
Właściwie, po namyśle, akceptuję to teraz. Wyjaśniłeś zarówno, jak stworzyć takie mapowanie, a także jak działa pod maską, o co pytałem dwie rzeczy.
Bogaty