Posso ripetere l'ultimo comando dell'interfaccia utente?


17

So che posso usare .per ripetere l'ultimo comando di modifica.

C'è un modo per ripetere l'ultimo comando di manipolazione dell'interfaccia utente? Ad esempio, posso scrivere 10<C-W>-per ridurre una finestra di dieci righe. Sarebbe bello essere in grado di premere il ⟨ qualche chiave ⟩ di ripetere facilmente questo comando se voglio ridursi di più.


Correlato: stackoverflow.com/q/6952636/2072269 (nessuna risposta fornita che può essere utilizzata dopo aver già effettuato un ridimensionamento).
Muru,

@muru: bello, ma è per questo caso specifico. E se avessi fatto qualcosa del genere fze poi 10;? Che dire :tabm +1? Dovranno essere tutti sottoposti a casi speciali?
wchargin,

Penso che tu mi abbia frainteso. Sto dicendo che il post collegato ha risposte inutili (prima che venga qualcun altro e lo suggerisce).
Muru,

Oh! ok, allora siamo nella stessa pagina @muru :)
wchargin,

Risposte:


12

Il comando punto .funziona perché Vim "tiene traccia" dei comandi che modificano il contenuto dei buffer. Se esegui :echo b:changedtick, lo vedrai incrementare con ogni modifica al buffer corrente.

Ma Vim non "tiene traccia" dei comandi non di modifica. Quindi, no, ciò che stai chiedendo non può essere fatto.


8

Non c'è modo di farlo di default in vim perché vim non tiene traccia del wincmd precedentemente eseguito. Tuttavia, è possibile farlo attraverso alcune mappature intelligenti:

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>

Nota che se hai delle mappature che usano <C-w>, possono essere ripetute solo se non sono della norevarietà. Eventuali wincmds emessi utilizzando :wincmdnon verranno ripetuti. Inoltre, qualsiasi wincmds che contiene più di un personaggio non può essere eseguito (come <C-w>gf) .

Argomenti della Guida pertinenti

  • :help v:count
  • :help getchar()
  • :help nr2char()
  • :help expr1
  • :help :wincmd
  • :help :execute
  • :help :for
  • :help :map-<silent>
  • :help c_CTRL-U
  • :help <SID>

1
Questo è fantastico e un eccellente esempio di VimScript ben scritto! Alcuni feedback minori (forse schizzinosi): questo comando di ripetizione si comporterebbe diversamente dal modo in cui l'integrato .si comporta con un conteggio. Quando viene fornito un conteggio ., il conteggio precedente viene ignorato. Quindi 2ddseguito da 3.eliminerebbe 2 righe e quindi 3 righe; al contrario, con i tuoi mapping, 2<C-w>-seguiti da 3Qridurrebbe la finestra di 2 righe e quindi di 6 (= 2x3) righe. Questo comportamento va bene, ma è bello trarre da analoghi comandi Vim incorporati quando si sceglie come dovrebbe comportarsi un comando personalizzato.
tommcdo,

Grazie! Inoltre, capisco cosa intendi con come funziona il conteggio. Potrei cambiarlo in modo che funzioni in questo modo.
EvergreenTree

4

Il plugin di sottomodalità può aiutare in questo. Puoi definire una "sottomodalità" che inserisci digitando <C-W>-, in cui hai definito -(e forse +) per continuare a ridimensionare la finestra.


2

C'è un altro plugin chiamato repmo.vim ("ripeti movimenti") che può fare quello che vuoi.

Ma dovrai specificare quali movimenti (o azioni in generale) vuoi ripetere. Il mio è attualmente configurato in questo modo:

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 = "," 

Quindi dopo averlo fatto 5 CTRL-W +posso premere ;per ripeterlo tutte le volte che mi piace.

Il plugin funziona creando mappature per ciascuna delle chiavi specificate.

Quando fo tvengono utilizzati, i mapping ;e ,vengono ripristinati al loro comportamento predefinito.

Trovo la mappatura g;particolarmente utile, per tornare a un precedente punto di modifica. g; ; ; ;


@albfan Non sono sicuro di aver capito la tua domanda, ma per me premere ,immediatamente gli atti e 5,funziona anche come previsto. E 'possibile aver impostato la tua mapleadera ,?
joeytwiddle,
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.