Bagaimana cara mencari pola di wilayah sintaksis tertentu?

10

Saya menggunakan vim untuk mengedit dokumen lateks. Seringkali, saya ingin mengubah nama variabel menjadi sesuatu yang lain. Namun, agak menyebalkan harus mengarungi pertandingan yang tidak relevan ketika saya mencari nama variabel. Saya ingin mencari hanya di "zona matematika" sebagaimana didefinisikan dalam file sintaks tex. Apakah ada cara mudah untuk membatasi pencarian ke wilayah sintaksis tertentu?

Rob F.
sumber
1
Saya pikir jawabannya tidak: tidak ada cara mudah untuk membatasi pencarian ke wilayah sintaksis tertentu.
Karl Yngve Lervåg
2
Pemetaan ini digunakan synIDattr()untuk mendapatkan grup sintaks untuk karakter di bawah kursor. Anda dapat menulis fungsi yang melakukan pencarian (atau tidak normal n) dan kemudian gunakan synIDattr()untuk memutuskan apakah akan tetap di lokasi ini, atau melanjutkan pencarian ke depan.
joeytwiddle
@ joeytwiddle Saya melihat komentar Anda sekarang setelah memposting jawaban dengan fungsi seperti itu. Apakah itu seperti apa yang ada dalam pikiran Anda?
jjaderberg
@ jjaderberg Ya itu. Kerja bagus!
joeytwiddle
Hanya untuk kelengkapan (saya menemukan jawaban yang bagus): stackoverflow.com/a/2696143/5000478
VanLaser

Jawaban:

4

Ini adalah fungsi yang bisa Anda coba. Saya hanya mengujinya sedikit tetapi tampaknya berfungsi baik.

function! JJSyntaxSearch(pattern, syntaxitem)
  while search(a:pattern, 'W') > 0
    for id in synstack(line("."),col("."))
      if synIDattr(id,"name") =~? a:syntaxitem
        return line(".")
      endif
    endfor
  endwhile
  return 0
endfunc

command! -nargs=* JJSyntaxSearch call JJSyntaxSearch(<f-args>)

Fungsi memanggil fungsi pencarian Vim dalam satu lingkaran sampai menemukan kecocokan 'biasa' yang juga merupakan kecocokan 'terkualifikasi' dengan item sintaksis tertentu, atau sampai mencapai akhir buffer.

Dibutuhkan dua argumen. Yang pertama adalah pola pencarian dan diteruskan tidak berubah ke search()fungsi Vim . Lihat :help search()bagaimana fungsi itu bekerja. Argumen kedua adalah nama item sintaks di mana Anda ingin memfilter pertandingan ini. Ini juga bisa menjadi pola dan dibandingkan sebagai ekspresi reguler yang tidak peka terhadap huruf besar-kecil.

Untuk menemukan pola 'alpha' di zona matematika yang bisa Anda lakukan

:JJSyntaxSearch alpha texMathZone.

Pada .akhirnya adalah atom pola untuk setiap karakter tunggal, lihat :help /.. Ini karena ada banyak item sintaks zona matematika yang dipanggil texMathZoneA, texMathZoneBdll.

The search()Fungsi memindahkan kursor ke pertandingan berikutnya 'biasa'. Kemudian fungsi kami mendapatkan semua ID item sintaks untuk posisi kursor baru tersebut synstack(). Melongok melalui mereka, itu mengambil nama setiap item pada gilirannya dan mengujinya terhadap syntaxitemargumen. Lihat :help synstack()dan :help synIDattr(). Jika ada kecocokan 'terkualifikasi', ia mengembalikan nomor baris. Jika mencapai akhir buffer tanpa menemukan kecocokan yang 'memenuhi syarat' itu kembali 0. Maksud dari fungsi ini adalah untuk mengarahkan kursor ke kecocokan 'terkualifikasi' berikutnya sehingga Anda dapat melakukan beberapa operasi di sana, tetapi akan berguna untuk mengembalikan "nomor baris atau 0" untuk menunjukkan apakah memanggil fungsi itu berarti, karena Misalnya jika Anda ingin memanggil fungsi berulang kali dari fungsi lain atau makro.

Saya memilih untuk menggunakan Wflag search()karena mencegah 'membungkus' ujung buffer. Kalau tidak, fungsi tersebut mungkin macet karena terus menemukan kecocokan 'biasa' yang sama tetapi tidak ada kecocokan 'berkualitas'.

jjaderberg
sumber
Terima kasih atas bantuan Anda! Saya belum mencoba fungsi ini, tetapi sepertinya apa yang saya inginkan.
Rob F.
1

Jika "zona matematika" Anda memenuhi syarat oleh beberapa pola sintaksis, misalnya, string "matematika", maka Anda setidaknya dapat menggunakan urutan pola untuk menemukan garis dengan pola yang cocok, seperti pada:

