" Language: Crystal
" Maintainer:
" rhysd <https://rhysd.github.io>
" Jeffrey Crochet <jlcrochet@pm.me>
"
" Based on Ruby syntax highlight
" which was made by Mirko Nasato and Doug Kearns
" ----------------------------------------------
" Prelude
if exists('b:current_syntax')
finish
endif
" Adding `@-@` should fix a wide variety of false positives related to
" instance/class variables with keywords in their name, like @def and
" @class
syn iskeyword @,48-57,_,192-255,@-@
" eCrystal Config
if exists('g:main_syntax') && g:main_syntax ==# 'ecrystal'
let b:crystal_no_expensive = 1
end
" Folding Config
if has('folding') && exists('g:crystal_fold')
setlocal foldmethod=syntax
endif
let s:foldable_groups = split(
\ get(
\ b:,
\ 'crystal_foldable_groups',
\ get(g:, 'crystal_foldable_groups', 'ALL')
\ )
\ )
function! s:foldable(...) abort
if index(s:foldable_groups, 'NONE') > -1
return 0
endif
if index(s:foldable_groups, 'ALL') > -1
return 1
endif
for l:i in a:000
if index(s:foldable_groups, l:i) > -1
return 1
endif
endfor
return 0
endfunction
function! s:run_syntax_fold(args) abort
let [_0, _1, groups, cmd; _] = matchlist(a:args, '\(["'']\)\(.\{-}\)\1\s\+\(.*\)')
if call('s:foldable', split(groups))
let cmd .= ' fold'
endif
exe cmd
endfunction
com! -nargs=* SynFold call s:run_syntax_fold(<q-args>)
" Top and Not-Top Clusters
syn cluster crystalTop contains=TOP
syn cluster crystalNotTop contains=CONTAINED
" Whitespace Errors
if exists('g:crystal_space_errors')
if !exists('g:crystal_no_trail_space_error')
syn match crystalSpaceError display excludenl "\s\+$"
endif
if !exists('g:crystal_no_tab_space_error')
syn match crystalSpaceError display " \+\t"me=e-1
endif
endif
" Operators
if exists('g:crystal_operators')
syn match crystalOperator "[~!^&|*/%+-]\|<=>\|<=\|\%(<\|\<\%(class\|struct\)\s\+\u\w*\s*\)\@<!<[^<]\@=\|===\|==\|=\~\|>>\|>=\|=\@1<!>\|\*\*\|\.\.\.\|\.\.\|::"
syn match crystalOperator "->\|-=\|/=\|\*\*=\|\*=\|&&=\|&=\|&&\|||=\||=\|||\|%=\|+=\|!\~\|!=\|//"
syn region crystalBracketOperator matchgroup=crystalOperator start="\%(\w[?!]\=\|[]})]\)\@2<=\[" end="]" contains=TOP
endif
" Expression Substitution and Backslash Notation
syn match crystalStringEscape "\\\\\|\\[abefnrstv]\|\\\o\{1,3}\|\\x\x\{1,2}" contained display
syn match crystalStringEscape "\%(\\M-\\C-\|\\C-\\M-\|\\M-\\c\|\\c\\M-\|\\c\|\\C-\|\\M-\)\%(\\\o\{1,3}\|\\x\x\{1,2}\|\\\=\S\)" contained display
syn region crystalInterpolation matchgroup=crystalInterpolationDelim start="#{" end="}" contained contains=TOP
syn region crystalNoInterpolation start="\\#{" end="}" contained
syn match crystalNoInterpolation "\\#{" display contained
syn match crystalDelimEscape "\\[(<{\[)>}\]]" transparent display contained contains=NONE
syn region crystalNestedParentheses matchgroup=crystalString start="(" skip="\\\\\|\\)" end=")" transparent contained
syn region crystalNestedCurlyBraces matchgroup=crystalString start="{" skip="\\\\\|\\}" end="}" transparent contained
syn region crystalNestedAngleBrackets matchgroup=crystalString start="<" skip="\\\\\|\\>" end=">" transparent contained
syn region crystalNestedSquareBrackets matchgroup=crystalString start="\[" skip="\\\\\|\\\]" end="\]" transparent contained
" These are mostly Oniguruma ready
syn region crystalRegexpComment matchgroup=crystalRegexpSpecial start="(?#" skip="\\)" end=")" contained
syn region crystalRegexpParens matchgroup=crystalRegexpSpecial start="(\(?:\|?<\=[=!]\|?>\|?<[a-z_]\w*>\|?[imx]*-[imx]*:\=\|\%(?#\)\@!\)" skip="\\)" end=")" contained transparent contains=@crystalRegexpSpecial
syn region crystalRegexpBrackets matchgroup=crystalRegexpCharClass start="\[\^\=" skip="\\\]" end="\]" contained transparent contains=crystalStringEscape,crystalRegexpEscape,crystalRegexpCharClass oneline
syn match crystalRegexpCharClass "\\[DdHhSsWw]" contained display
syn match crystalRegexpCharClass "\[:\^\=\%(alnum\|alpha\|ascii\|blank\|cntrl\|digit\|graph\|lower\|print\|punct\|space\|upper\|xdigit\):\]" contained
syn match crystalRegexpEscape "\\[].*?+^$|\\/(){}[]" contained
syn match crystalRegexpQuantifier "[*?+][?+]\=" contained display
syn match crystalRegexpQuantifier "{\d\+\%(,\d*\)\=}?\=" contained display
syn match crystalRegexpAnchor "[$^]\|\\[ABbGZz]" contained display
syn match crystalRegexpDot "\." contained display
syn match crystalRegexpSpecial "|" contained display
syn match crystalRegexpSpecial "\\[1-9]\d\=\d\@!" contained display
syn match crystalRegexpSpecial "\\k<\%([a-z_]\w*\|-\=\d\+\)\%([+-]\d\+\)\=>" contained display
syn match crystalRegexpSpecial "\\k'\%([a-z_]\w*\|-\=\d\+\)\%([+-]\d\+\)\='" contained display
syn match crystalRegexpSpecial "\\g<\%([a-z_]\w*\|-\=\d\+\)>" contained display
syn match crystalRegexpSpecial "\\g'\%([a-z_]\w*\|-\=\d\+\)'" contained display
syn cluster crystalStringSpecial contains=crystalInterpolation,crystalNoInterpolation,crystalStringEscape
syn cluster crystalExtendedStringSpecial contains=@crystalStringSpecial,crystalNestedParentheses,crystalNestedCurlyBraces,crystalNestedAngleBrackets,crystalNestedSquareBrackets,crystalNestedRawParentheses,crystalNestedRawCurlyBraces,crystalNestedRawAngleBrackets,crystalNestedRawSquareBrackets
syn cluster crystalRegexpSpecial contains=crystalInterpolation,crystalNoInterpolation,crystalStringEscape,crystalRegexpSpecial,crystalRegexpEscape,crystalRegexpBrackets,crystalRegexpCharClass,crystalRegexpDot,crystalRegexpQuantifier,crystalRegexpAnchor,crystalRegexpParens,crystalRegexpComment
" Numbers and ASCII Codes
syn match crystalASCIICode "\%(\w\|[]})\"'/]\)\@1<!\%(?\%(\\M-\\C-\|\\C-\\M-\|\\M-\\c\|\\c\\M-\|\\c\|\\C-\|\\M-\)\=\%(\\\o\{1,3}\|\\x\x\{1,2}\|\\\=\S\)\)"
syn match crystalInteger "\<0x[[:xdigit:]_]\+\%([ui]\%(8\|16\|32\|64\|128\)\|f\%(32\|64\)\)\=\>" display
syn match crystalInteger "\<0o[0-7_]\+\%([ui]\%(8\|16\|32\|64\|128\)\)\=\>" display
syn match crystalInteger "\<0b[01_]\+\%([ui]\%(8\|16\|32\|64\|128\)\)\=\>" display
syn match crystalInteger "\<\d[[:digit:]_]*\%([ui]\%(8\|16\|32\|64\|128\)\|f\%(32\|64\)\)\=\>" contains=crystalInvalidInteger display
syn match crystalFloat "\<\d[[:digit:]_]*\.\d[[:digit:]_]*\%(f\%(32\|64\)\)\=\>" contains=crystalInvalidInteger display
syn match crystalFloat "\<\d[[:digit:]_]*\%(\.\d[[:digit:]_]*\)\=\%([eE][-+]\=[[:digit:]_]\+\)\%(f\%(32\|64\)\)\=\>" contains=crystalInvalidInteger display
" Note: 042 is invalid but 0, 0_, 0_u8 and 0_1 are valid (#73)
syn match crystalInvalidInteger "\%(\.\|[eE][+-]\)\@2<!\<0\d\+\>" contained containedin=crystalFloat,crystalInteger display
" Identifiers
syn match crystalLocalVariableOrMethod "\<[_[:lower:]][_[:alnum:]]*[?!=]\=" contains=NONE display
syn match crystalBlockArgument "&[_[:lower:]][_[:alnum:]]" contains=NONE display transparent
syn match crystalTypeName "\%(\%([.@$]\@1<!\.\)\@1<!\<\|::\)\_s*\zs\u\w*\%(\>\|::\)\@=" contained
syn match crystalClassName "\%(\%([.@$]\@1<!\.\)\@1<!\<\|::\)\_s*\zs\u\w*\%(\>\|::\)\@=" contained
syn match crystalModuleName "\%(\%([.@$]\@1<!\.\)\@1<!\<\|::\)\_s*\zs\u\w*\%(\>\|::\)\@=" contained
syn match crystalStructName "\%(\%([.@$]\@1<!\.\)\@1<!\<\|::\)\_s*\zs\u\w*\%(\>\|::\)\@=" contained
syn match crystalLibName "\%(\%([.@$]\@1<!\.\)\@1<!\<\|::\)\_s*\zs\u\w*\%(\>\|::\)\@=" contained
syn match crystalEnumName "\%(\%([.@$]\@1<!\.\)\@1<!\<\|::\)\_s*\zs\u\w*\%(\>\|::\)\@=" contained
syn match crystalAnnotationName "\%(\%([.@$]\@1<!\.\)\@1<!\<\|::\)\_s*\zs\u\w*\%(\>\|::\)\@=" contained
syn match crystalConstant "\%(\%([.@$]\@1<!\.\)\@1<!\<\|::\)\_s*\zs\u\w*\%(\>\|::\)\@="
syn match crystalClassVariable "@@\%(\h\|%\|[^\x00-\x7F]\)\%(\w\|%\|[^\x00-\x7F]\)*" display
syn match crystalInstanceVariable "@\%(\h\|%\|[^\x00-\x7F]\)\%(\w\|%\|[^\x00-\x7F]\)*" display
syn match crystalFreshVariable "\%(\h\|[^\x00-\x7F]\)\@1<!%\%(\h\|[^\x00-\x7F]\)\%(\w\|%\|[^\x00-\x7F]\)*" display
syn match crystalSymbol "[]})\"':]\@1<!:\%(\^\|\~\|<<\|<=>\|<=\|<\|===\|[=!]=\|[=!]\~\|!\|>>\|>=\|>\||\|-@\|-\|/\|\[][=?]\|\[]\|\*\*\|\*\|&\|%\|+@\|+\|`\)"
syn match crystalSymbol "[]})\"':]\@1<!:\$\%(-.\|[`~<=>_,;:!?/.'"@$*\&+0]\)"
syn match crystalSymbol "[]})\"':]\@1<!:\%(\$\|@@\=\)\=\%(\h\|[^\x00-\x7F]\)\%(\w\|[^\x00-\x7F]\)*"
syn match crystalSymbol "[]})\"':]\@1<!:\%(\h\|%\|[^\x00-\x7F]\)\%(\w\|%\|[^\x00-\x7F]\)*\%([?!=]>\@!\)\="
syn match crystalSymbol "\%([{(,]\_s*\)\@<=\l\w*[!?]\=::\@!"he=e-1
syn match crystalSymbol "[]})\"':]\@1<!\%(\h\|[^\x00-\x7F]\)\%(\w\|[^\x00-\x7F]\)*[!?]\=:\s\@="he=e-1
syn match crystalSymbol "\%([{(,]\_s*\)\@<=[[:space:],{]\l\w*[!?]\=::\@!"hs=s+1,he=e-1
syn match crystalSymbol "[[:space:],{]\%(\h\|[^\x00-\x7F]\)\%(\w\|[^\x00-\x7F]\)*[!?]\=:\s\@="hs=s+1,he=e-1
SynFold ':' syn region crystalSymbol start="[]})\"':]\@1<!:\"" end="\"" skip="\\\\\|\\\"" contains=@crystalStringSpecial
syn match crystalBlockParameter "\%(\h\|%\|[^\x00-\x7F]\)\%(\w\|%\|[^\x00-\x7F]\)*" contained
syn region crystalBlockParameterList start="\%(\%(\<do\>\|{\)\s*\)\@<=|" end="|" oneline display contains=crystalBlockParameter
" In Crystal, almost all special variables were removed and global variables
" are not supported https://github.com/crystal-lang/crystal/commit/e872c716d0e936557b34c614efc5a4c24d845f79
" NOTE: Only $~ and $? are supported since they are actually not global.
syn match crystalPredefinedVariable "$[~?]"
syn match crystalPredefinedConstant "\%(\%(\.\@1<!\.\)\@2<!\|::\)\_s*\zs\%(ARGF\|ARGV\|ENV\|STDERR\|STDIN\|STDOUT\)\>\%(\s*(\)\@!"
" Normal Regular Expression
SynFold '/' syn region crystalRegexp matchgroup=crystalRegexpDelimiter start="\%(\%(^\|\<\%(and\|or\|while\|until\|unless\|if\|elsif\|ifdef\|when\|in\|not\|then\|else\)\|[;\~=!|&(,[<>?:*+-]\)\s*\)\@<=/" end="/[imx]*" skip="\\\\\|\\/" contains=@crystalRegexpSpecial
SynFold '/' syn region crystalRegexp matchgroup=crystalRegexpDelimiter start="\%(\h\k*\s\+\)\@<=/[ \t=/]\@!" end="/[imx]*" skip="\\\\\|\\/" contains=@crystalRegexpSpecial
" Generalized Regular Expression
SynFold '%' syn region crystalRegexp matchgroup=crystalRegexpDelimiter start="%r{" end="}[imx]*" skip="\\\\\|\\}" contains=@crystalRegexpSpecial,crystalNestedRawCurlyBraces
SynFold '%' syn region crystalRegexp matchgroup=crystalRegexpDelimiter start="%r<" end=">[imx]*" skip="\\\\\|\\>" contains=@crystalRegexpSpecial,crystalNestedRawAngleBrackets
SynFold '%' syn region crystalRegexp matchgroup=crystalRegexpDelimiter start="%r\[" end="\][imx]*" skip="\\\\\|\\\]" contains=@crystalRegexpSpecial
SynFold '%' syn region crystalRegexp matchgroup=crystalRegexpDelimiter start="%r(" end=")[imx]*" skip="\\\\\|\\)" contains=@crystalRegexpSpecial
SynFold '%' syn region crystalRegexp matchgroup=crystalRegexpDelimiter start="%r|" end="|[imx]*" skip="\\\\\|\\|" contains=@crystalRegexpSpecial
" Normal String
let s:spell_cluster = exists('crystal_spellcheck_strings') ? ',@Spell' : ''
let s:fold_arg = s:foldable('string') ? ' fold' : ''
exe 'syn region crystalString matchgroup=crystalStringDelimiter start="\"" end="\"" skip="\\\\\|\\\"" contains=@crystalStringSpecial' . s:spell_cluster . s:fold_arg
unlet s:spell_cluster s:fold_arg
" Shell Command Output
SynFold 'string' syn region crystalString matchgroup=crystalStringDelimiter start="`" end="`" skip="\\\\\|\\`" contains=@crystalStringSpecial
" Character
syn match crystalCharLiteral "'\%([^\\]\|\\[abefnrstv'\\]\|\\\o\{1,3}\|\\x\x\{1,2}\|\\u\x\{4}\)'" contains=crystalStringEscape display
" Generalized Single Quoted String, Symbol and Array of Strings
syn region crystalNestedRawParentheses matchgroup=crystalString start="(" end=")" transparent contained
syn region crystalNestedRawCurlyBraces matchgroup=crystalString start="{" end="}" transparent contained
syn region crystalNestedRawAngleBrackets matchgroup=crystalString start="<" end=">" transparent contained
syn region crystalNestedRawSquareBrackets matchgroup=crystalString start="\[" end="\]" transparent contained
SynFold '%' syn region crystalString matchgroup=crystalStringDelimiter start="%q(" end=")" contains=crystalNestedRawParentheses
SynFold '%' syn region crystalString matchgroup=crystalStringDelimiter start="%q{" end="}" contains=crystalNestedRawCurlyBraces
SynFold '%' syn region crystalString matchgroup=crystalStringDelimiter start="%q<" end=">" contains=crystalNestedRawAngleBrackets
SynFold '%' syn region crystalString matchgroup=crystalStringDelimiter start="%q\[" end="\]" contains=crystalNestedRawSquareBrackets
SynFold '%' syn region crystalString matchgroup=crystalStringDelimiter start="%q|" end="|"
SynFold '%' syn region crystalString matchgroup=crystalStringDelimiter start="%[wi](" end=")" skip="\\\\\|\\)" contains=crystalNestedParentheses,crystalDelimEscape
SynFold '%' syn region crystalString matchgroup=crystalStringDelimiter start="%[wi]{" end="}" skip="\\\\\|\\}" contains=crystalNestedCurlyBraces,crystalDelimEscape
SynFold '%' syn region crystalString matchgroup=crystalStringDelimiter start="%[wi]<" end=">" skip="\\\\\|\\>" contains=crystalNestedAngleBrackets,crystalDelimEscape
SynFold '%' syn region crystalString matchgroup=crystalStringDelimiter start="%[wi]\[" end="\]" skip="\\\\\|\\\]" contains=crystalNestedSquareBrackets,crystalDelimEscape
SynFold '%' syn region crystalString matchgroup=crystalStringDelimiter start="%[wi]|" end="|" skip="\\\\\|\\|" contains=crystalDelimEscape
" Generalized Double Quoted String and Array of Strings and Shell Command Output
" Note: %= is not matched here as the beginning of a double quoted string
SynFold '%' syn region crystalString matchgroup=crystalStringDelimiter start="%[Qx]\=(" end=")" skip="\\\\\|\\)" contains=@crystalStringSpecial,crystalNestedParentheses,crystalDelimEscape
SynFold '%' syn region crystalString matchgroup=crystalStringDelimiter start="%[Qx]\={" end="}" skip="\\\\\|\\}" contains=@crystalStringSpecial,crystalNestedCurlyBraces,crystalDelimEscape
SynFold '%' syn region crystalString matchgroup=crystalStringDelimiter start="%[Qx]\=<" end=">" skip="\\\\\|\\>" contains=@crystalStringSpecial,crystalNestedAngleBrackets,crystalDelimEscape
SynFold '%' syn region crystalString matchgroup=crystalStringDelimiter start="%[Qx]\=\[" end="\]" skip="\\\\\|\\\]" contains=@crystalStringSpecial,crystalNestedSquareBrackets,crystalDelimEscape
SynFold '%' syn region crystalString matchgroup=crystalStringDelimiter start="%[Qx]\=|" end="|" skip="\\\\\|\\|" contains=@crystalStringSpecial,crystalDelimEscape
" Here Document
syn region crystalHeredocStart matchgroup=crystalStringDelimiter start=+\%(\%(class\s*\|\%([]})"'.]\|::\)\)\_s*\|\w\)\@<!<<-\=\zs\%(\%(\h\|[^\x00-\x7F]\)\%(\w\|[^\x00-\x7F]\)*\)+ end=+$+ oneline contains=TOP
syn region crystalHeredocStart matchgroup=crystalStringDelimiter start=+\%(\%(class\s*\|\%([]})"'.]\|::\)\)\_s*\|\w\)\@<!<<-\=\zs"\%([^"]*\)"+ end=+$+ oneline contains=TOP
syn region crystalHeredocStart matchgroup=crystalStringDelimiter start=+\%(\%(class\s*\|\%([]})"'.]\|::\)\)\_s*\|\w\)\@<!<<-\=\zs'\%([^']*\)'+ end=+$+ oneline contains=TOP
syn region crystalHeredocStart matchgroup=crystalStringDelimiter start=+\%(\%(class\s*\|\%([]})"'.]\|::\)\)\_s*\|\w\)\@<!<<-\=\zs`\%([^`]*\)`+ end=+$+ oneline contains=TOP
SynFold '<<' syn region crystalString start=+\%(\%(class\|::\)\_s*\|\%([]})"'.]\)\s\|\w\)\@<!<<\z(\%(\h\|[^\x00-\x7F]\)\%(\w\|[^\x00-\x7F]\)*\)\ze\%(.*<<-\=['`"]\=\h\)\@!+hs=s+2 matchgroup=crystalStringDelimiter end=+^\z1$+ contains=crystalHeredocStart,crystalHeredoc,@crystalStringSpecial keepend
SynFold '<<' syn region crystalString start=+\%(\%(class\|::\)\_s*\|\%([]})"'.]\)\s\|\w\)\@<!<<"\z([^"]*\)"\ze\%(.*<<-\=['`"]\=\h\)\@!+hs=s+2 matchgroup=crystalStringDelimiter end=+^\z1$+ contains=crystalHeredocStart,crystalHeredoc,@crystalStringSpecial keepend
SynFold '<<' syn region crystalString start=+\%(\%(class\|::\)\_s*\|\%([]})"'.]\)\s\|\w\)\@<!<<'\z([^']*\)'\ze\%(.*<<-\=['`"]\=\h\)\@!+hs=s+2 matchgroup=crystalStringDelimiter end=+^\z1$+ contains=crystalHeredocStart,crystalHeredoc keepend
SynFold '<<' syn region crystalString start=+\%(\%(class\|::\)\_s*\|\%([]})"'.]\)\s\|\w\)\@<!<<`\z([^`]*\)`\ze\%(.*<<-\=['`"]\=\h\)\@!+hs=s+2 matchgroup=crystalStringDelimiter end=+^\z1$+ contains=crystalHeredocStart,crystalHeredoc,@crystalStringSpecial keepend
SynFold '<<' syn region crystalString start=+\%(\%(class\|::\)\_s*\|\%([]}).]\)\s\|\w\)\@<!<<-\z(\%(\h\|[^\x00-\x7F]\)\%(\w\|[^\x00-\x7F]\)*\)\ze\%(.*<<-\=['`"]\=\h\)\@!+hs=s+3 matchgroup=crystalStringDelimiter end=+^\s*\zs\z1$+ contains=crystalHeredocStart,@crystalStringSpecial keepend
SynFold '<<' syn region crystalString start=+\%(\%(class\|::\)\_s*\|\%([]}).]\)\s\|\w\)\@<!<<-"\z([^"]*\)"\ze\%(.*<<-\=['`"]\=\h\)\@!+hs=s+3 matchgroup=crystalStringDelimiter end=+^\s*\zs\z1$+ contains=crystalHeredocStart,@crystalStringSpecial keepend
SynFold '<<' syn region crystalString start=+\%(\%(class\|::\)\_s*\|\%([]}).]\)\s\|\w\)\@<!<<-'\z([^']*\)'\ze\%(.*<<-\=['`"]\=\h\)\@!+hs=s+3 matchgroup=crystalStringDelimiter end=+^\s*\zs\z1$+ contains=crystalHeredocStart keepend
SynFold '<<' syn region crystalString start=+\%(\%(class\|::\)\_s*\|\%([]}).]\)\s\|\w\)\@<!<<-`\z([^`]*\)`\ze\%(.*<<-\=['`"]\=\h\)\@!+hs=s+3 matchgroup=crystalStringDelimiter end=+^\s*\zs\z1$+ contains=crystalHeredocStart,@crystalStringSpecial keepend
" Module, Class, Method, and Alias Declarations
syn match crystalAliasDeclaration "[^[:space:];#.()]\+" contained contains=crystalSymbol,crystalPredefinedVariable nextgroup=crystalAliasDeclaration2 skipwhite
syn match crystalAliasDeclaration2 "[^[:space:];#.()]\+" contained contains=crystalSymbol,crystalPredefinedVariable
syn match crystalMethodDeclaration "[^[:space:];#(]\+" contained contains=crystalConstant,crystalFunction,crystalBoolean,crystalPseudoVariable,crystalInstanceVariable,crystalClassVariable
syn match crystalFunctionDeclaration "[^[:space:];#(=]\+" contained contains=crystalFunction
syn match crystalTypeDeclaration "[^[:space:];#=]\+" contained contains=crystalTypeName
syn match crystalClassDeclaration "[^[:space:];#<]\+" contained contains=crystalClassName,crystalOperator
syn match crystalModuleDeclaration "[^[:space:];#]\+" contained contains=crystalModuleName,crystalOperator
syn match crystalStructDeclaration "[^[:space:];#<]\+" contained contains=crystalStructName,crystalOperator
syn match crystalLibDeclaration "[^[:space:];#]\+" contained contains=crystalLibName,crystalOperator
syn match crystalMacroDeclaration "[^[:space:];#(]\+" contained contains=crystalFunction
syn match crystalEnumDeclaration "[^[:space:];#<\"]\+" contained contains=crystalEnumName
syn match crystalAnnotationDeclaration "[^[:space:];#]\+" contained contains=crystalAnnotationName
syn match crystalFunction "\<[_[:alpha:]][_[:alnum:]]*[?!=]\=[[:alnum:]_.:?!=]\@!" contained containedin=crystalMethodDeclaration,crystalFunctionDeclaration
syn match crystalFunction "\%(\s\|^\)\@1<=[_[:alpha:]][_[:alnum:]]*[?!=]\=\%(\s\|$\)\@=" contained containedin=crystalAliasDeclaration,crystalAliasDeclaration2
syn match crystalFunction "\%([[:space:].]\|^\)\@1<=\%(\[\][=?]\=\|\*\*\|[+-]@\=\|[*/%|&^~]\|<<\|>>\|[<>]=\=\|<=>\|===\|[=!]=\|[=!]\~\|!\|`\)\%([[:space:];#(]\|$\)\@=" contained containedin=crystalAliasDeclaration,crystalAliasDeclaration2,crystalMethodDeclaration,crystalFunctionDeclaration
syn cluster crystalDeclaration contains=crystalAliasDeclaration,crystalAliasDeclaration2,crystalMethodDeclaration,crystalFunctionDeclaration,crystalModuleDeclaration,crystalClassDeclaration,crystalStructDeclaration,crystalLibDeclaration,crystalMacroDeclaration,crystalFunction,crystalBlockParameter,crystalTypeDeclaration,crystalEnumDeclaration,crystalAnnotationDeclaration
" Keywords
" Note: the following keywords have already been defined:
" begin case class def do end for if module unless until while
syn match crystalControl "\<\%(break\|next\|rescue\|return\)\>[?!]\@!"
syn match crystalKeyword "\<\%(super\|previous_def\|yield\|of\|with\|uninitialized\|union\|out\)\>[?!]\@!"
syn match crystalBoolean "\<\%(true\|false\)\>[?!]\@!"
syn match crystalPseudoVariable "\<\%(nil\|__DIR__\|__FILE__\|__LINE__\|__END_LINE__\)\>[?!]\@!" " TODO: reorganise
syn match crystalPseudoVariable "\<self\>[?!]\@!"
" Expensive Mode - match 'end' with the appropriate opening keyword for syntax
" based folding and special highlighting of module/class/method definitions
if !exists('b:crystal_no_expensive') && !exists('g:crystal_no_expensive')
syn match crystalDefine "\<alias\>" nextgroup=crystalAliasDeclaration skipwhite skipnl
syn match crystalDefine "\<def\>" nextgroup=crystalMethodDeclaration skipwhite skipnl
syn match crystalDefine "\<fun\>" nextgroup=crystalFunctionDeclaration skipwhite skipnl
syn match crystalDefine "\<\%(type\|alias\)\>\%(\s*\h\w*\s*=\)\@=" nextgroup=crystalTypeDeclaration skipwhite skipnl
syn match crystalClass "\<class\>" nextgroup=crystalClassDeclaration skipwhite skipnl
syn match crystalModule "\<module\>" nextgroup=crystalModuleDeclaration skipwhite skipnl
syn match crystalStruct "\<struct\>" nextgroup=crystalStructDeclaration skipwhite skipnl
syn match crystalLib "\<lib\>" nextgroup=crystalLibDeclaration skipwhite skipnl
syn match crystalMacro "\<macro\>" nextgroup=crystalMacroDeclaration skipwhite skipnl
syn match crystalEnum "\<enum\>" nextgroup=crystalEnumDeclaration skipwhite skipnl
syn match crystalAnnotation "\<annotation\>" nextgroup=crystalAnnotationDeclaration skipwhite skipnl
SynFold 'def' syn region crystalMethodBlock start="\<def\>" matchgroup=crystalDefine end="\%(\<def\_s\+\)\@<!\<end\>" contains=TOP,crystalForallKeyword
SynFold 'macro' syn region crystalMethodBlock start="\<macro\>" matchgroup=crystalDefine end="\%(\<macro\_s\+\)\@<!\<end\>" contains=TOP
SynFold 'class' syn region crystalBlock start="\<class\>" matchgroup=crystalClass end="\<end\>" contains=TOP
SynFold 'module' syn region crystalBlock start="\<module\>" matchgroup=crystalModule end="\<end\>" contains=TOP
SynFold 'struct' syn region crystalBlock start="\<struct\>" matchgroup=crystalStruct end="\<end\>" contains=TOP
SynFold 'lib' syn region crystalBlock start="\<lib\>" matchgroup=crystalLib end="\<end\>" contains=TOP
SynFold 'enum' syn region crystalBlock start="\<enum\>" matchgroup=crystalEnum end="\<end\>" contains=TOP
SynFold 'annotation' syn region crystalBlock start="\<annotation\>" matchgroup=crystalAnnotation end="\<end\>" contains=TOP
" keywords in method declaration
syn match crystalForallKeyword "\<forall\>[?!]\@!" contained containedin=crystalMethodBlock
" modifiers
syn match crystalConditionalModifier "\<\%(if\|unless\|ifdef\)\>" display
SynFold 'do' syn region crystalDoBlock matchgroup=crystalControl start="\<do\>" end="\<end\>" contains=TOP
" curly bracket block or hash literal
SynFold '{' syn region crystalCurlyBlock matchgroup=crystalCurlyBlockDelimiter start="{" end="}" contains=TOP
SynFold '[' syn region crystalArrayLiteral matchgroup=crystalArrayDelimiter start="\%(\w\|[\]})]\)\@1<!\[" end="]" contains=TOP
" statements without 'do'
SynFold 'begin' syn region crystalBlockExpression matchgroup=crystalControl start="\<begin\>" end="\<end\>" contains=TOP
SynFold 'while' syn region crystalRepeatExpression matchgroup=crystalRepeat start="\<\%(while\|until\)\>" end="\<end\>" contains=TOP
SynFold 'case' syn region crystalCaseExpression matchgroup=crystalConditional start="\<case\>" end="\<end\>" contains=TOP
SynFold 'select' syn region crystalSelectExpression matchgroup=crystalConditional start="\<select\>" end="\<end\>" contains=TOP
SynFold 'if' syn region crystalConditionalExpression matchgroup=crystalConditional start="\%(\%(^\|\.\.\.\=\|[{:,;([<>~\*/%&^|+=-]\|\%(\<[_[:lower:]][_[:alnum:]]*\)\@<![?!]\)\s*\)\@<=\%(if\|ifdef\|unless\)\>" end="\%(\%(\%(\.\@1<!\.\)\|::\)\s*\)\@<!\<end\>" contains=TOP
syn match crystalConditional "\<\%(then\|else\|when\|in\)\>[?!]\@!" contained containedin=crystalCaseExpression
syn match crystalConditional "\<\%(when\|else\)\>[?!]\@!" contained containedin=crystalSelectExpression
syn match crystalConditional "\<\%(then\|else\|elsif\)\>[?!]\@!" contained containedin=crystalConditionalExpression
syn match crystalExceptional "\<\%(\%(\%(;\|^\)\s*\)\@<=rescue\|else\|ensure\)\>[?!]\@!" contained containedin=crystalBlockExpression
syn match crystalMethodExceptional "\<\%(\%(\%(;\|^\)\s*\)\@<=rescue\|else\|ensure\)\>[?!]\@!" contained containedin=crystalMethodBlock
SynFold 'macro' syn region crystalMacroBlock matchgroup=crystalMacroRegion start="\z(\\\=\){%\s*\%(\%(if\|for\|begin\)\>.*\|.*\<do\>\)\s*%}" end="\z1{%\s*end\s*%}" transparent contains=TOP
if !exists('g:crystal_minlines')
let g:crystal_minlines = 500
endif
exec 'syn sync minlines=' . g:crystal_minlines
else
" Non-expensive mode
syn match crystalControl "\<def\>[?!]\@!" nextgroup=crystalMethodDeclaration skipwhite skipnl
syn match crystalControl "\<fun\>[?!]\@!" nextgroup=crystalFunctionDeclaration skipwhite skipnl
syn match crystalControl "\<class\>[?!]\@!" nextgroup=crystalClassDeclaration skipwhite skipnl
syn match crystalControl "\<module\>[?!]\@!" nextgroup=crystalModuleDeclaration skipwhite skipnl
syn match crystalControl "\<struct\>[?!]\@!" nextgroup=crystalStructDeclaration skipwhite skipnl
syn match crystalControl "\<lib\>[?!]\@!" nextgroup=crystalLibDeclaration skipwhite skipnl
syn match crystalControl "\<macro\>[?!]\@!" nextgroup=crystalMacroDeclaration skipwhite skipnl
syn match crystalControl "\<enum\>[?!]\@!" nextgroup=crystalEnumDeclaration skipwhite skipnl
syn match crystalControl "\<annotation\>[?!]\@!" nextgroup=crystalAnnotationDeclaration skipwhite skipnl
syn match crystalControl "\<\%(case\|begin\|do\|if\|ifdef\|unless\|while\|select\|until\|else\|elsif\|ensure\|then\|when\|in\|end\)\>[?!]\@!"
syn match crystalKeyword "\<alias\>[?!]\@!"
syn match crystalForallKeyword "\<forall\>[?!]\@!"
endif
" Link attribute
syn region crystalLinkAttr matchgroup=crystalLinkAttrDelim start="@\[" end="]" contains=TOP display oneline
" Special Methods
if !exists('g:crystal_no_special_methods')
syn keyword crystalAccess protected private
" attr is a common variable name
syn keyword crystalAttribute abstract
syn match crystalAttribute "\<\%(\%(class_\)\=\%(getter\|setter\|property\)[!?]\=\|def_\%(clone\|equals\|equals_and_hash\|hash\)\|delegate\|forward_missing_to\)\s" display
syn match crystalControl "\<\%(abort\|at_exit\|exit\|fork\|loop\)\>[?!]\@!" display
syn keyword crystalException raise
" false positive with 'include?'
syn match crystalInclude "\<include\>[?!]\@!" display
syn keyword crystalInclude extend require
syn keyword crystalKeyword caller typeof pointerof sizeof instance_sizeof offsetof
syn match crystalRecord "\<record\%(\s\+\u\w*\)\@=" display
endif
" Macro
" Note: This definition must be put after crystalNestedCurlyBraces to give higher priority
syn region crystalMacroRegion matchgroup=crystalMacroDelim start="\\\={%" end="%}" display oneline contains=@crystalMacroGroup containedin=ALL
syn region crystalMacroRegion matchgroup=crystalMacroDelim start="\\\={{" end="}}" display contains=TOP containedin=ALL
" Cluster for groups that can appear inside macro expressions
syn cluster crystalMacroGroup contains=@crystalTop
" Cluster for Expensive Mode groups that can't appear inside macro
" regions
syn cluster crystalExpensive contains=
\ crystalMethodBlock,crystalBlock,crystalDoBlock,crystalBlockExpression,crystalRepeatExpression,
\ crystalCaseExpression,crystalSelectExpression,crystalConditionalExpression
syn cluster crystalMacroGroup remove=@crystalExpensive
" Some keywords will have to be redefined for them to be highlighted
" properly
syn keyword crystalMacroKeyword contained
\ if unless else elsif end for in do while until loop begin
syn cluster crystalMacroGroup add=crystalMacroKeyword
" Comments and Documentation
syn match crystalSharpBang "\%^#!.*" display
syn keyword crystalTodo FIXME NOTE TODO OPTIMIZE XXX todo contained
if exists('g:main_syntax') && g:main_syntax ==# 'ecrystal'
" eCrystal tags can contain Crystal comments, so we need to modify the
" pattern for comments so that it does not consume delimiters
syn match crystalComment "#.*\ze\%($\|-\=%>\)" contains=crystalSharpBang,crystalSpaceError,crystalTodo,@Spell
else
syn match crystalComment "#.*" contains=crystalSharpBang,crystalSpaceError,crystalTodo,@Spell
endif
SynFold '#' syn region crystalMultilineComment start="\%(\%(^\s*#.*\n\)\@<!\%(^\s*#.*\n\)\)\%(\(^\s*#.*\n\)\{1,}\)\@=" end="\%(^\s*#.*\n\)\@<=\%(^\s*#.*\n\)\%(^\s*#\)\@!" contains=crystalComment transparent keepend
" Note: this is a hack to prevent 'keywords' being highlighted as such when called as methods with an explicit receiver
syn match crystalKeywordAsMethod "\%(\%(\.\@1<!\.\)\|::\)\_s*\%(alias\|begin\|break\|case\|class\|def\|defined\|do\|else\|select\)\>" transparent contains=NONE
syn match crystalKeywordAsMethod "\%(\%(\.\@1<!\.\)\|::\)\_s*\%(elsif\|end\|ensure\|false\|for\|if\|ifdef\|in\|module\|next\|nil\)\>" transparent contains=NONE
syn match crystalKeywordAsMethod "\%(\%(\.\@1<!\.\)\|::\)\_s*\%(rescue\|return\|self\|super\|previous_def\|then\|true\)\>" transparent contains=NONE
syn match crystalKeywordAsMethod "\%(\%(\.\@1<!\.\)\|::\)\_s*\%(unless\|until\|when\|in\|while\|yield\|with\|__FILE__\|__LINE__\)\>" transparent contains=NONE
syn match crystalKeywordAsMethod "\<\%(alias\|begin\|case\|class\|def\|do\|end\)[?!]" transparent contains=NONE
syn match crystalKeywordAsMethod "\<\%(if\|ifdef\|module\|unless\|until\|while\)[?!]" transparent contains=NONE
syn match crystalKeywordAsMethod "\%(\%(\.\@1<!\.\)\|::\)\_s*\%(abort\|at_exit\|caller\|exit\)\>" transparent contains=NONE
syn match crystalKeywordAsMethod "\%(\%(\.\@1<!\.\)\|::\)\_s*\%(extend\|fork\|include\|asm\)\>" transparent contains=NONE
syn match crystalKeywordAsMethod "\%(\%(\.\@1<!\.\)\|::\)\_s*\%(loop\|private\|protected\)\>" transparent contains=NONE
syn match crystalKeywordAsMethod "\%(\%(\.\@1<!\.\)\|::\)\_s*\%(require\|raise\)\>" transparent contains=NONE
syn match crystalKeywordAsMethod "\%(\%(\.\@1<!\.\)\|::\)\_s*\%(typeof\|pointerof\|sizeof\|instance_sizeof\|offsetof\|\)\>" transparent contains=NONE
hi def link crystalClass crystalDefine
hi def link crystalModule crystalDefine
hi def link crystalStruct crystalDefine
hi def link crystalLib crystalDefine
hi def link crystalEnum crystalDefine
hi def link crystalAnnotation crystalDefine
hi def link crystalMethodExceptional crystalDefine
hi def link crystalDefine Define
hi def link crystalFunction Function
hi def link crystalConditional Conditional
hi def link crystalConditionalModifier crystalConditional
hi def link crystalExceptional crystalConditional
hi def link crystalRepeat Repeat
hi def link crystalControl Statement
hi def link crystalInclude Include
hi def link crystalRecord Statement
hi def link crystalInteger Number
hi def link crystalASCIICode Character
hi def link crystalFloat Float
hi def link crystalBoolean Boolean
hi def link crystalException Exception
if !exists('g:crystal_no_identifiers')
hi def link crystalIdentifier Identifier
else
hi def link crystalIdentifier NONE
endif
hi def link crystalClassVariable crystalIdentifier
hi def link crystalConstant Type
hi def link crystalTypeName crystalConstant
hi def link crystalClassName crystalConstant
hi def link crystalModuleName crystalConstant
hi def link crystalStructName crystalConstant
hi def link crystalLibName crystalConstant
hi def link crystalEnumName crystalConstant
hi def link crystalAnnotationName crystalConstant
hi def link crystalBlockParameter crystalIdentifier
hi def link crystalInstanceVariable crystalIdentifier
hi def link crystalFreshVariable crystalIdentifier
hi def link crystalPredefinedIdentifier crystalIdentifier
hi def link crystalPredefinedConstant crystalPredefinedIdentifier
hi def link crystalPredefinedVariable crystalPredefinedIdentifier
hi def link crystalSymbol Constant
hi def link crystalKeyword Keyword
hi def link crystalOperator Operator
hi def link crystalAccess Statement
hi def link crystalAttribute Statement
hi def link crystalPseudoVariable Constant
hi def link crystalCharLiteral Character
hi def link crystalComment Comment
hi def link crystalTodo Todo
hi def link crystalStringEscape Special
hi def link crystalInterpolationDelim Delimiter
hi def link crystalNoInterpolation crystalString
hi def link crystalSharpBang PreProc
hi def link crystalRegexpDelimiter crystalStringDelimiter
hi def link crystalSymbolDelimiter crystalStringDelimiter
hi def link crystalStringDelimiter Delimiter
hi def link crystalString String
hi def link crystalHeredoc crystalString
hi def link crystalRegexpEscape crystalRegexpSpecial
hi def link crystalRegexpQuantifier crystalRegexpSpecial
hi def link crystalRegexpAnchor crystalRegexpSpecial
hi def link crystalRegexpDot crystalRegexpCharClass
hi def link crystalRegexpCharClass crystalRegexpSpecial
hi def link crystalRegexpSpecial Special
hi def link crystalRegexpComment Comment
hi def link crystalRegexp crystalString
hi def link crystalMacro PreProc
hi def link crystalMacroDelim crystalMacro
hi def link crystalMacroKeyword crystalKeyword
hi def link crystalForallKeyword crystalDefine
hi def link crystalLinkAttrDelim crystalMacroDelim
hi def link crystalError Error
hi def link crystalSpaceError crystalError
hi def link crystalInvalidInteger crystalError
let b:current_syntax = 'crystal'
delc SynFold
" vim: sw=2 sts=2 et: