Kann ich den letzten UI-Befehl wiederholen?

17

Ich weiß, dass ich .damit den letzten Bearbeitungsbefehl wiederholen kann .

Gibt es eine Möglichkeit, den letzten UI-Manipulationsbefehl zu wiederholen? Zum Beispiel kann ich schreiben 10<C-W>-, um ein Fenster um zehn Zeilen zu verkleinern. Es wäre schön, in der Lage zu sein, eine Taste zu drücken , um diesen Befehl einfach zu wiederholen, wenn ich ihn weiter verkleinern möchte.

wchargin
quelle
Verwandte Themen : stackoverflow.com/q/6952636/2072269 (keine Antwort angegeben, die verwendet werden kann, nachdem Sie bereits eine Größenänderung vorgenommen haben).
Muru
@muru: nett, aber das ist für diesen speziellen Fall. Was ist, wenn ich so etwas gemacht habe fzund dann 10;? Was ist :tabm +1? Müssen diese alle speziell behandelt werden?
Wchargin
Ich denke du hast mich falsch verstanden. Ich sage, der verlinkte Beitrag hat nutzlose Antworten (bevor jemand anderes kommt und es vorschlägt).
Muru
Oh! Okay, dann sind wir auf der gleichen Seite @muru :)
wchargin

Antworten:

12

Der Punktbefehl .funktioniert, weil Vim Befehle "verfolgt", die den Inhalt von Puffern ändern. Wenn Sie ausführen :echo b:changedtick, wird es mit jeder Änderung des aktuellen Puffers inkrementiert.

Vim "verfolgt" jedoch nicht die Befehle, die nicht bearbeitet wurden. Also, nein, was Sie verlangen, kann nicht getan werden.

lcd047
quelle
8

Dies ist in vim standardmäßig nicht möglich, da vim das zuvor ausgeführte wincmd nicht verfolgt. Dies ist jedoch durch einige clevere Zuordnungen möglich:

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>

Beachten Sie, dass Zuordnungen, die verwendet werden <C-w>, nur dann wiederholt werden können, wenn sie nicht der noreSorte sind. Mit ausgegebene WinCMDS :wincmdwerden nicht wiederholt. Wincmds, die mehr als ein Zeichen enthalten, können ebenfalls nicht ausgeführt werden (z. B. <C-w>gf) .

Relevante Hilfethemen

  • :help v:count
  • :help getchar()
  • :help nr2char()
  • :help expr1
  • :help :wincmd
  • :help :execute
  • :help :for
  • :help :map-<silent>
  • :help c_CTRL-U
  • :help <SID>
Immergrüner Baum
quelle
1
Das ist großartig und ein exzellentes Beispiel für gut geschriebenes VimScript! Ein paar kleinere (vielleicht wählerische) Rückmeldungen: Dieser Wiederholungsbefehl würde sich anders verhalten als das eingebaute Verhalten .bei einer Zählung. Wenn eine Zählung an übergeben wird, .wird die vorherige Zählung ignoriert. Also 2ddgefolgt von 3.würde 2 Zeilen und dann 3 Zeilen löschen; Im Gegensatz dazu würde mit Ihren Zuordnungen, 2<C-w>-gefolgt von 3Q, das Fenster um 2 Zeilen und dann um 6 (= 2x3) Zeilen verkleinert. Dieses Verhalten ist in Ordnung, aber es ist nett, analoge integrierte Vim-Befehle zu verwenden, wenn Sie festlegen, wie sich ein benutzerdefinierter Befehl verhalten soll.
tommcdo
Vielen Dank! Ich verstehe auch, was Sie damit meinen, wie die Zählung funktioniert. Ich kann es ändern, damit es so funktioniert.
EvergreenTree
4

Das Submode- Plugin kann dabei helfen. Sie können einen "Untermodus" definieren, den Sie eingeben, indem <C-W>-Sie definieren -(und möglicherweise +), dass die Größe des Fensters weiter geändert werden soll.

tommcdo
quelle
2

Es gibt ein weiteres Plugin namens repmo.vim ("Wiederholungsbewegungen"), das tun kann, was Sie wollen.

Aber Sie müssen die Bewegungen angeben (oder Aktionen im Allgemeinen) Sie wiederholen möchten. Meins ist derzeit so konfiguriert:

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

Nachdem 5 CTRL-W +ich das getan habe, kann ich ;es so oft wie möglich wiederholen.

Das Plugin erstellt Zuordnungen für jeden der angegebenen Schlüssel.

Wenn foder tverwendet werden, werden die Zuordnungen ;und ,auf ihr Standardverhalten zurückgesetzt.

Ich finde die Zuordnung g;besonders nützlich, um zu einem früheren Bearbeitungspunkt zurückzukehren. g; ; ; ;

joeytwiddle
quelle
@albfan Ich bin mir nicht sicher, ob ich deine Frage verstehe, aber für mich ,wirkt das Drücken sofort und 5,funktioniert auch wie erwartet. Ist es möglich , Sie haben Ihr Set mapleaderzu ,?
Joeytwiddle