Могу ли я повторить последнюю команду интерфейса?

17

Я знаю, что могу использовать, .чтобы повторить последнюю команду редактирования.

Есть ли способ повторить последнюю команду манипуляции с пользовательским интерфейсом? Например, я могу написать, 10<C-W>-чтобы уменьшить окно на десять строк. Было бы неплохо иметь возможность нажать « некоторую клавишу», чтобы легко повторить эту команду, если я захочу уменьшить ее.

wchargin
источник
Связанный: stackoverflow.com/q/6952636/2072269 (не дан ответ, который можно использовать после того, как вы уже сделали изменение размера).
Муру
@ Муру: хорошо, но это для этого конкретного случая. Что делать, если я сделал что-то подобное, fzа затем 10;? Как насчет :tabm +1? Это все должно быть в специальном корпусе?
wchargin
Я думаю, вы меня не поняли. Я говорю, что у связанного поста есть бесполезные ответы (прежде, чем кто-то еще придет и предложит это).
Муру
ой! хорошо, тогда мы на одной странице @muru :)
wchargin

Ответы:

12

Команда dot .работает, потому что Vim «отслеживает» команды, которые изменяют содержимое буферов. Если вы запустите :echo b:changedtick, вы увидите, что он увеличивается с каждым изменением текущего буфера.

Но Vim не «отслеживает» нередактирующие команды. Таким образом, нет, то, что вы просите, не может быть сделано.

lcd047
источник
8

В vim нет способа сделать это по умолчанию, потому что vim не отслеживает ранее выполненный wincmd. Тем не менее, это можно сделать с помощью некоторых умных сопоставлений:

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>

Обратите внимание, что если у вас есть какие-либо сопоставления, которые используют, <C-w>они могут повторяться, только если они не относятся к noreразнообразию. Любые wincmds, выпущенные с использованием :wincmd, повторяться не будут. Кроме того, любые wincmds, содержащие более одного символа, не могут быть выполнены (например, <C-w>gf) .

Соответствующие разделы справки

  • :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
Это отличный и отличный пример хорошо написанного VimScript! Небольшая (возможно, требовательная) обратная связь: эта команда повтора будет вести себя не так, как встроенная команда .при подсчете. Когда счетчик предоставляется ., предыдущий счет игнорируется. Таким образом , 2ddпосле чего 3.удалили бы 2 строки , а затем 3 линии; напротив, с вашими сопоставлениями, 2<C-w>-после чего 3Qуменьшится окно на 2 строки, а затем на 6 (= 2x3) строк. Такое поведение хорошо, но приятно использовать аналогичные встроенные команды Vim при выборе поведения собственной команды.
Tommcdo
Благодарность! Кроме того, я понимаю, что вы имеете в виду, как работает счет. Я могу изменить это так, чтобы это работало таким образом.
EvergreenTree
4

Подрежим плагин может помочь с этим. Вы можете определить «подрежим», который вы вводите, набрав <C-W>-, в котором вы определили -(и, возможно, +), чтобы продолжить изменение размера окна.

tommcdo
источник
2

Есть еще один плагин, который называется repmo.vim («повторить движения»), который может делать то, что вы хотите.

Но вам нужно будет указать, какие движения (или действия в целом) вы хотите повторить. Мой в настоящее время настроен так:

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

Так что после этого 5 CTRL-W +я могу нажать, ;чтобы повторить это столько раз, сколько нравится.

Плагин работает, создавая сопоставления для каждого из указанных ключей.

Когда fили tиспользуются, то ;и ,отображения сбрасываются обратно на их поведение по умолчанию.

Я считаю, что отображение g;особенно полезно, чтобы вернуться к более ранней точке редактирования. g; ; ; ;

joeytwiddle
источник
@albfan Я не уверен, что понимаю ваш вопрос, но для меня неотложные ,действия немедленно, а 5,также работает, как ожидалось. Возможно ли вы установить mapleaderTo ,?
Joeytwiddle