I would like to write a syntax highlighter for a language like this one:

block1 {
   keyword1 value;
   keyword2 value;

   sub_block1 {
      keyword3 value;
block2 {
   keyword1 value;

A block starts with a name followed by an opening brace (e.g. block1 {) and ends with a closing brace }. The block names and the keywords are specified by the language (authorized keywords and block names).

Like C language, this language is not sensitive to line break, multiple spaces or tabs and a line ends with a ;, except for block ends.

A block contains authorized keywords followed by values. It may also contains authorized sub-blocks. Note that a sub-block can contain sub-sub-blocks with its own authorized keywords.

I would like to highlight only authorized keywords or sub-blocks in a given block. I already wrote a syntax highlighter that highlight all the block names, but I am not able to tell vim to not highlight certain keywords or sub-blocks in a given block. By the way, I do not know how to detect if a given keyword or sub-block is in a given block.

Here is my current syntax highlighter:

" Vim syntax file
" Language: Notus
" Mantainer: Antoine Lemoine
" Last Change: 13 June 2016

if exists("b:current_syntax")

syn keyword notusTodo               contained TODO FIXME XXX

syn keyword notusBooleanValues      true false

syn keyword notusConditional        if else
syn keyword notusRepeat             while exit

syn keyword notusMathKeyword        abs ceil floor cos sin tan acos asin atan atan2 cosh sinh tanh acosh asinh atanh erf erfc exp log sqrt i2s pow modulo
syn keyword notusDeclaration        double integer boolean string define
syn keyword notusInclude            include std
syn keyword notusOutput             print export
syn match   notusInternalLanguage   "\k\@<!@\(double\|integer\|boolean\|return\|if\|else\|elseif\|exit\|while\|x\|y\|z\|t\)\>"

syn region  notusStringS            start=+'+ skip=+\\\\\|\\"+ end=+'+
syn region  notusStringD            start=+"+ skip=+\\\\\|\\"+ end=+"+

syn match   notusOperator           "\(+\|-\|/\|\*\)"
syn match   notusOperator           "\(\(>\|<\)=\=\|==\|!=\|=\||\|&\|!\)"
syn match   notusOperator           "\(?\|:\)"

syn match   notusComment            "#.*" contains=notusTodo
syn match   notusComment            "\s#.*" contains=notusTodo

" Integers
syn match   notusNumber             display "\<\d\+\(_\a\w*\)\=\>"
" floating point number, without a decimal point
syn match   notusFloatIll           display "\<\d\+[deDE][-+]\=\d\+\(_\a\w*\)\=\>"
" floating point number, starting with a decimal point
syn match   notusFloatIll           display "\.\d\+\([deDE][-+]\=\d\+\)\=\(_\a\w*\)\=\>"
" floating point number, no digits after decimal
syn match   notusFloatIll           display "\<\d\+\.\([deDE][-+]\=\d\+\)\=\(_\a\w*\)\=\>"
" floating point number, D or Q exponents
syn match   notusFloatIll           display "\<\d\+\.\d\+\([dD][-+]\=\d\+\)\=\(_\a\w*\)\=\>"
" floating point number
syn match   notusFloat              display "\<\d\+\.\d\+\([eE][-+]\=\d\+\)\=\(_\a\w*\)\=\>"

" Keywords per block

" Initial condition block
syn keyword notusKwIni              circle rectangle polygon surface_mesh union intersection difference shape instructions shaped_instructions

" Solver block
syn keyword notusKwSolver           preconditioner

" Main block
syn keyword notusKwMain             domain grid modeling numerical_parameters post_processing

"" Domain block
syn keyword notusKwDomain           immersed_boundary

"" Domain immersed_boundary
syn keyword notusKwIBD              shape

"" Grid block
syn keyword notusKwGrid             grid_x grid_y grid_z

"" Modeling block
syn keyword notusKwMod              fluids species equations

""" Fluids block
syn keyword notusKwFluids           fluid

""" Species block
syn keyword notusKwSpecies          species

""" Equations block
syn keyword notusKwEq               navier_stokes energy phase_advection species_transport

"""" Navier-Stokes block
syn keyword notusKwModNS            capilarity_term boundary_condition initial_condition_x initial_condition_y initial_condition_z immerserd_boundary_condition

"""" Energy block
syn keyword notusKwModEn            initial_condition boundary_condition immersed_boundary_condition phase_change linear_term source_term velocity_field

"""" Phase advection block
syn keyword notusKwModAdv           fluid velocity_field

""""" Fluid block
syn keyword notusKwModAdvFluid      boundary_condition initial_condition immersed_boundary_condition

"""" Species transport block
syn keyword notusKwModSpecies       species velocity_field

""""" Species block
syn keyword notusKwModAdvSpecies    boundary_condition initial_condition immersed_boundary_condition linear_term source_term

"" Numerical parameters block
syn keyword notusKwNum              navier_stokes energy phase_advection species_transport stop_tests

""" Navier-Stokes block
syn keyword notusKwNPNS             solver_pressure solver_momentum solver_ibd_extrapolation

""" Energy block
syn keyword notusKwNPEnergy         solver

""" Species transport block
syn keyword notusKwNPSpecies        species

"""" Species transport block
syn keyword notusKwNPSpeciesP       solver

""" Phase advection block
syn keyword notusKwNPAdv            vof_plic mof level_set

"" Post-processing block
syn keyword notusKwPostProc         validation

hi def link notusComment            Comment
hi def link notusTodo               Todo
hi def link notusDeclaration        Type
hi def link notusOperator           Operator
hi def link notusNumber             Number
hi def link notusFloatIll           Number
hi def link notusBooleanValues      Number
hi def link notusFloat              Number
hi def link notusRepeat             Repeat
hi def link notusConditional        Conditional
hi def link notusInternalLanguage   Function
hi def link notusMathKeyword        Function
hi def link notusInclude            Function
hi def link notusOutput             Function
hi def link notusStringS            String
hi def link notusStringD            String
hi def link notusKwIni              Keyword
hi def link notusKwSolver           Keyword
hi def link notusKwMain             Keyword
hi def link notusKwDomain           Keyword
hi def link notusKwIBD              Keyword
hi def link notusKwGrid             Keyword
hi def link notusKwMod              Keyword
hi def link notusKwFluids           Keyword
hi def link notusKwSpecies          Keyword
hi def link notusKwEq               Keyword
hi def link notusKwModNS            Keyword
hi def link notusKwModEn            Keyword
hi def link notusKwModAdv           Keyword
hi def link notusKwModAdvFluid      Keyword
hi def link notusKwModSpecies       Keyword
hi def link notusKwModAdvSpecies    Keyword
hi def link notusKwNum              Keyword
hi def link notusKwNPNS             Keyword
hi def link notusKwNPEnergy         Keyword
hi def link notusKwNPSpecies        Keyword
hi def link notusKwNPSpeciesP       Keyword
hi def link notusKwNPAdv            Keyword
hi def link notusKwPostProc         Keyword

let b:current_syntax="nts"

A pseudo documentation of the language can be found in http://notus-cfd.org/doc/d5/dbc/user_ui.html

Is there any syntax file that do similar work in the vim files? Do you have any idea on how to create such a syntax highlighter?

  • 2
    See :h :syn-cluster. Your question is to vague for a more concrete answer. Commented Sep 6, 2016 at 9:44
  • 2
    Also, show us what you've got as a syntax script so far. Commented Sep 6, 2016 at 15:19
  • The cluster is exactly what I need do make the block independent. However, I am not able to detect a block. I tried, for example, syn region modelingBlock start="modeling" end="}" keepend contains=... but it does not work as I want since it does not detect the opening brace. Commented Sep 6, 2016 at 15:53

1 Answer 1


If I understand you correctly, you only want detection of the {...} blocks if they are preceded by certain authorized names.

I would approach this via keyword matches of the names, which then instruct Vim to try a match with a following block (the skip... arguments allow for whitespace and new lines in between):

syn keyword myName block1 skipwhite skipnl skipempty nextgroup=myBlock
syn keyword myName sub_block1 skipwhite skipnl skipempty nextgroup=myBlock

The block definition is a simple region; it is contained so that it doesn't match on its own, only initiated by the nextgroup=myBlock from above. It needs to contains= all elements that can be nested; here, just the authorized names.

syn region myBlock start="{" end="}" contained contains=myName

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.