Tôi có thể lặp lại lệnh UI cuối cùng không?


17

Tôi biết rằng tôi có thể sử dụng .để lặp lại lệnh chỉnh sửa cuối cùng.

Có cách nào để lặp lại lệnh thao tác UI cuối cùng không? Ví dụ, tôi có thể viết 10<C-W>-để thu nhỏ một cửa sổ bằng mười hàng. Thật tuyệt khi có thể nhấn ⟨một số phím để dễ dàng lặp lại lệnh này nếu tôi muốn thu nhỏ nó nhiều hơn.


Liên quan: stackoverflow.com/q/6952636/2072269 (không có câu trả lời nào có thể được sử dụng sau khi bạn đã thực hiện thay đổi kích thước).
muru

@muru: tốt, nhưng đó là cho trường hợp cụ thể này. Điều gì xảy ra nếu tôi đã làm một cái gì đó như thế fzvà sau đó 10;? Thế còn :tabm +1? Có phải tất cả sẽ phải được đặc biệt?
wchargein

tôi nghĩ bạn đã hiểu lầm tôi. Tôi đang nói rằng bài đăng được liên kết có câu trả lời vô ích (trước khi có người khác đến và gợi ý nó).
muru

Oh! được rồi, sau đó chúng ta ở cùng một trang @muru :)
wchargein

Câu trả lời:


12

Lệnh dot .hoạt động vì Vim "theo dõi" các lệnh thay đổi nội dung của bộ đệm. Nếu bạn chạy :echo b:changedtick, bạn sẽ thấy nó tăng dần theo từng thay đổi đối với bộ đệm hiện tại.

Nhưng Vim không "theo dõi" các lệnh không chỉnh sửa. Vì vậy, không, những gì bạn yêu cầu không thể được thực hiện.


8

Không có cách nào để làm điều này theo mặc định trong vim vì vim không theo dõi wincmd đã thực hiện trước đó. Tuy nhiên, có thể thực hiện điều này thông qua một số ánh xạ thông minh:

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>

Lưu ý rằng nếu bạn có bất kỳ ánh xạ nào sử dụng <C-w>chúng chỉ có thể được lặp lại nếu chúng không phải là noregiống. Bất kỳ wincmds ban hành sử dụng :wincmdsẽ không được lặp lại. Ngoài ra, bất kỳ wincmds nào chứa nhiều hơn một ký tự đều không thể được thực hiện (chẳng hạn như <C-w>gf) .

Chủ đề trợ giúp có liên quan

  • :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
Điều này thật tuyệt, và là một ví dụ tuyệt vời về VimScript được viết tốt! Một số phản hồi nhỏ (có thể kén chọn): Lệnh lặp lại này sẽ hành xử khác với cách .ứng xử tích hợp với số đếm. Khi một số đếm được cung cấp cho ., số đếm trước đó bị bỏ qua. Vì vậy, 2ddtiếp theo 3.sẽ xóa 2 dòng và sau đó 3 dòng; ngược lại, với ánh xạ của bạn, 2<C-w>-theo sau 3Qsẽ thu nhỏ cửa sổ 2 dòng và sau đó là 6 (= 2x3) dòng. Hành vi đó là tốt, nhưng thật tuyệt khi rút ra từ các lệnh Vim tích hợp tương tự khi chọn cách một lệnh tùy chỉnh nên hoạt động.
tommcdo

Cảm ơn! Ngoài ra, tôi thấy những gì bạn có ý nghĩa với cách thức hoạt động. Tôi có thể thay đổi nó để nó hoạt động theo cách đó.
EvergreenTree

4

Các submode plugin có thể giúp với điều này. Bạn có thể xác định "mã con" mà bạn nhập bằng cách nhập <C-W>-, trong đó bạn đã xác định -(và có lẽ +) để tiếp tục thay đổi kích thước cửa sổ.


2

Có một plugin khác gọi là repmo.vim ("chuyển động lặp lại") có thể làm những gì bạn muốn.

Nhưng bạn sẽ cần xác định những chuyển động (hoặc hành động nói chung) mà bạn muốn lặp lại. Của tôi hiện được cấu hình như thế này:

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

Vì vậy, sau khi làm 5 CTRL-W +tôi có thể nhấn ;để lặp lại nhiều lần như thế.

Plugin hoạt động bằng cách tạo ánh xạ cho từng phím được chỉ định.

Khi fhoặc tđược sử dụng, ánh xạ ;,ánh xạ sẽ bị xóa trở lại hành vi mặc định của chúng.

Tôi thấy ánh xạ g;đặc biệt hữu ích, để quay lại điểm chỉnh sửa trước đó. g; ; ; ;


@albfan Tôi không chắc là tôi hiểu câu hỏi của bạn, nhưng đối với tôi, ,hành động bức xúc ngay lập tức và 5,cũng hoạt động như mong đợi. Có thể bạn đã cài đặt của bạn mapleaderđể ,?
joeytwiddle
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.