Puis-je répéter la dernière commande d'interface utilisateur?


17

Je sais que je peux utiliser .pour répéter la dernière commande d'édition.

Existe-t-il un moyen de répéter la dernière commande de manipulation de l'interface utilisateur? Par exemple, je peux écrire 10<C-W>-pour réduire une fenêtre de dix lignes. Ce serait bien de pouvoir appuyer sur ⟨ une touche ⟩ de répéter facilement cette commande si je veux réduire plus.


En relation: stackoverflow.com/q/6952636/2072269 (aucune réponse donnée qui peut être utilisée après avoir déjà effectué un redimensionnement).
muru

@muru: sympa, mais c'est pour ce cas spécifique. Et si j'ai fait quelque chose comme ça fzet ensuite 10;? Et alors :tabm +1? Est-ce que tout cela devra être dans un boîtier spécial?
wchargin

Je pense que vous m'avez mal compris. Je dis que le message lié a des réponses inutiles (avant que quelqu'un d'autre ne le suggère).
muru

Oh! D'accord, alors nous sommes sur la même page @muru :)
wchargin

Réponses:


12

La commande dot .fonctionne parce que Vim "garde la trace" des commandes qui modifient le contenu des tampons. Si vous exécutez :echo b:changedtick, vous le verrez incrémenter à chaque modification du tampon actuel.

Mais Vim ne "garde pas" la trace des commandes non éditables. Ainsi, non, ce que vous demandez ne peut pas être fait.


8

Il n'y a aucun moyen de le faire par défaut dans vim car vim ne garde pas la trace du wincmd précédemment exécuté. Cependant, il est possible de le faire grâce à des mappages intelligents:

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>

Notez que si vous avez des mappages qui les utilisent, <C-w>ils ne peuvent être répétés que s'ils ne sont pas de la norevariété. Aucun wincmds émis à l'aide de :wincmdne sera répété. De plus, aucun wincmds contenant plus d'un caractère ne peut être exécuté (tel que <C-w>gf) .

Rubriques d'aide pertinentes

  • :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
C'est génial, et un excellent exemple de VimScript bien écrit! Quelques commentaires mineurs (peut-être pointilleux): Cette commande de répétition se comporterait différemment de la façon dont le intégré .se comporte avec un nombre. Lorsqu'un compte est fourni à ., le compte précédent est ignoré. Donc 2ddsuivi de 3.supprimerait 2 lignes puis 3 lignes; en revanche, avec vos mappages, 2<C-w>-suivi de 3Qréduirait la fenêtre de 2 lignes, puis de 6 (= 2x3) lignes. Ce comportement est correct, mais il est agréable de s'inspirer des commandes Vim intégrées analogues lors du choix du comportement d'une commande personnalisée.
tommcdo

Merci! De plus, je vois ce que vous voulez dire avec le fonctionnement du décompte. Je peux le changer pour qu'il fonctionne de cette façon.
EvergreenTree

4

Le plugin de sous- mode peut vous aider. Vous pouvez définir un "sous-mode" que vous entrez en tapant <C-W>-, dans lequel vous avez défini -(et peut-être +) de continuer à redimensionner la fenêtre.


2

Il existe un autre plugin appelé repmo.vim ("répéter les mouvements") qui peut faire ce que vous voulez.

Mais vous devrez spécifier les mouvements (ou actions en général) que vous souhaitez répéter. Le mien est actuellement configuré comme ceci:

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

Donc, après l'avoir fait, 5 CTRL-W +je peux le ;répéter autant de fois que nécessaire.

Le plugin fonctionne en créant des mappages pour chacune des clés spécifiées.

Lorsque fou tsont utilisés, les mappages ;et ,sont réinitialisés à leur comportement par défaut.

Je trouve le mappage g;particulièrement utile pour revenir à un point de montage antérieur. g; ; ; ;


@albfan Je ne suis pas sûr de comprendre votre question, mais pour moi, presser ,agit immédiatement et 5,fonctionne aussi comme prévu. Est - il possible que vous avez défini votre mapleaderà ,?
joeytwiddle
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.