As regiões de sintaxe do vim podem ser feitas para tocar / se sobrepor?

13

Há algum tempo, eu decidi aprender mais sobre como os arquivos de sintaxe do vim funcionam, criando os meus. Meu objetivo era criar um arquivo de sintaxe simples que dividisse o arquivo em 3 partes com base em delimitadores e incluísse arquivos de sintaxe preexistentes para duas dessas três partes.

Este é um arquivo de exemplo:

Some text, unstyled

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

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

O objetivo era aplicar git.vimapenas ao log e diff.vimapenas ao diff, excluindo os dois cabeçalhos. 1 Foi assim que meu arquivo de sintaxe acabou:

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"

Observe como endna primeira região é o mesmo que startna segunda região. Isso não funciona; a segunda região aparentemente não é detectada e o realce da sintaxe não é aplicado.

Eu posso fazer isso afrouxando a regex para end=/^===/e start=/=== Diff/, para que as regiões não se toquem, mas não gostem particularmente disso - é menos óbvio que se deve começar onde a outra termina.

Existe uma maneira de permitir que duas definições de região toquem os mesmos caracteres (e / ou tornem as arestas correspondentes exclusivas em vez de inclusivas) ou estou preso ao regex mais flexível?

1 (Sim, eu sei que git.viminclui diff.vim, mas este foi um exercício de aprendizado)

Izkata
fonte
Eu acho que isso deve ser possível usando um deslocamento "Region End" para tornar as bordas exclusivas (consulte :h :syn-pattern-offset), ou alterando a região GitLog para estender até o final do arquivo e a região Diff para estar inteiramente dentro da região GitLog . Eu não consegui fazer com que nenhum desses métodos funcionasse.
Rich
Testar isso ficou um pouco mais difícil pelo fato de que - como você observa - o git.vim já destaca a saída do diff. Pode ser uma ideia alterar seu exemplo de acordo!
Rico

Respostas:

4

Você pode dizer ao mecanismo de regex do Vim por onde começar a próxima partida.

Até agora eu sei que existem 2 maneiras:

  1. Use \zepara definir o final de uma partida:

    syntax region GitLog
        \ start=/^===* Log/
        \ end=/\ze^===* Diff/
        \ contains=@gitlog
    
  2. Use lookahead positivo \@=, que é chamado de correspondência de largura zero no Vim:

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

Assim, o fim-de-jogo "ponteiro" tipo de retrocede para o início da ^===* Difflinha, de modo que region Diff's startirá iniciar a sua correspondência na ^===* Difflinha novamente.

cychoi
fonte