Reputation: 6171
This is a follow-up from VIM: simple steps to create syntax highlight file - for logfiles
I am trying to use the 'region-match' facility to syntax-highlight stack-traces in some logfiles: these logfiles (log4j-based) look a bit like this:
YYYY-MM-DD HH:MM:ss,SSSS...INFO...Message
YYYY-MM-DD HH:MM:ss,SSSS...INFO...Message
YYYY-MM-DD HH:MM:ss,SSSS...ERROR...Message
...stack trace...
...stack trace...
...blah blah, more server-vomit...
...
YYYY-MM-DD HH:MM:ss,SSSS...INFO...Message
So far I have managed to almost do what I want with this:
:syntax region error matchgroup=string start=/^\d\{4}-\d\{2}-\d\{2} \d\{2}:\d\{2}:\d\{2},\d\{3}.* ERROR/ end=/^\d\{4}-\d\{2}-\d\{2} \d\{2}:\d\{2}:\d\{2},\d\{3}/
But the issue, is that match goes too far. It includes the next record (ie, the match includes the next YYYY-MM-DD...
).
I believe this VIM manual example for quoted text suggests that I should be able to highlight in-between, but I don't seem to be able to map the syntax for my example.
So to be clear: I need to match the first YYYY-MM-DD...
line that includes ERROR
, and then all subsequent lines up to but not including the next YYYY-MM-DD
line.
Upvotes: 6
Views: 4791
Reputation: 9313
Tell Vim to use a positive lookahead using the \@=
construct. With a lookahead, you can match the text on the next line without including or consuming it. Use the same start
, but change your end
to:
/\(^\d\{4}-\d\{2}-\d\{2} \d\{2}:\d\{2}:\d\{2},\d\{3}\)\@=/
Note that this is incompatible with Vi.
Upvotes: 0
Reputation: 11
My file is an adaptation :-) here it is:
syntax region fatal start=/^\d\{4}-\d\{2}-\d\{2}.*FATAL.*/ end=/\n\d\{4}-\d\{2}-\d\{2}/me=s-1,re=s-1
syntax region error start=/^\d\{4}-\d\{2}-\d\{2}.*ERROR.*/ end=/\n\d\{4}-\d\{2}-\d\{2}/me=s-1,re=s-1
syntax region warn start=/^\d\{4}-\d\{2}-\d\{2}.*WARN.*/ end=/\n\d\{4}-\d\{2}-\d\{2}/me=s-1,re=s-1
syntax region info start=/^\d\{4}-\d\{2}-\d\{2}.*INFO.*/ end=/\n\d\{4}-\d\{2}-\d\{2}/me=s-1,re=s-1
syntax region debug start=/^\d\{4}-\d\{2}-\d\{2}.*DEBUG.*/ end=/\n\d\{4}-\d\{2}-\d\{2}/me=s-1,re=s-1
syntax region trace start=/^\d\{4}-\d\{2}-\d\{2}.*TRACE.*/ end=/\n\d\{4}-\d\{2}-\d\{2}/me=s-1,re=s-1
" Highlight colors for log levels.
hi fatal ctermfg=DarkRed ctermbg=Black
hi error ctermfg=Red ctermbg=Black
hi warn ctermfg=Magenta ctermbg=Black
hi info ctermfg=Green ctermbg=Black
hi debug ctermfg=LightCyan ctermbg=Black
hi trace ctermfg=LightMagenta ctermbg=Black
Upvotes: 1
Reputation: 72616
There are a lot of difficulties with overlapping regions in Vim's syntax highlighting engine. The order in which matches and regions are defined makes a difference and it can be very hard to make it do what you want.
The main thing I'd suggest is to look at :help syn-pattern-offset
. This provides a means to make the region end at the start of a pattern among other things. For example if your end pattern is:
end=/pattern/re=s-1
Then the region will end at the character before the p
of pattern.
This takes a lot of playing around to make it work and I'm far from being an expert on these things, but to get you started, try this:
syntax match logDate /^\d\{4}-\d\{2}-\d\{2}/ containedin=logDateTimeTypeLine nextgroup=logTime skipwhite
syntax match logTime /\d\{2}:\d\{2}:\d\{2},\d\{3}/ containedin=logDateTimeTypeLine,logTrace
syntax match logDateTimeTypeLine /^\d\{4}-\d\{2}-\d\{2} \d\{2}:\d\{2}:\d\{2},\d\{3}.*/
syntax region logTrace matchgroup=logErrorStartLine start=/^\d\{4}-\d\{2}-\d\{2} \d\{2}:\d\{2}:\d\{2},\d\{3}.*ERROR.*/ms=s,rs=e+1 end=/^\d\{4}-\d\{2}-\d\{2} \d\{2}:\d\{2}:\d\{2},\d\{3}/me=s-1,he=s-1,re=s-1
hi link logTrace Error
hi link logDateTimeTypeLine Keyword
hi link logDate String
hi link logTime Comment
hi logErrorStartLine guifg=red
Upvotes: 7
Reputation: 59804
:help keepend
:syntax region error matchgroup=string start=/.../ end=/.../ keepend
Upvotes: 2