Tôi có thể lặp lại một macro với toán tử dot dot không?


15

Tôi có thể lặp lại một macro với .lệnh không? Ví dụ: tôi muốn có thể nhập:

@q...

và có hiệu quả gọi @q4 lần. Với hành vi mặc định, công trình này chỉ khi 'q' giữ một lệnh duy nhất, ví dụ dw, xhoặc iHello<esc>. (Điều này có ý nghĩa mặc dù, vì '.' Lặp lại thay đổi cuối cùng , không phải là lần nhấn phím / lệnh cuối cùng)

Tôi cũng thích có tác phẩm này với số lượng. Ví dụ: gõ:

3@q.

sẽ có hiệu quả tương tự như chạy @q6 lần. Làm thế nào tôi có thể cấu hình hành vi này?


1
Không chính xác những gì bạn đang yêu cầu, nhưng có lẽ nó sẽ hữu ích cho github.com/wincent/replay . Bản ghi này cuối cùng được ghi lại macro và phát lại nó khi nhấnEnter
grodzik

FYI, @@lặp lại macro cuối cùng, vì vậy nếu bạn hỏi điều này vì lợi ích của ánh xạ và như vậy, nó sẽ hoạt động cho bạn.
Shahbaz

Câu trả lời:


7

Hãy thử cái này Nó ánh xạ lại @để g@(cộng với một chuyển động giả l) được sử dụng sau đó, do đó trở thành toán tử cuối cùng và có thể lặp lại với ..

" When . repeats g@, repeat the last macro.
fun! AtRepeat(_)
    " If no count is supplied use the one saved in s:atcount.
    " Otherwise save the new count in s:atcount, so it will be
    " applied to repeats.
    let s:atcount = v:count ? v:count : s:atcount
    " feedkeys() rather than :normal allows finishing in Insert
    " mode, should the macro do that. @@ is remapped, so 'opfunc'
    " will be correct, even if the macro changes it.
    call feedkeys(s:atcount.'@@')
endfun

fun! AtSetRepeat(_)
    set opfunc=AtRepeat
endfun

" Called by g@ being invoked directly for the first time. Sets
" 'opfunc' ready for repeats with . by calling AtSetRepeat().
fun! AtInit()
    " Make sure setting 'opfunc' happens here, after initial playback
    " of the macro recording, in case 'opfunc' is set there.
    set opfunc=AtSetRepeat
    return 'g@l'
endfun

" Enable calling a function within the mapping for @
nno <expr> <plug>@init AtInit()
" A macro could, albeit unusually, end in Insert mode.
ino <expr> <plug>@init "\<c-o>".AtInit()

fun! AtReg()
    let s:atcount = v:count1
    let c = nr2char(getchar())
    return '@'.c."\<plug>@init"
endfun

nmap <expr> @ AtReg()

Tôi đã cố gắng xử lý nhiều trường hợp góc như tôi có thể nghĩ ra. Bạn có thể lặp lại @:với .. Đếm đến @hoặc .được giữ lại cho các lần nhấn tiếp theo của ..

Điều này thật khó khăn và tôi không tin rằng một cái gì đó sẽ không bị phá vỡ ở đâu đó trên đường đi. Vì vậy, không có bảo đảm, bảo hành, hoặc lời hứa với điều này.

Cá nhân, tôi không có sự khác biệt giữa các lần lặp lại chi tiết .cho lần thay đổi cuối cùng và các lần lặp lại vĩ mô của @@.

BIÊN TẬP

Tôi hình dung, đã đi xa đến mức này, rằng tôi cũng có thể thêm một số mã bổ sung sẽ cho phép nhấn .ngay lập tức sau khi ghi macro để phát lại.

fun! QRepeat(_)
    call feedkeys('@'.s:qreg)
endfun

fun! QSetRepeat(_)
    set opfunc=QRepeat
endfun

