vim: Tiếp tục macro sau lỗi trong Subacro?


14

Tôi đang trong quá trình làm đẹp một số mã nguồn bằng vim. {1}

Tôi đã tạo một vài macro vim thực hiện các bước riêng lẻ: xóa khoảng trống theo dõi, xóa các dòng trống sau {, loại bỏ các dòng trống trước đó {, loại công cụ đó.

Bây giờ, tôi muốn tạo một macro thực thi tất cả các macro riêng lẻ theo trình tự. Tuy nhiên, một khi macro đệ quy đầu tiên chấm dứt (vì nó không còn có thể tìm thấy bất kỳ kết quả khớp nào -> lỗi khớp), macro "trình bao bọc" của tôi cũng chấm dứt.

Có cách nào để làm cho vim macro tiếp tục sau khi một subacro tạo ra lỗi không?

{1} Tôi biết về các bộ chuyển đổi tự động. Tôi thậm chí có thể sử dụng chúng cho vấn đề hiện tại của tôi. Tôi chỉ đề cập đến việc định dạng lại nguồn cho ví dụ. Không đăng bất kỳ câu trả lời về làm đẹp nguồn này hoặc đó. Câu hỏi không phải là về định dạng lại mã theo từng se , mà là về macro vim.

Thí dụ:

  • Macro 1 - khoảng trắng cắt xén - qw/\s\+$d$@wq
  • Macro 2 - xóa các dòng trống trước} - qe/\n\n *}dd@eq
  • Macro Wrapper - retabbing, Macro 1, Macro 2 - qr:retab@w@eq

Khi tôi thực thi trình bao bọc - @r- nó sẽ thử lại, sau đó thực thi Macro 1 cho đến khi không còn khoảng trắng theo dõi nào nữa, sau đó chấm dứt ( không thực hiện Macro 2).

Làm rõ:

Những gì tôi đang tìm kiếm là làm thế nào để gọi một subacro để khi subacro đó kết thúc, macro gọi tiếp tục?

Câu trả lời:


12

Tôi đề nghị bạn sử dụng :tryđể "hấp thụ" lỗi của Subacro.

Đây là một ví dụ ngớ ngẩn:

:let @a='f|dt|@a'
:let @q=':try|exe "norm! @a"|endtry^Mj0@q'
@q

Macro bao bọc của bạn sẽ trông giống như thế này:

let @r=':retab^M:try|exe "norm! @w"|endtry|try|exe "norm! @e"|endtry^M'

Trong khi garyjohn cung cấp một cách giải quyết cho việc không lỗi trong chương trình con, đây là câu trả lời duy nhất thực sự xử lý một lỗi như vậy. Tôi phải xin lỗi mặc dù; Tôi đã không kiểm tra câu trả lời của bạn kịp thời để bạn nhận được tiền thưởng (hiện đã hết hạn) ... :-(
DevSolar

25

Nếu lệnh không thành công là sự thay thế không tìm thấy mẫu của nó, ví dụ:

:%s/foo/bar/

Khi fookhông tồn tại trong bộ đệm, bạn có thể thêm ecờ để bỏ qua lỗi đó, ví dụ:

:%s/foo/bar/e

Xem

:help :s_flags

Bạn có thể yêu cầu Vim bỏ qua các lỗi từ một số lệnh: ex bằng cách đặt trước chúng với :silent!. Xem

:help :silent


Chỉnh sửa sau khi thêm ví dụ cho câu hỏi

Macro 1 và Macro 2 đều là đệ quy và không có bất kỳ cơ chế rõ ràng nào để chấm dứt đệ quy. Tôi đoán là một trong những thử nghiệm nội bộ của Vim cho đệ quy không giới hạn đang được kích hoạt, điều này tạo ra lỗi. Nếu Macro 1 đang tạo ra một lỗi như vậy, thì lỗi đó sẽ chấm dứt việc thực thi Macro Wrapper ngay sau đó @w.

Đề nghị của tôi sẽ là giới hạn số lần macro của bạn được thực thi bằng cách viết lại chúng dưới dạng: các lệnh ex và giới hạn phạm vi các dòng mà chúng được thực thi. Ví dụ:

qw:%s/\s\+$//^Mq
qe:%s/\n\n *}/\r}/^Mq

