vim: Lanjutkan makro setelah kesalahan dalam submacro?

14

Saya sedang dalam proses mempercantik beberapa kode sumber menggunakan vim. {1}

Saya telah membuat beberapa makro vim yang melakukan langkah-langkah individual: menghapus trailing whilespace, menghapus baris kosong setelah {, menghapus baris kosong sebelumnya {, hal-hal semacam itu.

Sekarang, saya ingin membuat makro yang mengeksekusi semua makro secara berurutan. Namun, begitu makro rekursif pertama berakhir (karena tidak dapat lagi menemukan kecocokan -> kesalahan pencocokan), makro "pembungkus" saya juga berakhir.

Apakah ada cara untuk membuat makro vim melanjutkan setelah submacro menghasilkan kesalahan?

{1} Saya tahu tentang reformator otomatis. Saya bahkan mungkin menggunakannya pada masalah saya saat ini. Saya hanya menyebutkan pemformatan ulang sumber untuk contoh ini. Jangan memposting jawaban apapun tentang ahli kecantikan sumber ini atau itu. Pertanyaannya bukan tentang memformat ulang kode per se , tetapi tentang makro vim.

Contoh:

  • Makro 1 - memangkas spasi tambahan - qw/\s\+$d$@wq
  • Makro 2 - menghapus baris kosong sebelumnya} - qe/\n\n *}dd@eq
  • Makro Wrapper - retabbing, Makro 1, Makro 2 - qr:retab@w@eq

Ketika saya menjalankan pembungkus - @r- itu akan retab, kemudian jalankan Macro 1 sampai tidak ada spasi spasi tambahan ditemukan, kemudian hentikan ( tanpa menjalankan Macro 2).

Klarifikasi:

Apa yang saya cari adalah bagaimana memanggil submacro sehingga ketika submacro itu berakhir, makro panggilan berlanjut?

DevSolar
sumber

Jawaban:

12

Saya sarankan Anda gunakan :tryuntuk "menyerap" kesalahan submacro.

Ini adalah contoh konyol:

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

Makro pembungkus Anda akan terlihat seperti ini:

let @r=':retab^M:try|exe "norm! @w"|endtry|try|exe "norm! @e"|endtry^M'
Peter Rincker
sumber
Sementara garyjohn memberikan solusi untuk tidak memiliki kesalahan dalam submacro, ini adalah satu-satunya jawaban yang benar-benar menangani kesalahan semacam itu. Saya harus minta maaf; Saya tidak memeriksa jawaban Anda pada waktunya bagi Anda untuk mendapatkan hadiah (sekarang kedaluwarsa) ... :-(
DevSolar
25

Jika perintah gagal adalah substitusi yang tidak menemukan polanya, misalnya,

:%s/foo/bar/

ketika footidak ada di buffer, Anda dapat menambahkan etanda untuk mengabaikan kesalahan itu, misalnya,

:%s/foo/bar/e

Lihat

:help :s_flags

Anda bisa memberi tahu Vim untuk mengabaikan kesalahan dari beberapa perintah ex dengan mendahului mereka :silent!. Lihat

:help :silent


Edit Mengikuti Penambahan Contoh pada Pertanyaan

Makro 1 dan Makro 2 keduanya rekursif dan tidak memiliki mekanisme eksplisit untuk mengakhiri rekursi. Dugaan saya adalah bahwa salah satu tes internal Vim untuk rekursi tak terbatas sedang dipicu, yang menghasilkan kesalahan. Jika Makro 1 menghasilkan kesalahan seperti itu, maka kesalahan itu akan menghentikan eksekusi Wrapper Macro segera setelah itu @w.

Saran saya adalah untuk membatasi berapa kali makro Anda dieksekusi dengan menulis ulang mereka sebagai: perintah ex dan membatasi rentang garis di mana mereka dieksekusi. Sebagai contoh:

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

mana ^Mcara mengetik Enter atau tombol Kembali Anda. Saya belum menguji mereka bersama-sama di Makro Wrapper Anda, tetapi saya pikir Anda akan dapat memperbaiki kesalahan yang mungkin saya buat.

garyjohn
sumber
Ini bukan substitusi dalam kasus saya, tetapi penemuan sederhana (yaitu, /foo). Meskipun :silent!memang trik submakro rekursif tidak membatalkan makro pembungkus, sekarang submacro tidak berakhir sama sekali ... dan saya menduga bahwa membuatnya entah bagaimana mengakhiri lagi akan kembali mengakhiri makro pembungkus juga. Sepertinya saya mandek. : - \
DevSolar
Sulit untuk mengatakan apa yang salah tanpa melihat makro yang Anda gunakan, atau contoh sederhana yang menunjukkan masalah yang sama.
garyjohn
Menambahkan contoh.
DevSolar
2

Apa yang berhasil bagi saya adalah kombinasi jawaban @Peter Rincker dan @garyjohn. Secara terpisah saya terus mendapatkan masalah aneh.

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

Saya pikir silent!di dalam <leader>rt, dan karakter pipa antara endtrydan witu adalah kunci - hanya memiliki garis istirahat setelah endtrygagal. The trys bekerja ketika saya baru saja memasukkan mereka, tetapi ketika menjalankan sebagai makro kesalahan tentang teks pencarian tidak ditemukan akan terus dibangkitkan.

Mat
sumber
1

Saya secara rutin membuat macro on-the-fly ketika saya perlu melakukan tugas yang berulang di antara banyak file. Dalam kasus saya, saya memiliki NERDtree ( http://www.vim.org/scripts/script.php?script_id=1658 ) diinstal di VIM, yang membuat vsplitjendela, dan di sebelah kiri, saya memiliki daftar semua file di direktori saat ini. Dalam satu contoh, saya perlu menemukan contoh pertama dari string MY_TESTdalam file, dan kemudian menghapus, jika ada, awalan berlabel CUSTOM_PREFIX-dari baris itu, simpan file, lalu pindah ke yang berikutnya.

Inilah cara saya menjalankan makro ini di sekitar 2000 file di direktori saat ini. Saya bisa menulis skrip bash untuk melakukan ini, tetapi lebih cepat di VIM, dalam kasus saya. The +tombol Menandakan ditekan 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

Semoga ini membantu!

Awan
sumber