Czy mogę powtórzyć ostatnie polecenie interfejsu użytkownika?

17

Wiem, że mogę użyć .do powtórzenia ostatniego polecenia edycji.

Czy istnieje sposób na powtórzenie ostatniego polecenia manipulowania interfejsem użytkownika? Na przykład mogę pisać, 10<C-W>-aby zmniejszyć okno o dziesięć wierszy. Byłoby miło, aby móc prasie ⟨ jakiegoś klucza ⟩ łatwo powtórzyć tę komendę, jeśli chcę go więcej kurczyć.

wchargin
źródło
Powiązane: stackoverflow.com/q/6952636/2072269 (nie biorąc pod uwagę, że odpowiedź może być stosowany po tym, jak już wykonali Resize).
muru
@muru: fajnie, ale to w tym konkretnym przypadku. Co jeśli zrobiłem coś takiego fz, a potem 10;? Co :tabm +1? Czy to wszystko będzie musiało być w specjalnej obudowie?
wchargin
Myślę, że mnie źle zrozumiałeś. Mówię, że połączony post ma bezużyteczne odpowiedzi (zanim ktoś inny przyjdzie i zasugeruje).
muru
O! okej, więc jesteśmy na tej samej stronie @muru :)
wchargin

Odpowiedzi:

12

Polecenie kropkowe .działa, ponieważ Vim „śledzi” polecenia zmieniające zawartość buforów. Jeśli uruchomisz :echo b:changedtick, zobaczysz, że zwiększa się on z każdą zmianą w bieżącym buforze.

Ale Vim nie „śledzi” poleceń, które nie są edytowane. Zatem nie, czego nie można zrobić, o co prosisz.

lcd047
źródło
8

W vimie nie ma takiej możliwości, ponieważ vim nie śledzi poprzednio wykonanego programu wincmd. Można to jednak zrobić za pomocą sprytnych mapowań:

function! s:Wincmd(count, key)
    " If count is not zero, use the original count.  If otherwise, don't
    " include a count.
    let if_count = a:count ? a:count : ""
    " This builds a wincmd from the given key, and saves it so
    " it can be repeated.
    let g:last_wincmd = "wincmd " . nr2char(a:key)
    " Execute the built wincmd
    execute if_count . g:last_wincmd
endfunction

function! s:WincmdRepeat(count)
    " If no wincmd has been executed yet, don't do anything
    if !exists('g:last_wincmd') | return | endif
    " If a count is given, repeat the last wincmd that amount of times.
    " If otherwise, just repeat once.
    let if_count = a:count ? a:count : ""
    execute if_count . g:last_wincmd
endfunction

" Overwrite the default <C-w> mapping so that the last wincmd can be kept
" track of.  The getchar function is what captures the key pressed
" directly afterwards.  The <C-u> is to remove any cmdline range that vim
" automatically inserted.
nnoremap <silent> <C-w> :<C-u>call <SID>Wincmd(v:count, getchar())<CR>

" This just calls the function which repeats the previous wincmd.  It
" does accept a count, which is the number of times it should repeat the
" previous wincmd.  You can also replace Q with whatever key you want. 
nnoremap <silent> Q :<C-u> call <SID>WincmdRepeat(v:count)<CR>

Zauważ, że jeśli używasz mapowań, <C-w>można je powtórzyć tylko wtedy, gdy nie są noreodmiany. Wszelkie wydane za pomocą wincmds :wincmdnie będą się powtarzać. Ponadto nie można wykonać żadnych wincmds zawierających więcej niż jedną postać (np. <C-w>gf) .

Odpowiednie tematy pomocy

  • :help v:count
  • :help getchar()
  • :help nr2char()
  • :help expr1
  • :help :wincmd
  • :help :execute
  • :help :for
  • :help :map-<silent>
  • :help c_CTRL-U
  • :help <SID>
Wiecznie zielone drzewo
źródło
1
To jest świetny i doskonały przykład dobrze napisanego VimScript! Niektóre drobne (być może wybredne) informacje zwrotne: To polecenie powtarzania zachowywałoby się inaczej niż zachowanie wbudowane .z liczeniem. Po dostarczeniu .licznika poprzednie liczenie jest ignorowane. Tak więc 2ddnastępuje 3.usunięcie 2 linii, a następnie 3 linii; w przeciwieństwie do twoich mapowań, 2<C-w>-po których następuje 3Qzmniejszenie okna o 2 linie, a następnie o 6 (= 2x3) linii. Takie zachowanie jest w porządku, ale dobrze jest czerpać z analogicznych wbudowanych poleceń Vima, wybierając sposób, w jaki powinno się zachowywać polecenie niestandardowe.
tommcdo,
Dzięki! Widzę też, co masz na myśli, mówiąc o tym, jak działa liczenie. Mogę to zmienić, aby działało w ten sposób.
EvergreenTree,
4

Podtryb Wtyczka może w tym pomóc. Możesz zdefiniować „podtryb”, który wpisujesz <C-W>-, wpisując , w którym zdefiniowałeś -(i być może +), aby kontynuować zmianę rozmiaru okna.

tommcdo
źródło
2

Istnieje inna wtyczka o nazwie repmo.vim („powtarzaj ruchy”), która może robić, co chcesz.

Ale trzeba będzie określić, które wnioski (lub działania w ogóle) chcesz powtórzyć. Mój jest obecnie skonfigurowany w następujący sposób:

let g:repmo_mapmotions = "j|k h|l zh|zl g;|g, <C-w>w|<C-w>W"
let g:repmo_mapmotions .= " <C-w>+|<C-w>- <C-w>>|<C-w><"
let g:repmo_key = ";" 
let g:repmo_revkey = "," 

Więc po zrobieniu 5 CTRL-W +mogę uderzyć, ;aby powtórzyć to tyle razy, ile razy.

Wtyczka działa poprzez tworzenie odwzorowań dla każdego określonego klucza.

Gdy flub tsą używane, odwzorowania ;i ,są przywracane do ich domyślnego zachowania.

Uważam, że mapowanie jest g;szczególnie przydatne, aby wrócić do wcześniejszego punktu edycji. g; ; ; ;

joeytwiddle
źródło
@ albfan Nie jestem pewien, czy rozumiem twoje pytanie, ale dla mnie ,natychmiastowe działanie działa, a 5,także działa zgodnie z oczekiwaniami. Czy to możliwe, że ustawiłeś mapleaderTO ,?
joeytwiddle