:/math//your pattern/

(Catatan: kedua pola mungkin berada pada garis yang berbeda!)

Ini mungkin tidak membatasi kecocokan Anda ke zona - untuk itu Anda perlu mengidentifikasi akhir zona -, tetapi itu hanya akan menampilkan kecocokan tersebut setelah pola / matematika / awal. Anda dapat mengulangi pencarian untuk kejadian berikutnya dengan menggunakan riwayat mode-ex ( : up-arrow enter).


Catatan: ISTR yang pada versi vim / vi sebelumnya saya juga dapat menggunakan metode itu secara langsung sebagai perintah pencarian (sebagai lawan dari perintah mode ex) /math//your pattern/dengan keuntungan dari kurang mengetik dan menggunakan perintah ndan N, tetapi saya tidak dapat mengkonfirmasi itu untuk versi vim saya saat ini.

Janis
sumber
1

Jika Anda mencari string foodi dalam $...$atau $$...$$, ini seharusnya berfungsi:

\$.*\zsfoo

Ini mengaitkan kecocokan dengan $karakter tetapi hanya memilih string foo.

Ini sebenarnya bukan solusi yang mudah, tetapi orang dapat menggunakan tanda :global+ :substituteuntuk menemukan "zona matematika" dan mencari di dalamnya:

:global /\v\\begin\{%(align|alignat|displaymath)\}/ +1,/\\end/-1 s/foo/&/gc

Berpura-pura itu :substituteadalah perintah pencarian, Anda bisa pergi ke kejadian berikutnya dengan ndan keluar dengan q. Jika Anda mengkonfirmasi penggantian secara tidak sengaja seharusnya tidak ada masalah.

Anda harus mengatur daftar di dalam %(... )ke nama-nama lingkungan matematika yang Anda gunakan (daftar lengkapnya lumayan:) align|alignat|displaymath|eqnarray|equation|flalign|gather|math|multline|subequations|xalignat|xxalignat. Perhatikan bahwa saya menggunakan pola sangat ajaib ( \v) di sini.

Penjelasan:

:globalmenjalankan perintah Ex ( :s) pada setiap baris di mana pertandingan pola ( :help :global)
/\vmulai pola yang sangat ajaib ( :h /, :h pattern, :h magic)
\\begin\{cocok dengan literal \begin{
%(align|alignat|displaymath)setiap pertandingan dari kata-kata ini ( :h /\%(, :h /bar)
\}/cocok dengan literal }dan mengakhiri pola.

+1,/\\end/-1rentang yang terdiri dari baris berikutnya (dihitung dari yang ditemukan oleh :global) hingga baris sebelum yang ditemukan oleh pola pencarian /\\end. Dalam kisaran itu,

s/foo/&/gccari dan ganti setiap kemunculan literal foodengan dirinya sendiri, setelah konfirmasi ( :h :substitute)

Peter Lewerin
sumber
Ini tentu saja merupakan permulaan, tetapi saya sering menggunakan lingkungan persamaan, perataan, dan IEEEeqnarray, dan saya tidak ingin mengecualikan yang dari pencarian saya.
Rob F.
@RobF.: Sangat mungkin untuk mencocokkan dalam berbagai lingkungan, tetapi itu tidak akan mudah kecuali satu skrip itu. Namun, jika Anda secara konsisten menggunakan di \mathitsekitar nama variabel, menemukannya jauh lebih mudah.
Peter Lewerin
0

Jika Anda mencari string 'pagi' di dalam file /morninglalu entertekan nuntuk bergerak maju

Arvind Gangwar
sumber
1
Pertanyaannya mengatakan I would like to search only in "math zones"metode Anda mencari seluruh file yang tidak membatasi zona penelitian.
statox
0

Tidak ada pilihan selain menulis fungsi khusus untuk ini. Saya menulis fungsi yang mencari string yang Anda inginkan dan hanya berhenti jika:

  1. kehabisan pertandingan
  2. ada pertandingan yang ada di dalam lingkungan matematika (itu akan berhenti di pertandingan)

Anda cukup menyebutnya dengan string yang ingin Anda cari.

function! Finmath(nextstr)
    while 1
        if search(a:nextstr)==0
            break
        endif
        if searchpairpos('\(', '','\)','n')!=[0,0]
            break
        endif
        if searchpairpos('\[', '','\]','n')!=[0,0]
            break
        endif
        let a = getcurpos() 
        if count(strpart(getline('.'),0,a[2]),'$')%2==1
            break
        endif 
    endwhile 
endfunction

Saya bermaksud untuk menulis fungsi serupa untuk GrammerousCheck yang hanya berhenti pada kesalahan tata bahasa di luar matematika.

eyal karni
sumber