fun! QStop()
    set opfunc=QSetRepeat
    return 'g@l'
endfun

nno <expr> <plug>qstop QStop()
ino <expr> <plug>qstop "\<c-o>".QStop()

let s:qrec = 0
fun! QStart()
    if s:qrec == 1
        let s:qrec = 0
        return "q\<plug>qstop"
    endif
    let s:qreg = nr2char(getchar())
    if s:qreg =~# '[0-9a-zA-Z"]'
        let s:qrec = 1
    endif
    return 'q'.s:qreg
endfun

nmap <expr> q QStart()

Điều này làm việc tuyệt vời! Kể từ khi đăng câu hỏi này, quy trình làm việc của tôi đã thay đổi, vì vậy tôi thực sự không muốn lặp lại các macro với dấu chấm nữa. Tuy nhiên, điều này hoạt động rất tốt, vì vậy dù sao tôi cũng sẽ chấp nhận nó (mặc dù tôi có thể sẽ không thêm nó vào .vimrc)
James

Không phải lo lắng, vấn đề thú vị bất kể!
Antony

1
Chỉnh sửa: cho phép phát lại macro .ngay sau khi ghi.
Antony

Tôi nghĩ \<plug>qstopnên có trước qchức năng QStart
Steve Vermeulen

6

Để lặp lại macro cuối cùng của bạn, bạn có thể sử dụng @@vì vậy 3@@về cơ bản sẽ chạy @q 3 lần. Tuy nhiên, tổ hợp phím @ có thể khó sử dụng, vì vậy, trong .vimrc của tôi, tôi có các dòng:

  "- Lazy macro repeat
  nmap <leader>m @@

Điều này cho phép tôi sử dụng khóa trưởng (,) cộng với m để chạy macro cuối cùng. Sau đó, bạn có thể đặt trước số này để lặp lại macro.

Bây giờ 3,mlà tương đương với 3@@. Tổng số khóa và không cần phải giữ ca.

EDIT : Sau khi suy nghĩ lại, tôi đã đưa ra một macro mới. nmap <leader>. @@ Điều này cũng hoạt động khi đi trước một số vì vậy 3,.bây giờ 3@@tôi rất thích xem tác phẩm này để tôi có thể chuyển qua một chữ cái macro và lặp lại macro đó thay vì macro cuối cùng.


OP muốn 3@q.chạy @q6 lần. Điều này không làm điều đó.
dùng41805

Đọc lại câu hỏi của bạn Tôi không chắc câu trả lời này. Bạn có thể đưa ra một ví dụ về khi bạn sẽ sử dụng 3@q.? Có vẻ như bạn cũng có thể chỉ cần trả trước với số lượng. Tôi có xu hướng thiết lập một tìm kiếm trước khi bắt đầu một macro sau đó sử dụng ntrong macro để chuyển đến điểm bắt đầu của nơi nó có thể được phát lại.
Shadoath

5

Bạn có thể ghi lại việc sử dụng một macro trong một macro khác và lặp lại điều đó.

qqdwq
qr2@qq

Bây giờ 3@rgiống như chạy @qsáu lần.


1

Theo mặc định spacetrong vim là "di chuyển đúng 1 ký tự" đã được bao phủ bởi l, vì vậy tôi đã ánh xạ lại không gian để chạy lại macro từ bộ đệm q:

noremap <Space> @q

Để sử dụng, chỉ cần ghi một macro với qqđầu tiên, dừng ghi với qvà sau đó nhấn spaceđể phát lại.


FYI, vì lý do bạn tuyên bố (đó không phải là khóa bắt buộc), rất nhiều người sử dụng không gian làm khóa lãnh đạo của họ để có thể không có nhiều người sử dụng nó miễn phí như bạn nghĩ. :)
Lớp B

0

Vì tôi không sử dụng ,và thích một giải pháp đơn giản dễ gõ, nên cách này hiệu quả với tôi:

:map , @@
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.