¿Puedo repetir el último comando de la interfaz de usuario?


17

Sé que puedo usar .para repetir el último comando de edición.

¿Hay alguna manera de repetir el último comando de manipulación de la interfaz de usuario? Por ejemplo, puedo escribir 10<C-W>-para reducir una ventana en diez filas. Sería bueno para ser capaz de prensa ⟨ alguna clave ⟩ repetir fácilmente este comando si quiero reducir su tamaño más.


Relacionado: stackoverflow.com/q/6952636/2072269 (no se proporciona una respuesta que pueda usarse después de que ya haya cambiado el tamaño).
muru

@muru: bien, pero eso es para este caso específico. ¿Qué pasa si he hecho algo así fzy luego 10;? ¿Qué hay de :tabm +1? ¿Todos estos tendrán que estar en una carcasa especial?
wchargin

Creo que me has malentendido. Estoy diciendo que la publicación vinculada tiene respuestas inútiles (antes de que alguien más venga y lo sugiera).
muru

¡Oh! bien, entonces estamos en la misma página @muru :)
wchargin

Respuestas:


12

El comando dot .funciona porque Vim "realiza un seguimiento" de los comandos que cambian el contenido de los buffers. Si ejecuta :echo b:changedtick, verá que se incrementa con cada cambio en el búfer actual.

Pero Vim no "realiza un seguimiento" de los comandos que no son de edición. Por lo tanto, no, lo que estás pidiendo no se puede hacer.


8

No hay forma de hacerlo de forma predeterminada en vim porque vim no realiza un seguimiento del wincmd ejecutado anteriormente. Sin embargo, es posible hacer esto a través de algunas asignaciones inteligentes:

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>

Tenga en cuenta que si tiene alguna asignación que use <C-w>, solo se puede repetir si no es de la norevariedad. Los wincmds emitidos usando :wincmdno se repetirán. Además, no se pueden realizar wincmds que contengan más de un carácter (como <C-w>gf) .

Temas de ayuda relevantes

  • :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
¡Esto es genial, y un excelente ejemplo de VimScript bien escrito! Algunos comentarios menores (quizás quisquillosos): este comando de repetición se comportaría de manera diferente al comportamiento integrado .con un conteo. Cuando se suministra un recuento ., se ignora el recuento anterior. Entonces 2ddseguido de 3.eliminaría 2 líneas y luego 3 líneas; en contraste, con sus asignaciones, 2<C-w>-seguido 3Qreduciría la ventana en 2 líneas y luego en 6 (= 2x3) líneas. Ese comportamiento está bien, pero es bueno extraer de los comandos Vim incorporados análogos al elegir cómo debe comportarse un comando personalizado.
tommcdo

¡Gracias! Además, veo lo que quieres decir con cómo funciona el conteo. Puedo cambiarlo para que funcione de esa manera.
EvergreenTree

4

El complemento submode puede ayudar con esto. Puede definir un "submodo" que ingresa escribiendo <C-W>-, en el que ha definido -(y tal vez +) para continuar cambiando el tamaño de la ventana.


2

Hay otro complemento llamado repmo.vim ("repetir movimientos") que puede hacer lo que quiera.

Pero deberá especificar qué movimientos (o acciones en general) desea repetir. El mío está configurado actualmente de esta manera:

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

Entonces, después de hacerlo 5 CTRL-W +, puedo presionar ;para repetirlo tantas veces como quiera.

El complemento funciona creando asignaciones para cada una de las claves especificadas.

Cuando fo tse usan, las asignaciones ;y ,se vuelven a borrar a su comportamiento predeterminado.

Me parece g;especialmente útil la asignación , para volver a un punto de edición anterior. g; ; ; ;


@albfan No estoy seguro de entender tu pregunta, pero para mí presionar ,actúa de inmediato y 5,también funciona como se esperaba. ¿Es posible que haya establecido la mapleadera ,?
joeytwiddle
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.