Bisakah saya mengulangi perintah UI terakhir?

17

Saya tahu bahwa saya dapat menggunakan .untuk mengulangi perintah pengeditan terakhir.

Apakah ada cara untuk mengulangi perintah manipulasi UI terakhir? Sebagai contoh, saya dapat menulis 10<C-W>-untuk mengecilkan jendela dengan sepuluh baris. Itu akan baik untuk dapat tekan ⟨ beberapa kunci ⟩ untuk dengan mudah mengulangi perintah ini jika saya ingin mengecilkan lebih.

wchargin
sumber
Terkait: stackoverflow.com/q/6952636/2072269 (tidak ada jawaban yang diberikan yang dapat digunakan setelah Anda sudah melakukan resize a).
muru
@uru: bagus, tapi itu untuk kasus khusus ini. Bagaimana jika saya telah melakukan sesuatu seperti itu fzdan kemudian 10;? Bagaimana dengan :tabm +1? Apakah ini semua harus dibuat khusus?
wchargin
Saya pikir Anda salah paham. Saya mengatakan pos yang ditautkan memiliki jawaban yang tidak berguna (sebelum orang lain datang dan menyarankannya).
muru
oh! oke, kalau begitu kita ada di halaman yang sama @muru :)
wchargin

Jawaban:

12

Perintah dot .berfungsi karena Vim "melacak" perintah yang mengubah konten buffer. Jika Anda menjalankan :echo b:changedtick, Anda akan melihatnya bertambah dengan setiap perubahan pada buffer saat ini.

Tetapi Vim tidak "melacak" perintah-perintah yang tidak diedit. Jadi, tidak, apa yang Anda minta tidak bisa dilakukan.

lcd047
sumber
8

Tidak ada cara untuk melakukan ini secara default di vim karena vim tidak melacak wincmd yang sebelumnya dieksekusi. Namun, dimungkinkan untuk melakukan ini melalui beberapa pemetaan cerdas:

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>

Perhatikan bahwa jika Anda memiliki pemetaan yang menggunakannya, <C-w>mereka hanya bisa diulang jika bukan dari norevarietasnya. Setiap mata uang yang dikeluarkan menggunakan :wincmdtidak akan diulang. Juga, setiap wincmds yang berisi lebih dari satu karakter tidak dapat dilakukan (seperti <C-w>gf) .

Topik Bantuan yang Relevan

  • :help v:count
  • :help getchar()
  • :help nr2char()
  • :help expr1
  • :help :wincmd
  • :help :execute
  • :help :for
  • :help :map-<silent>
  • :help c_CTRL-U
  • :help <SID>
Pohon cemara
sumber
1
Ini bagus, dan merupakan contoh VimScript yang ditulis dengan sangat baik! Beberapa umpan balik kecil (mungkin pilih-pilih): Perintah berulang ini akan berperilaku berbeda dari cara built-in .berperilaku dengan hitungan. Ketika hitungan diberikan ., hitungan sebelumnya diabaikan. Jadi 2dddiikuti oleh 3.akan menghapus 2 baris dan kemudian 3 baris; sebaliknya, dengan pemetaan Anda, 2<C-w>-diikuti oleh 3Qakan mengecilkan jendela dengan 2 garis dan kemudian oleh 6 (= 2x3) garis. Perilaku itu baik-baik saja, tetapi menyenangkan untuk menggambar dari perintah Vim built-in analog ketika memilih bagaimana perilaku kustom harus berperilaku.
tommcdo
Terima kasih! Juga, saya mengerti apa yang Anda maksud dengan cara penghitungan. Saya dapat mengubahnya sehingga berfungsi seperti itu.
EvergreenTree
4

The submode Plugin dapat membantu dengan ini. Anda bisa mendefinisikan "submode" yang Anda masukkan dengan mengetik <C-W>-, di mana Anda telah menetapkan -(dan mungkin +) untuk melanjutkan mengubah ukuran jendela.

tommcdo
sumber
2

Ada plugin lain yang disebut repmo.vim ("repeat motions") yang dapat melakukan apa yang Anda inginkan.

Tetapi Anda perlu menentukan gerakan mana (atau tindakan secara umum) yang ingin Anda ulangi. Milik saya saat ini dikonfigurasi seperti ini:

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

Jadi setelah melakukan itu 5 CTRL-W +saya bisa menekan ;untuk mengulanginya sebanyak yang diinginkan.

Plugin berfungsi dengan membuat pemetaan untuk masing-masing tombol yang ditentukan.

Ketika fatau tdigunakan, pemetaan ;dan ,dihapus kembali ke perilaku default mereka.

Saya menemukan pemetaan untuk g;sangat berguna, untuk kembali ke titik edit sebelumnya. g; ; ; ;

joeytwiddle
sumber
@albfan Saya tidak yakin saya mengerti pertanyaan Anda, tetapi bagi saya ,tindakan segera mendesak, dan 5,juga berfungsi seperti yang diharapkan. Apakah mungkin Anda telah mengatur Anda mapleaderke ,?
joeytwiddle