Search code examples
vimvim-syntax-highlighting

vim - how to match linked sequences in syntax file


I want to create a syntax file in vim for a custom file type I have. Part of the syntax is this line

entry: 1,02:15:00,03:15:00,56,Some String

I would like to match every part separately to assign different colors. entry should be a part, 1 should be a part, 02:15:00 should be a part, 03:15:00 should be a different part, 56 yet another part, Some String a different part, and all ,s as a part. Each of these should be named differently so I can color them with different colors as needed.

I was able to match them with contains, but similar values (first time and second time) get the same name. I also tried using nextgroup to chain them one after another, but this left me with , having many names I need to color separately (and there are many commas in the original file not like the simple example I shown here).

Is there a way to do such syntax highlighting in a proper way?


Solution

  • You can link all comma names to one with

    " Adjust the below to make commas have another color.
    " It is common that instead of defining colors directly you link 
    " new highlighting groups to some standard one.
    hi def link MySyntaxComma Delimiter
    
    hi def link MySyntaxCommaAfterNumber       MySyntaxComma
    hi def link MySyntaxCommaAfterFirstTime    MySyntaxComma
    hi def link MySyntaxCommaAfterSecondTime   MySyntaxComma
    hi def link MySyntaxCommaAfterSecondNumber MySyntaxComma
    

    You can also use a loop with :execute to hide the repeating rules:

    syntax match MySyntaxEntryStart /^entry:\s*/ nextgroup=MySyntaxNumber1
    let s:rules=[['Number1', '\d\+'], ['Time1', '\d\d:\d\d:\d\d'], ['Time2', '\d\d:\d\d:\d\d'], ['Number2', '\d\+'], ['String', '.*']]
    while !empty(s:rules)
        let [s:name, s:reg]=remove(s:rules, 0)
        let s:cmd='syntax match MySyntax'.s:name.' /'.s:reg.'/ contained'
        if !empty(s:rules)
            let s:cmd.=' nextgroup=MySyntaxCommaAfter'.s:name
            execute 'syntax match MySyntaxCommaAfter'.s:name.' /,/ contained nextgroup=MySyntax'.s:rules[0][0]
            execute 'hi def link MySyntaxCommaAfter'.s:name.' MySyntaxComma'
        endif
        execute s:cmd
    endwhile
    unlet s:rules s:cmd s:name s:reg