Vim Macro trên mọi dòng lựa chọn trực quan


85

Tôi muốn chạy macro trên mọi dòng trong vùng lựa chọn, thay vì tính tổng số dòng trong đầu. Ví dụ: tôi có thể viết một macro để chuyển đổi:

Last, First

Vào

First Last

và tôi muốn nó chạy trên tất cả các dòng sau:

Stewart, John 
Pumpkin, Freddy
Mai, Stefan
...

Bất kỳ ý tưởng Vim guru?

CHỈNH SỬA: Đây chỉ là một ví dụ, rõ ràng đây là ba lần có thể regexable, nhưng có những trường hợp khác không dễ dàng đến mức tôi muốn sử dụng macro hơn.


1
Thành thật mà nói, tôi có thể sẽ thực hiện nhiệm vụ cụ thể này với regex. Nhưng câu hỏi vẫn có giá trị đối với những trường hợp phức tạp hơn.
Jamie Wong

Tại sao vim? Theo ý kiến ​​của tôi thì sed đáng sợ hơn.
kokosing

8
@kogut: Tại sao lại thoát khỏi trình soạn thảo của bạn để chỉnh sửa văn bản của bạn với một regex một dòng?
Stephen

1
Được rồi, bạn đã hiểu đúng;)
kokosing

Câu trả lời:


152

Giả sử bạn có một macro qchạy (và duy trì) trên một dòng. Sau đó, bạn có thể chạy nó trên mọi dòng trong lựa chọn của mình với:

:'<,'>normal @q

(nếu bạn đã chọn một nhóm dòng, nhấn :sản xuất :'<,'>trên dòng lệnh)

Ví dụ: macro sau viết hoa mọi từ trừ chữ đầu tiên trên một dòng:

:let @q="^dwgU$P"

Vì vậy, chạy nó trên phần sau (nơi các +dòng được chọn)

 0000: a long long time ago
 0001: in a galaxy far away
+0002: naboo was under an attack
+0003: and i thought me and qui-gon jinn
+0004: could talk the federation in
 0005: to maybe cutting them a little slack.

Với normal @qlệnh trên , tạo:

 0000: a long long time ago
 0001: in a galaxy far away
 0002: naboo WAS UNDER AN ATTACK
 0003: and I THOUGHT ME AND QUI-GON JINN
 0004: could TALK THE FEDERATION IN
 0005: to maybe cutting them a little slack.

6
:let @q="^wgU$"

1
@raosystem: có lỗi đánh máy trong lệnh của bạn không? đối với tôi nó chỉ hoạt động như thế này::'<,'>normal! @q
oliver

3
@oliver: kiểm tra ánh xạ của bạn - bạn có thể đã ánh xạ lại @q. Từ :help normal- "Nếu [!] Được đưa ra, các ánh xạ sẽ không được sử dụng."
rapter

2
@raosystem: chết tiệt ... bạn nói đúng! Tôi sử dụng yankring và dường như có vấn đề với điều này: ... Bạn không thể thực thi macro với ": normal @a". Vẫn không thể thực hiện được, nhưng bạn có thể thực thi nó với ": normal! @A" (từ tài liệu trợ giúp của yankring)
oliver

1
Cá nhân tôi thích để lập bản đồ @trong chế độ hình ảnh như thế này: vnoremap @ :normal @. Bằng cách đó, bạn vẫn có thể làm @anhư bạn mong đợi (mặc dù bạn phải nhấn enter sau đó :()
LondonRob

19

Chọn các dòng sau đó nhấn :để vào chế độ lệnh. Vim sẽ tự động điền vào '<,'>, giới hạn phạm vi đối với các dòng đã chọn. Đối với ví dụ của bạn, bạn có thể sử dụng :slệnh để thực hiện hoán đổi:

:'<,'>s/\(\w\+\), \(\w\+\)/\2, \1/

Thao tác này sẽ hoán đổi hai từ được phân tách bằng dấu phẩy trên mỗi dòng trong lựa chọn trực quan.

Bạn cũng có thể sử dụng '<'>giống như bất kỳ dấu trang hoặc vị trí dòng nào khác, ví dụ như một phần của lệnh di chuyển, vì vậy ở chế độ bình thường d'<sẽ xóa từ vị trí con trỏ hiện tại đến đầu dòng đầu tiên trong vùng chọn trực quan. Các dấu vẫn có hiệu lực ngay cả khi khối không còn được đánh dấu trực quan.

Nếu bạn muốn phát lại một macro đã ghi trên mọi dòng, bạn cần thực hiện macro bằng :normallệnh. Thật không may, :normallệnh không hoạt động trên một loạt các dòng, nhưng bạn có thể khắc phục điều đó bằng :globallệnh. Thao tác này chạy một :exlệnh trên mọi dòng khớp với regex, vì vậy bạn có thể thực hiện điều này:

:'<,'>g/^/ norm @a

Giải trình:

:'<,'>       for every line in the visual block
g/^/         on every line that matches the regex /^/ - i.e. every line
norm         run in normal mode
@a           the macro recorded in a

Điều này tốt hơn câu trả lời được chấp nhận vì nó hỗ trợ macro thêm các dòng mới.
Jan Warchoł

@Dave, Kirby Có lẽ tốt hơn nên trao đổi ^với .để làm cho macro chỉ chạy trên các dòng có một số văn bản, phải không?
SergioAraujo

1

Bạn có thể thêm chức năng bên dưới vào của bạn ~/.vimrchoặc chỉ cần sao chép nó trên trình duyệt của bạn và chạy:@+

fun! RunMacroOverSelection(macroname)
    execute "'<,'>normal @". a:macroname
endfun
com -nargs=1 Rover :call RunMacroOverSelection(<f-args>)
nnoremap <leader>r :Rover<space>

Ưu điểm là bạn có thể áp dụng bất kỳ macro nào trên vùng chọn trực quan. Bạn cần cung cấp ký tự macro làm đối số, như:

:Rover a
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.