trong đó ^Mcó nghĩa là gõ phím Enter hoặc Return. Tôi chưa từng thử nghiệm chúng trong Macro Wrapper của bạn, nhưng tôi nghĩ bạn sẽ có thể sửa bất kỳ lỗi nào tôi có thể mắc phải.


Nó không phải là một sự thay thế trong trường hợp của tôi, mà là một tìm kiếm đơn giản (nghĩa là /foo). Mặc dù :silent!thực sự thủ thuật của subacro đệ quy không hủy bỏ macro của trình bao bọc, nhưng bây giờ, Subacro hoàn toàn không chấm dứt ... và tôi nghi ngờ rằng làm cho nó bằng cách nào đó chấm dứt một lần nữa cũng sẽ chấm dứt macro trình bao bọc. Có vẻ như tôi bị mắc kẹt. : - \
DevSolar

Thật khó để nói những gì có thể sai mà không nhìn thấy các macro bạn đang sử dụng hoặc một ví dụ đơn giản thể hiện cùng một vấn đề.
garyjohn

Đã thêm một ví dụ.
DevSolar

2

Điều làm việc cho tôi là sự kết hợp giữa câu trả lời @Peter Rincker và @ÿjohn. Gần đây tôi chỉ nhận được những vấn đề kỳ lạ.

nnoremap <leader>rt :silent! %s/\s\+$//e<CR>
let @r='\rt'
let @t=':try|silent! exe "norm! @r"|endtry|w^M'

Tôi nghĩ rằng silent!trong <leader>rt, và các nhân vật ống giữa endtrywlà chìa khóa - chỉ đơn giản là có ngắt dòng sau khi endtrythất bại. Các tryhoạt động khi tôi chỉ nhập chúng, nhưng khi chạy dưới dạng macro, lỗi về văn bản tìm kiếm không được tìm thấy sẽ tiếp tục được nêu ra.


1

Tôi thường xuyên tạo các macro khi đang di chuyển khi tôi cần thực hiện một tác vụ lặp đi lặp lại giữa nhiều tệp. Trong trường hợp của tôi, tôi có NERDtree ( http://www.vim.org/scripts/script.php?script_id=1658 ) được cài đặt trong VIM, tạo một vsplitcửa sổ và ở bên trái, tôi có một danh sách tất cả các tệp trong thư mục hiện tại. Trong một ví dụ, tôi cần tìm phiên bản đầu tiên của chuỗi MY_TESTtrong tệp, sau đó xóa, nếu có, một tiền tố được gắn nhãn CUSTOM_PREFIX-từ dòng đó, lưu tệp, sau đó chuyển sang tiếp theo.

Đây là cách tôi có macro này hoạt động trên khoảng 2000 tệp trong thư mục hiện tại. Tôi có thể viết một tập lệnh bash để làm điều này, nhưng trong trường hợp của tôi nhanh hơn trong VIM. Các +phím biểu thị phím được nhấn simul

# Start recording a macro sequence to register 'A'

q,a

# Search silently for the string "MY_TEST"; DO NOT report an error
# if the string could not be found.
:silent! /MY_TEST


# Replace, on just the current line, the string "CUSTOM_PREFIX-", with
# nothing (ie: delete it), and suppress any warning messages if the
# string could not be found on the current line.
:s/CUSTOM_PREFIX-//e


# Now issue some UI commands. CTRL-W then and arrow key lets you hope
# between tabs/splits/windows within vim.

CTRL+ W,

# Scroll down to the next file in the list in NERDtree



# Open the next file

ENTER

# End the macro

q

# Run the macro a thousand times in VIM

1000 @,,a

Hi vọng điêu nay co ich!

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.