Bisakah vim sintaks dibuat untuk menyentuh / tumpang tindih?

13

Jadi beberapa waktu yang lalu saya telah memutuskan untuk mempelajari lebih lanjut tentang bagaimana file sintaks vim bekerja, dengan membuat sendiri. Tujuan saya adalah membuat file sintaksis sederhana yang akan membagi file menjadi 3 bagian berdasarkan pembatas, dan menyertakan file sintaksis yang sudah ada sebelumnya untuk dua dari tiga bagian tersebut.

Ini adalah contoh file:

Some text, unstyled

==================== Log
(Output of git log)

==================== Diff
(Output of diff)

Tujuannya adalah untuk menerapkan git.vimhanya pada log, dan diff.vimhanya untuk diff, tidak termasuk dua header. 1 Seperti inilah tampilan file sintaks saya:

if exists("b:current_syntax")
    finish
endif

syntax include @gitlog $VIMRUNTIME/syntax/git.vim
syntax region GitLog
    \ start=/^===* Log/
    \ end=/^===* Diff/
    \ contains=@gitlog

syntax include @gitdiff $VIMRUNTIME/syntax/diff.vim
syntax region Diff
    \ start=/^===* Diff/
    \ end=/\n\n/
    \ contains=@gitdiff

let b:current_syntax = "logdiff"

Perhatikan bagaimana enddi wilayah pertama sama dengan startdi wilayah kedua. Ini tidak berfungsi; wilayah kedua tampaknya tidak terdeteksi dan penyorotan sintaks tidak diterapkan.

Saya bisa membuatnya bekerja dengan melonggarkan regex ke end=/^===/dan start=/=== Diff/, sehingga daerah tidak menyentuh, tetapi tidak terlalu seperti itu - kurang jelas bahwa satu seharusnya mulai di mana yang lain berakhir.

Apakah ada cara untuk memungkinkan dua definisi wilayah menyentuh karakter yang sama (dan / atau membuat tepi yang cocok menjadi eksklusif dan bukan inklusif) atau apakah saya terjebak dengan regex yang lebih longgar?

1 (Ya, saya tahu git.vimtermasuk diff.vim, tetapi ini adalah latihan pembelajaran)

Izkata
sumber
Saya pikir ini harus dimungkinkan dengan menggunakan offset "Region End" untuk membuat ujungnya eksklusif (lihat :h :syn-pattern-offset), atau dengan mengubah wilayah GitLog untuk memperluas ke akhir file, dan wilayah Diff untuk sepenuhnya berada di dalam wilayah GitLog . Saya tidak bisa mendapatkan salah satu dari metode ini untuk bekerja.
Kaya
Pengujian itu dibuat agak sulit oleh fakta bahwa - seperti yang Anda perhatikan - git.vim sudah menyoroti keluaran diff. Mungkin ide untuk mengubah contoh Anda sesuai!
Kaya

Jawaban:

4

Anda dapat memberi tahu mesin regim Vim tempat memulai pertandingan berikutnya.

Sejauh ini saya tahu ada 2 cara:

  1. Gunakan \zeuntuk mengatur akhir pertandingan:

    syntax region GitLog
        \ start=/^===* Log/
        \ end=/\ze^===* Diff/
        \ contains=@gitlog
    
  2. Gunakan lookahead positif \@=,, yang disebut pencocokan lebar-nol di Vim:

    syntax region GitLog
        \ start=/^===* Log/
        \ end=/\(^===* Diff\)\@=/
        \ contains=@gitlog
    

Jadi akhir-of-pertandingan "pointer" jenis memutar ulang ke awal ^===* Diffbaris, sehingga region Diff's startakan mulai pencocokan di ^===* Diffbaris lagi.

cychoi
sumber