xref: /vim-8.2.3635/runtime/syntax/ruby.vim (revision c236c16d)
1071d4279SBram Moolenaar" Vim syntax file
2071d4279SBram Moolenaar" Language:		Ruby
3c6249bb2SBram Moolenaar" Maintainer:		Doug Kearns <[email protected]>
46b730e11SBram Moolenaar" Info:			$Id$
5a5792f58SBram Moolenaar" URL:			http://vim-ruby.rubyforge.org
66b730e11SBram Moolenaar" Anon CVS:		See above site
7c6249bb2SBram Moolenaar" Release Coordinator:	Doug Kearns <[email protected]>
86b730e11SBram Moolenaar" ----------------------------------------------------------------------------
96b730e11SBram Moolenaar"
10071d4279SBram Moolenaar" Previous Maintainer:	Mirko Nasato
11071d4279SBram Moolenaar" Thanks to perl.vim authors, and to Reimer Behrends. :-) (MN)
126b730e11SBram Moolenaar" ----------------------------------------------------------------------------
13071d4279SBram Moolenaar
14c1762ccbSBram Moolenaarif exists("b:current_syntax")
15071d4279SBram Moolenaar  finish
16071d4279SBram Moolenaarendif
17071d4279SBram Moolenaar
186b730e11SBram Moolenaarif has("folding") && exists("ruby_fold")
196b730e11SBram Moolenaar  setlocal foldmethod=syntax
206b730e11SBram Moolenaarendif
216b730e11SBram Moolenaar
22*c236c16dSBram Moolenaarsyn cluster rubyNotTop			contains=@rubyExtendedStringSpecial,@rubyRegexpSpecial,@rubyDeclaration,rubyConditional,rubyTodo
23*c236c16dSBram Moolenaar
246b730e11SBram Moolenaarif exists("ruby_space_errors")
256b730e11SBram Moolenaar  if !exists("ruby_no_trail_space_error")
266b730e11SBram Moolenaar    syn match rubySpaceError display excludenl "\s\+$"
276b730e11SBram Moolenaar  endif
286b730e11SBram Moolenaar  if !exists("ruby_no_tab_space_error")
296b730e11SBram Moolenaar    syn match rubySpaceError display " \+\t"me=e-1
306b730e11SBram Moolenaar  endif
316b730e11SBram Moolenaarendif
326b730e11SBram Moolenaar
339964e468SBram Moolenaar" Operators
349964e468SBram Moolenaarif exists("ruby_operators")
35c1762ccbSBram Moolenaar  syn match  rubyOperator	 "\%([~!^&|*/%+-]\|\%(class\s*\)\@<!<<\|<=>\|<=\|\%(<\|\<class\s\+\u\w*\s*\)\@<!<[^<]\@=\|===\|==\|=\~\|>>\|>=\|=\@<!>\|\*\*\|\.\.\.\|\.\.\|::\)"
36c1762ccbSBram Moolenaar  syn match  rubyPseudoOperator  "\%(-=\|/=\|\*\*=\|\*=\|&&=\|&=\|&&\|||=\||=\|||\|%=\|+=\|!\~\|!=\)"
37*c236c16dSBram Moolenaar  syn region rubyBracketOperator matchgroup=rubyOperator start="\%(\w[?!]\=\|[]})]\)\@<=\[\s*" end="\s*]" contains=ALLBUT,@rubyNotTop
389964e468SBram Moolenaarendif
399964e468SBram Moolenaar
40071d4279SBram Moolenaar" Expression Substitution and Backslash Notation
41*c236c16dSBram Moolenaarsyn match rubyStringEscape	"\\\\\|\\[abefnrstv]\|\\\o\{1,3}\|\\x\x\{1,2}"							 contained display
42*c236c16dSBram Moolenaarsyn match rubyStringEscape	"\%(\\M-\\C-\|\\C-\\M-\|\\M-\\c\|\\c\\M-\|\\c\|\\C-\|\\M-\)\%(\\\o\{1,3}\|\\x\x\{1,2}\|\\\=\S\)" contained display
439964e468SBram Moolenaar
44*c236c16dSBram Moolenaarsyn region rubyInterpolation	      matchgroup=rubyInterpolationDelimiter start="#{" end="}" contained contains=ALLBUT,@rubyNotTop
459964e468SBram Moolenaarsyn match  rubyInterpolation	      "#\%(\$\|@@\=\)\w\+"    display contained  contains=rubyInterpolationDelimiter,rubyInstanceVariable,rubyClassVariable,rubyGlobalVariable,rubyPredefinedVariable
469964e468SBram Moolenaarsyn match  rubyInterpolationDelimiter "#\ze\%(\$\|@@\=\)\w\+" display contained
47c1762ccbSBram Moolenaarsyn match  rubyInterpolation	      "#\$\%(-\w\|\W\)"       display contained  contains=rubyInterpolationDelimiter,rubyPredefinedVariable,rubyInvalidVariable
48c1762ccbSBram Moolenaarsyn match  rubyInterpolationDelimiter "#\ze\$\%(-\w\|\W\)"    display contained
499964e468SBram Moolenaarsyn region rubyNoInterpolation	      start="\\#{" end="}"    contained
509964e468SBram Moolenaarsyn match  rubyNoInterpolation	      "\\#{"		      display contained
519964e468SBram Moolenaarsyn match  rubyNoInterpolation	      "\\#\%(\$\|@@\=\)\w\+"  display contained
52c1762ccbSBram Moolenaarsyn match  rubyNoInterpolation	      "\\#\$\W"               display contained
536b730e11SBram Moolenaar
546b730e11SBram Moolenaarsyn match rubyDelimEscape	"\\[(<{\[)>}\]]" transparent display contained contains=NONE
556b730e11SBram Moolenaar
56*c236c16dSBram Moolenaarsyn region rubyNestedParentheses	start="("	skip="\\\\\|\\)"	matchgroup=rubyString end=")"	transparent contained
57*c236c16dSBram Moolenaarsyn region rubyNestedCurlyBraces	start="{"	skip="\\\\\|\\}"	matchgroup=rubyString end="}"	transparent contained
58*c236c16dSBram Moolenaarsyn region rubyNestedAngleBrackets	start="<"	skip="\\\\\|\\>"	matchgroup=rubyString end=">"	transparent contained
59*c236c16dSBram Moolenaarsyn region rubyNestedSquareBrackets	start="\["	skip="\\\\\|\\\]"	matchgroup=rubyString end="\]"	transparent contained
606b730e11SBram Moolenaar
61*c236c16dSBram Moolenaar" These are mostly Oniguruma ready
62*c236c16dSBram Moolenaarsyn region rubyRegexpComment	matchgroup=rubyRegexpSpecial   start="(?#"									skip="\\)"  end=")"  contained
63*c236c16dSBram Moolenaarsyn region rubyRegexpParens	matchgroup=rubyRegexpSpecial   start="(\(?:\|?<\=[=!]\|?>\|?<[a-z_]\w*>\|?[imx]*-[imx]*:\=\|\%(?#\)\@!\)"	skip="\\)"  end=")"  contained transparent contains=@rubyRegexpSpecial
64*c236c16dSBram Moolenaarsyn region rubyRegexpBrackets	matchgroup=rubyRegexpCharClass start="\[\^\="									skip="\\\]" end="\]" contained transparent contains=rubyStringEscape,rubyRegexpEscape,rubyRegexpCharClass oneline
65*c236c16dSBram Moolenaarsyn match  rubyRegexpCharClass	"\\[DdHhSsWw]"		contained display
66*c236c16dSBram Moolenaarsyn match  rubyRegexpCharClass	"\[:\^\=\%(alnum\|alpha\|ascii\|blank\|cntrl\|digit\|graph\|lower\|print\|punct\|space\|upper\|xdigit\):\]"		contained
67*c236c16dSBram Moolenaarsyn match  rubyRegexpEscape	"\\[].*?+^$|\\/(){}[]"	contained display
68*c236c16dSBram Moolenaarsyn match  rubyRegexpQuantifier	"[*?+][?+]\="		contained display
69*c236c16dSBram Moolenaarsyn match  rubyRegexpQuantifier	"{\d\+\%(,\d*\)\=}?\="	contained display
70*c236c16dSBram Moolenaarsyn match  rubyRegexpAnchor	"[$^]\|\\[ABbGZz]"	contained display
71*c236c16dSBram Moolenaarsyn match  rubyRegexpDot	"\."			contained display
72*c236c16dSBram Moolenaarsyn match  rubyRegexpSpecial	"|"			contained display
73*c236c16dSBram Moolenaarsyn match  rubyRegexpSpecial	"\\[1-9]\d\=\d\@!"	contained display
74*c236c16dSBram Moolenaarsyn match  rubyRegexpSpecial	"\\k<\%([a-z_]\w*\|-\=\d\+\)\%([+-]\d\+\)\=>" contained display
75*c236c16dSBram Moolenaarsyn match  rubyRegexpSpecial	"\\k'\%([a-z_]\w*\|-\=\d\+\)\%([+-]\d\+\)\='" contained display
76*c236c16dSBram Moolenaarsyn match  rubyRegexpSpecial	"\\g<\%([a-z_]\w*\|-\=\d\+\)>" contained display
77*c236c16dSBram Moolenaarsyn match  rubyRegexpSpecial	"\\g'\%([a-z_]\w*\|-\=\d\+\)'" contained display
78*c236c16dSBram Moolenaar
79*c236c16dSBram Moolenaarsyn cluster rubyStringSpecial		contains=rubyInterpolation,rubyNoInterpolation,rubyStringEscape
806b730e11SBram Moolenaarsyn cluster rubyExtendedStringSpecial	contains=@rubyStringSpecial,rubyNestedParentheses,rubyNestedCurlyBraces,rubyNestedAngleBrackets,rubyNestedSquareBrackets
81*c236c16dSBram Moolenaarsyn cluster rubyRegexpSpecial		contains=rubyInterpolation,rubyNoInterpolation,rubyStringEscape,rubyRegexpSpecial,rubyRegexpEscape,rubyRegexpBrackets,rubyRegexpCharClass,rubyRegexpDot,rubyRegexpQuantifier,rubyRegexpAnchor,rubyRegexpParens,rubyRegexpComment
82071d4279SBram Moolenaar
83071d4279SBram Moolenaar" Numbers and ASCII Codes
84c1762ccbSBram Moolenaarsyn match rubyASCIICode	"\%(\w\|[]})\"'/]\)\@<!\%(?\%(\\M-\\C-\|\\C-\\M-\|\\M-\\c\|\\c\\M-\|\\c\|\\C-\|\\M-\)\=\%(\\\o\{1,3}\|\\x\x\{1,2}\|\\\=\S\)\)"
856b730e11SBram Moolenaarsyn match rubyInteger	"\<0[xX]\x\+\%(_\x\+\)*\>"								display
866b730e11SBram Moolenaarsyn match rubyInteger	"\<\%(0[dD]\)\=\%(0\|[1-9]\d*\%(_\d\+\)*\)\>"						display
876b730e11SBram Moolenaarsyn match rubyInteger	"\<0[oO]\=\o\+\%(_\o\+\)*\>"								display
886b730e11SBram Moolenaarsyn match rubyInteger	"\<0[bB][01]\+\%(_[01]\+\)*\>"								display
896b730e11SBram Moolenaarsyn match rubyFloat	"\<\%(0\|[1-9]\d*\%(_\d\+\)*\)\.\d\+\%(_\d\+\)*\>"					display
906b730e11SBram Moolenaarsyn match rubyFloat	"\<\%(0\|[1-9]\d*\%(_\d\+\)*\)\%(\.\d\+\%(_\d\+\)*\)\=\%([eE][-+]\=\d\+\%(_\d\+\)*\)\>"	display
91071d4279SBram Moolenaar
926b730e11SBram Moolenaar" Identifiers
936b730e11SBram Moolenaarsyn match rubyLocalVariableOrMethod "\<[_[:lower:]][_[:alnum:]]*[?!=]\=" contains=NONE display transparent
946b730e11SBram Moolenaarsyn match rubyBlockArgument	    "&[_[:lower:]][_[:alnum:]]"		 contains=NONE display transparent
95071d4279SBram Moolenaar
969964e468SBram Moolenaarsyn match  rubyConstant			"\%(\%([.@$]\@<!\.\)\@<!\<\|::\)\_s*\zs\u\w*\%(\>\|::\)\@=\%(\s*(\)\@!"
976b730e11SBram Moolenaarsyn match  rubyClassVariable		"@@\h\w*" display
986b730e11SBram Moolenaarsyn match  rubyInstanceVariable		"@\h\w*"  display
996b730e11SBram Moolenaarsyn match  rubyGlobalVariable		"$\%(\h\w*\|-.\)"
100c1762ccbSBram Moolenaarsyn match  rubySymbol			"[]})\"':]\@<!:\%(\^\|\~\|<<\|<=>\|<=\|<\|===\|==\|=\~\|>>\|>=\|>\||\|-@\|-\|/\|\[]=\|\[]\|\*\*\|\*\|&\|%\|+@\|+\|`\)"
101c1762ccbSBram Moolenaarsyn match  rubySymbol			"[]})\"':]\@<!:\$\%(-.\|[`~<=>_,;:!?/.'"@$*\&+0]\)"
102c1762ccbSBram Moolenaarsyn match  rubySymbol			"[]})\"':]\@<!:\%(\$\|@@\=\)\=\h\w*"
103*c236c16dSBram Moolenaarsyn match  rubySymbol			"[]})\"':]\@<!:\h\w*\%([?!=]>\@!\)\="
104c1762ccbSBram Moolenaarsyn region rubySymbol			start="[]})\"':]\@<!:\"" end="\"" skip="\\\\\|\\\""
105c1762ccbSBram Moolenaarsyn region rubySymbol			start="[]})\"':]\@<!:\"" end="\"" skip="\\\\\|\\\"" contains=@rubyStringSpecial fold
106071d4279SBram Moolenaar
107c1762ccbSBram Moolenaarsyn match  rubyBlockParameter		"\h\w*" contained
108c1762ccbSBram Moolenaarsyn region rubyBlockParameterList	start="\%(\%(\<do\>\|{\)\s*\)\@<=|" end="|" oneline display contains=rubyBlockParameter
109c1762ccbSBram Moolenaar
110*c236c16dSBram Moolenaarsyn match rubyInvalidVariable    "$[^ A-Za-z_-]"
1116b730e11SBram Moolenaarsyn match rubyPredefinedVariable #$[!$&"'*+,./0:;<=>?@\`~1-9]#
1126b730e11SBram Moolenaarsyn match rubyPredefinedVariable "$_\>"											   display
1136b730e11SBram Moolenaarsyn match rubyPredefinedVariable "$-[0FIKadilpvw]\>"									   display
1146b730e11SBram Moolenaarsyn match rubyPredefinedVariable "$\%(deferr\|defout\|stderr\|stdin\|stdout\)\>"					   display
1151e015460SBram Moolenaarsyn match rubyPredefinedVariable "$\%(DEBUG\|FILENAME\|KCODE\|LOADED_FEATURES\|LOAD_PATH\|PROGRAM_NAME\|SAFE\|VERBOSE\)\>" display
1166b730e11SBram Moolenaarsyn match rubyPredefinedConstant "\%(\%(\.\@<!\.\)\@<!\|::\)\_s*\zs\%(MatchingData\|ARGF\|ARGV\|ENV\)\>\%(\s*(\)\@!"
1176b730e11SBram Moolenaarsyn match rubyPredefinedConstant "\%(\%(\.\@<!\.\)\@<!\|::\)\_s*\zs\%(DATA\|FALSE\|NIL\|RUBY_PLATFORM\|RUBY_RELEASE_DATE\)\>\%(\s*(\)\@!"
1186b730e11SBram Moolenaarsyn match rubyPredefinedConstant "\%(\%(\.\@<!\.\)\@<!\|::\)\_s*\zs\%(RUBY_VERSION\|STDERR\|STDIN\|STDOUT\|TOPLEVEL_BINDING\|TRUE\)\>\%(\s*(\)\@!"
119071d4279SBram Moolenaar"Obsolete Global Constants
1206b730e11SBram Moolenaar"syn match rubyPredefinedConstant "\%(::\)\=\zs\%(PLATFORM\|RELEASE_DATE\|VERSION\)\>"
1216b730e11SBram Moolenaar"syn match rubyPredefinedConstant "\%(::\)\=\zs\%(NotImplementError\)\>"
122071d4279SBram Moolenaar
123071d4279SBram Moolenaar" Normal Regular Expression
124*c236c16dSBram Moolenaarsyn region rubyRegexp matchgroup=rubyRegexpDelimiter start="\%(\%(^\|\<\%(and\|or\|while\|until\|unless\|if\|elsif\|when\|not\|then\|else\)\|[;\~=!|&(,[>]\)\s*\)\@<=/" end="/[iomxneus]*" skip="\\\\\|\\/" contains=@rubyRegexpSpecial keepend fold
125*c236c16dSBram Moolenaarsyn region rubyRegexp matchgroup=rubyRegexpDelimiter start="\%(\h\k*\s\+\)\@<=/[ \t=]\@!" end="/[iomxneus]*" skip="\\\\\|\\/" contains=@rubyRegexpSpecial fold
126*c236c16dSBram Moolenaar
127*c236c16dSBram Moolenaar" Generalized Regular Expression
128*c236c16dSBram Moolenaarsyn region rubyRegexp matchgroup=rubyRegexpDelimiter start="%r\z([~`!@#$%^&*_\-+=|\:;"',.?/]\)"	end="\z1[iomxneus]*"	 skip="\\\\\|\\\z1" contains=@rubyRegexpSpecial fold
129*c236c16dSBram Moolenaarsyn region rubyRegexp matchgroup=rubyRegexpDelimiter start="%r{"				end="}[iomxneus]*"	 skip="\\\\\|\\}"   contains=@rubyRegexpSpecial fold
130*c236c16dSBram Moolenaarsyn region rubyRegexp matchgroup=rubyRegexpDelimiter start="%r<"				end=">[iomxneus]*"	 skip="\\\\\|\\>"   contains=@rubyRegexpSpecial,rubyNestedAngleBrackets,rubyDelimEscape fold
131*c236c16dSBram Moolenaarsyn region rubyRegexp matchgroup=rubyRegexpDelimiter start="%r\["				end="\][iomxneus]*"	 skip="\\\\\|\\\]"  contains=@rubyRegexpSpecial fold
132*c236c16dSBram Moolenaarsyn region rubyRegexp matchgroup=rubyRegexpDelimiter start="%r("				end=")[iomxneus]*"	 skip="\\\\\|\\)"   contains=@rubyRegexpSpecial fold
1336b730e11SBram Moolenaar
1346b730e11SBram Moolenaar" Normal String and Shell Command Output
1359964e468SBram Moolenaarsyn region rubyString matchgroup=rubyStringDelimiter start="\"" end="\"" skip="\\\\\|\\\"" contains=@rubyStringSpecial fold
1369964e468SBram Moolenaarsyn region rubyString matchgroup=rubyStringDelimiter start="'"	end="'"  skip="\\\\\|\\'"			       fold
1379964e468SBram Moolenaarsyn region rubyString matchgroup=rubyStringDelimiter start="`"	end="`"  skip="\\\\\|\\`"  contains=@rubyStringSpecial fold
1386b730e11SBram Moolenaar
1396b730e11SBram Moolenaar" Generalized Single Quoted String, Symbol and Array of Strings
140c1762ccbSBram Moolenaarsyn region rubyString matchgroup=rubyStringDelimiter start="%[qw]\z([~`!@#$%^&*_\-+=|\:;"',.?/]\)"  end="\z1" skip="\\\\\|\\\z1" fold
141c1762ccbSBram Moolenaarsyn region rubyString matchgroup=rubyStringDelimiter start="%[qw]{"				    end="}"   skip="\\\\\|\\}"	 fold	contains=rubyNestedCurlyBraces,rubyDelimEscape
142c1762ccbSBram Moolenaarsyn region rubyString matchgroup=rubyStringDelimiter start="%[qw]<"				    end=">"   skip="\\\\\|\\>"	 fold	contains=rubyNestedAngleBrackets,rubyDelimEscape
143c1762ccbSBram Moolenaarsyn region rubyString matchgroup=rubyStringDelimiter start="%[qw]\["				    end="\]"  skip="\\\\\|\\\]"	 fold	contains=rubyNestedSquareBrackets,rubyDelimEscape
144c1762ccbSBram Moolenaarsyn region rubyString matchgroup=rubyStringDelimiter start="%[qw]("				    end=")"   skip="\\\\\|\\)"	 fold	contains=rubyNestedParentheses,rubyDelimEscape
145*c236c16dSBram Moolenaarsyn region rubySymbol matchgroup=rubySymbolDelimiter start="%[s]\z([~`!@#$%^&*_\-+=|\:;"',.?/]\)"   end="\z1" skip="\\\\\|\\\z1" fold
146*c236c16dSBram Moolenaarsyn region rubySymbol matchgroup=rubySymbolDelimiter start="%[s]{"				    end="}"   skip="\\\\\|\\}"	 fold	contains=rubyNestedCurlyBraces,rubyDelimEscape
147*c236c16dSBram Moolenaarsyn region rubySymbol matchgroup=rubySymbolDelimiter start="%[s]<"				    end=">"   skip="\\\\\|\\>"	 fold	contains=rubyNestedAngleBrackets,rubyDelimEscape
148*c236c16dSBram Moolenaarsyn region rubySymbol matchgroup=rubySymbolDelimiter start="%[s]\["				    end="\]"  skip="\\\\\|\\\]"	 fold	contains=rubyNestedSquareBrackets,rubyDelimEscape
149*c236c16dSBram Moolenaarsyn region rubySymbol matchgroup=rubySymbolDelimiter start="%[s]("				    end=")"   skip="\\\\\|\\)"	 fold	contains=rubyNestedParentheses,rubyDelimEscape
1506b730e11SBram Moolenaar
1516b730e11SBram Moolenaar" Generalized Double Quoted String and Array of Strings and Shell Command Output
1526b730e11SBram Moolenaar" Note: %= is not matched here as the beginning of a double quoted string
1536b730e11SBram Moolenaarsyn region rubyString matchgroup=rubyStringDelimiter start="%\z([~`!@#$%^&*_\-+|\:;"',.?/]\)"	    end="\z1" skip="\\\\\|\\\z1" contains=@rubyStringSpecial fold
1546b730e11SBram Moolenaarsyn region rubyString matchgroup=rubyStringDelimiter start="%[QWx]\z([~`!@#$%^&*_\-+=|\:;"',.?/]\)" end="\z1" skip="\\\\\|\\\z1" contains=@rubyStringSpecial fold
1556b730e11SBram Moolenaarsyn region rubyString matchgroup=rubyStringDelimiter start="%[QWx]\={"				    end="}"   skip="\\\\\|\\}"	 contains=@rubyStringSpecial,rubyNestedCurlyBraces,rubyDelimEscape fold
1566b730e11SBram Moolenaarsyn region rubyString matchgroup=rubyStringDelimiter start="%[QWx]\=<"				    end=">"   skip="\\\\\|\\>"	 contains=@rubyStringSpecial,rubyNestedAngleBrackets,rubyDelimEscape fold
1576b730e11SBram Moolenaarsyn region rubyString matchgroup=rubyStringDelimiter start="%[QWx]\=\["				    end="\]"  skip="\\\\\|\\\]"	 contains=@rubyStringSpecial,rubyNestedSquareBrackets,rubyDelimEscape fold
1586b730e11SBram Moolenaarsyn region rubyString matchgroup=rubyStringDelimiter start="%[QWx]\=("				    end=")"   skip="\\\\\|\\)"	 contains=@rubyStringSpecial,rubyNestedParentheses,rubyDelimEscape fold
159071d4279SBram Moolenaar
160071d4279SBram Moolenaar" Here Document
161*c236c16dSBram Moolenaarsyn region rubyHeredocStart matchgroup=rubyStringDelimiter start=+\%(\%(class\s*\|\%([]})"'.]\|::\)\)\_s*\|\w\)\@<!<<-\=\zs\%(\h\w*\)+   end=+$+ oneline contains=ALLBUT,@rubyNotTop
162*c236c16dSBram Moolenaarsyn region rubyHeredocStart matchgroup=rubyStringDelimiter start=+\%(\%(class\s*\|\%([]})"'.]\|::\)\)\_s*\|\w\)\@<!<<-\=\zs"\%([^"]*\)"+ end=+$+ oneline contains=ALLBUT,@rubyNotTop
163*c236c16dSBram Moolenaarsyn region rubyHeredocStart matchgroup=rubyStringDelimiter start=+\%(\%(class\s*\|\%([]})"'.]\|::\)\)\_s*\|\w\)\@<!<<-\=\zs'\%([^']*\)'+ end=+$+ oneline contains=ALLBUT,@rubyNotTop
164*c236c16dSBram Moolenaarsyn region rubyHeredocStart matchgroup=rubyStringDelimiter start=+\%(\%(class\s*\|\%([]})"'.]\|::\)\)\_s*\|\w\)\@<!<<-\=\zs`\%([^`]*\)`+ end=+$+ oneline contains=ALLBUT,@rubyNotTop
165071d4279SBram Moolenaar
166c1762ccbSBram Moolenaarsyn region rubyString start=+\%(\%(class\s*\|\%([]})"'.]\|::\)\)\_s*\|\w\)\@<!<<\z(\h\w*\)\ze+hs=s+2    matchgroup=rubyStringDelimiter end=+^\z1$+ contains=rubyHeredocStart,@rubyStringSpecial fold keepend
167c1762ccbSBram Moolenaarsyn region rubyString start=+\%(\%(class\s*\|\%([]})"'.]\|::\)\)\_s*\|\w\)\@<!<<"\z([^"]*\)"\ze+hs=s+2  matchgroup=rubyStringDelimiter end=+^\z1$+ contains=rubyHeredocStart,@rubyStringSpecial fold keepend
168c1762ccbSBram Moolenaarsyn region rubyString start=+\%(\%(class\s*\|\%([]})"'.]\|::\)\)\_s*\|\w\)\@<!<<'\z([^']*\)'\ze+hs=s+2  matchgroup=rubyStringDelimiter end=+^\z1$+ contains=rubyHeredocStart		      fold keepend
169c1762ccbSBram Moolenaarsyn region rubyString start=+\%(\%(class\s*\|\%([]})"'.]\|::\)\)\_s*\|\w\)\@<!<<`\z([^`]*\)`\ze+hs=s+2  matchgroup=rubyStringDelimiter end=+^\z1$+ contains=rubyHeredocStart,@rubyStringSpecial fold keepend
1706b730e11SBram Moolenaar
171c1762ccbSBram Moolenaarsyn region rubyString start=+\%(\%(class\s*\|\%([]}).]\|::\)\)\_s*\|\w\)\@<!<<-\z(\h\w*\)\ze+hs=s+3    matchgroup=rubyStringDelimiter end=+^\s*\zs\z1$+ contains=rubyHeredocStart,@rubyStringSpecial fold keepend
172c1762ccbSBram Moolenaarsyn region rubyString start=+\%(\%(class\s*\|\%([]}).]\|::\)\)\_s*\|\w\)\@<!<<-"\z([^"]*\)"\ze+hs=s+3  matchgroup=rubyStringDelimiter end=+^\s*\zs\z1$+ contains=rubyHeredocStart,@rubyStringSpecial fold keepend
173c1762ccbSBram Moolenaarsyn region rubyString start=+\%(\%(class\s*\|\%([]}).]\|::\)\)\_s*\|\w\)\@<!<<-'\z([^']*\)'\ze+hs=s+3  matchgroup=rubyStringDelimiter end=+^\s*\zs\z1$+ contains=rubyHeredocStart		     fold keepend
174c1762ccbSBram Moolenaarsyn region rubyString start=+\%(\%(class\s*\|\%([]}).]\|::\)\)\_s*\|\w\)\@<!<<-`\z([^`]*\)`\ze+hs=s+3  matchgroup=rubyStringDelimiter end=+^\s*\zs\z1$+ contains=rubyHeredocStart,@rubyStringSpecial fold keepend
1756b730e11SBram Moolenaar
1766b730e11SBram Moolenaarif exists('main_syntax') && main_syntax == 'eruby'
177d5cdbeb8SBram Moolenaar  let b:ruby_no_expensive = 1
1786b730e11SBram Moolenaarend
179071d4279SBram Moolenaar
1809964e468SBram Moolenaarsyn match  rubyAliasDeclaration    "[^[:space:];#.()]\+"  contained contains=rubySymbol,rubyGlobalVariable,rubyPredefinedVariable nextgroup=rubyAliasDeclaration2 skipwhite
1819964e468SBram Moolenaarsyn match  rubyAliasDeclaration2   "[^[:space:];#.()]\+"  contained contains=rubySymbol,rubyGlobalVariable,rubyPredefinedVariable
1829964e468SBram Moolenaarsyn match  rubyMethodDeclaration   "[^[:space:];#(]\+"	  contained contains=rubyConstant,rubyBoolean,rubyPseudoVariable,rubyInstanceVariable,rubyClassVariable,rubyGlobalVariable
183*c236c16dSBram Moolenaarsyn match  rubyClassDeclaration    "[^[:space:];#<]\+"	  contained contains=rubyConstant,rubyOperator
184*c236c16dSBram Moolenaarsyn match  rubyModuleDeclaration   "[^[:space:];#<]\+"	  contained contains=rubyConstant,rubyOperator
1859964e468SBram Moolenaarsyn match  rubyFunction "\<[_[:alpha:]][_[:alnum:]]*[?!=]\=[[:alnum:].:?!=]\@!" contained containedin=rubyMethodDeclaration
1869964e468SBram Moolenaarsyn match  rubyFunction "\%(\s\|^\)\@<=[_[:alpha:]][_[:alnum:]]*[?!=]\=\%(\s\|$\)\@=" contained containedin=rubyAliasDeclaration,rubyAliasDeclaration2
1879964e468SBram Moolenaarsyn match  rubyFunction "\%([[:space:].]\|^\)\@<=\%(\[\]=\=\|\*\*\|[+-]@\=\|[*/%|&^~]\|<<\|>>\|[<>]=\=\|<=>\|===\|==\|=\~\|`\)\%([[:space:];#(]\|$\)\@=" contained containedin=rubyAliasDeclaration,rubyAliasDeclaration2,rubyMethodDeclaration
188c1762ccbSBram Moolenaar
189*c236c16dSBram Moolenaarsyn cluster rubyDeclaration	contains=rubyAliasDeclaration,rubyAliasDeclaration2,rubyMethodDeclaration,rubyModuleDeclaration,rubyClassDeclaration,rubyFunction,rubyBlockParameter
190*c236c16dSBram Moolenaar
191c1762ccbSBram Moolenaar" Expensive Mode - match 'end' with the appropriate opening keyword for syntax
192c1762ccbSBram Moolenaar" based folding and special highlighting of module/class/method definitions
193d5cdbeb8SBram Moolenaarif !exists("b:ruby_no_expensive") && !exists("ruby_no_expensive")
1949964e468SBram Moolenaar  syn match  rubyDefine "\<alias\>"		nextgroup=rubyAliasDeclaration	skipwhite skipnl
1959964e468SBram Moolenaar  syn match  rubyDefine "\<def\>"		nextgroup=rubyMethodDeclaration skipwhite skipnl
196*c236c16dSBram Moolenaar  syn match  rubyDefine "\<undef\>"		nextgroup=rubyFunction skipwhite skipnl
1979964e468SBram Moolenaar  syn match  rubyClass	"\<class\>"		nextgroup=rubyClassDeclaration	skipwhite skipnl
1989964e468SBram Moolenaar  syn match  rubyModule "\<module\>"		nextgroup=rubyModuleDeclaration skipwhite skipnl
199*c236c16dSBram Moolenaar  syn region rubyBlock start="\<def\>"		matchgroup=rubyDefine end="\%(\<def\_s\+\)\@<!\<end\>" contains=ALLBUT,@rubyNotTop fold
200*c236c16dSBram Moolenaar  syn region rubyBlock start="\<class\>"	matchgroup=rubyClass  end="\<end\>" contains=ALLBUT,@rubyNotTop fold
201*c236c16dSBram Moolenaar  syn region rubyBlock start="\<module\>"	matchgroup=rubyModule end="\<end\>" contains=ALLBUT,@rubyNotTop fold
202071d4279SBram Moolenaar
2036b730e11SBram Moolenaar  " modifiers
204c1762ccbSBram Moolenaar  syn match  rubyConditionalModifier "\<\%(if\|unless\)\>"   display
205c1762ccbSBram Moolenaar  syn match  rubyRepeatModifier	     "\<\%(while\|until\)\>" display
206071d4279SBram Moolenaar
207*c236c16dSBram Moolenaar  syn region rubyDoBlock matchgroup=rubyControl start="\<do\>" end="\<end\>" contains=ALLBUT,@rubyNotTop fold
208c1762ccbSBram Moolenaar  " curly bracket block or hash literal
209*c236c16dSBram Moolenaar  syn region rubyCurlyBlock   start="{" end="}" contains=ALLBUT,@rubyNotTop fold
210*c236c16dSBram Moolenaar  syn region rubyArrayLiteral matchgroup=rubyArrayDelimiter start="\%(\w\|[\]})]\)\@<!\[" end="]" contains=ALLBUT,@rubyNotTop fold
211071d4279SBram Moolenaar
212c1762ccbSBram Moolenaar  " statements without 'do'
213*c236c16dSBram Moolenaar  syn region rubyBlockExpression       matchgroup=rubyControl	  start="\<begin\>" end="\<end\>" contains=ALLBUT,@rubyNotTop fold
214*c236c16dSBram Moolenaar  syn region rubyCaseExpression	       matchgroup=rubyConditional start="\<case\>"  end="\<end\>" contains=ALLBUT,@rubyNotTop fold
215*c236c16dSBram Moolenaar  syn region rubyConditionalExpression matchgroup=rubyConditional start="\%(\%(^\|\.\.\.\=\|[{:,;([<>~\*/%&^|+=-]\|\%(\<[_[:lower:]][_[:alnum:]]*\)\@<![?!]\)\s*\)\@<=\%(if\|unless\)\>" end="\<end\>" contains=ALLBUT,@rubyNotTop fold
216071d4279SBram Moolenaar
217*c236c16dSBram Moolenaar  syn match rubyConditional "\<\%(then\|else\|when\)\>[?!]\@!"  contained containedin=rubyCaseExpression
218*c236c16dSBram Moolenaar  syn match rubyConditional "\<\%(then\|else\|elsif\)\>[?!]\@!" contained containedin=rubyConditionalExpression
219c1762ccbSBram Moolenaar
220c1762ccbSBram Moolenaar  " statements with optional 'do'
221*c236c16dSBram Moolenaar  syn region rubyOptionalDoLine   matchgroup=rubyRepeat start="\<for\>[?!]\@!" start="\%(\%(^\|\.\.\.\=\|[{:,;([<>~\*/%&^|+-]\|\%(\<[_[:lower:]][_[:alnum:]]*\)\@<![!=?]\)\s*\)\@<=\<\%(until\|while\)\>" matchgroup=rubyOptionalDo end="\%(\<do\>\)" end="\ze\%(;\|$\)" oneline contains=ALLBUT,@rubyNotTop
222*c236c16dSBram Moolenaar  syn region rubyRepeatExpression start="\<for\>[?!]\@!" start="\%(\%(^\|\.\.\.\=\|[{:,;([<>~\*/%&^|+-]\|\%(\<[_[:lower:]][_[:alnum:]]*\)\@<![!=?]\)\s*\)\@<=\<\%(until\|while\)\>" matchgroup=rubyRepeat end="\<end\>" contains=ALLBUT,@rubyNotTop nextgroup=rubyOptionalDoLine fold
223071d4279SBram Moolenaar
224071d4279SBram Moolenaar  if !exists("ruby_minlines")
225071d4279SBram Moolenaar    let ruby_minlines = 50
226071d4279SBram Moolenaar  endif
227071d4279SBram Moolenaar  exec "syn sync minlines=" . ruby_minlines
228071d4279SBram Moolenaar
2296b730e11SBram Moolenaarelse
230*c236c16dSBram Moolenaar  syn match   rubyControl "\<def\>[?!]\@!"	nextgroup=rubyMethodDeclaration skipwhite skipnl
231*c236c16dSBram Moolenaar  syn match   rubyControl "\<class\>[?!]\@!"	nextgroup=rubyClassDeclaration	skipwhite skipnl
232*c236c16dSBram Moolenaar  syn match   rubyControl "\<module\>[?!]\@!"	nextgroup=rubyModuleDeclaration skipwhite skipnl
233*c236c16dSBram Moolenaar  syn match   rubyControl "\<\%(case\|begin\|do\|for\|if\|unless\|while\|until\|else\|elsif\|then\|when\|end\)\>[?!]\@!"
234*c236c16dSBram Moolenaar  syn match   rubyKeyword "\<\%(alias\|undef\)\>[?!]\@!"
2356b730e11SBram Moolenaarendif
236071d4279SBram Moolenaar
237071d4279SBram Moolenaar" Keywords
2386b730e11SBram Moolenaar" Note: the following keywords have already been defined:
2396b730e11SBram Moolenaar" begin case class def do end for if module unless until while
240*c236c16dSBram Moolenaarsyn match   rubyControl		"\<\%(and\|break\|ensure\|in\|next\|not\|or\|redo\|rescue\|retry\|return\)\>[?!]\@!"
2416b730e11SBram Moolenaarsyn match   rubyOperator	"\<defined?" display
242*c236c16dSBram Moolenaarsyn match   rubyKeyword		"\<\%(super\|yield\)\>[?!]\@!"
243*c236c16dSBram Moolenaarsyn match   rubyBoolean		"\<\%(true\|false\)\>[?!]\@!"
244*c236c16dSBram Moolenaarsyn match   rubyPseudoVariable	"\<\%(nil\|self\|__FILE__\|__LINE__\)\>[?!]\@!"
245*c236c16dSBram Moolenaarsyn match   rubyBeginEnd	"\<\%(BEGIN\|END\)\>[?!]\@!"
246071d4279SBram Moolenaar
2476b730e11SBram Moolenaar" Special Methods
2486b730e11SBram Moolenaarif !exists("ruby_no_special_methods")
249*c236c16dSBram Moolenaar  syn keyword rubyAccess    public protected private module_function
250*c236c16dSBram Moolenaar  " attr is a common variable name
251*c236c16dSBram Moolenaar  syn match   rubyAttribute "\%(\%(^\|;\)\s*\)\@<=attr\>\(\s*[.=]\)\@!"
252*c236c16dSBram Moolenaar  syn keyword rubyAttribute attr_accessor attr_reader attr_writer
253*c236c16dSBram Moolenaar  syn match   rubyControl   "\<\%(exit!\|\%(abort\|at_exit\|exit\|fork\|loop\|trap\)\>[?!]\@!\)"
2546b730e11SBram Moolenaar  syn keyword rubyEval	    eval class_eval instance_eval module_eval
2556b730e11SBram Moolenaar  syn keyword rubyException raise fail catch throw
256*c236c16dSBram Moolenaar  " false positive with 'include?'
257*c236c16dSBram Moolenaar  syn match   rubyInclude   "\<include\>[?!]\@!"
258*c236c16dSBram Moolenaar  syn keyword rubyInclude   autoload extend load require
2596b730e11SBram Moolenaar  syn keyword rubyKeyword   callcc caller lambda proc
260071d4279SBram Moolenaarendif
261071d4279SBram Moolenaar
2626b730e11SBram Moolenaar" Comments and Documentation
2636b730e11SBram Moolenaarsyn match   rubySharpBang     "\%^#!.*" display
264c1762ccbSBram Moolenaarsyn keyword rubyTodo	      FIXME NOTE TODO OPTIMIZE XXX contained
2656b730e11SBram Moolenaarsyn match   rubyComment       "#.*" contains=rubySharpBang,rubySpaceError,rubyTodo,@Spell
2669964e468SBram Moolenaarif !exists("ruby_no_comment_fold")
2679964e468SBram Moolenaar  syn region rubyMultilineComment start="\%(\%(^\s*#.*\n\)\@<!\%(^\s*#.*\n\)\)\%(\(^\s*#.*\n\)\{1,}\)\@=" end="\%(^\s*#.*\n\)\@<=\%(^\s*#.*\n\)\%(^\s*#\)\@!" contains=rubyComment transparent fold keepend
268c1762ccbSBram Moolenaar  syn region rubyDocumentation	  start="^=begin\ze\%(\s.*\)\=$" end="^=end\s*$" contains=rubySpaceError,rubyTodo,@Spell fold
2699964e468SBram Moolenaarelse
2709964e468SBram Moolenaar  syn region rubyDocumentation	  start="^=begin\s*$" end="^=end\s*$" contains=rubySpaceError,rubyTodo,@Spell
2719964e468SBram Moolenaarendif
2726b730e11SBram Moolenaar
2736b730e11SBram Moolenaar" Note: this is a hack to prevent 'keywords' being highlighted as such when called as methods with an explicit receiver
2746b730e11SBram Moolenaarsyn match rubyKeywordAsMethod "\%(\%(\.\@<!\.\)\|::\)\_s*\%(alias\|and\|begin\|break\|case\|class\|def\|defined\|do\|else\)\>"			transparent contains=NONE
2756b730e11SBram Moolenaarsyn match rubyKeywordAsMethod "\%(\%(\.\@<!\.\)\|::\)\_s*\%(elsif\|end\|ensure\|false\|for\|if\|in\|module\|next\|nil\)\>"			transparent contains=NONE
2766b730e11SBram Moolenaarsyn match rubyKeywordAsMethod "\%(\%(\.\@<!\.\)\|::\)\_s*\%(not\|or\|redo\|rescue\|retry\|return\|self\|super\|then\|true\)\>"			transparent contains=NONE
2776b730e11SBram Moolenaarsyn match rubyKeywordAsMethod "\%(\%(\.\@<!\.\)\|::\)\_s*\%(undef\|unless\|until\|when\|while\|yield\|BEGIN\|END\|__FILE__\|__LINE__\)\>"	transparent contains=NONE
2786b730e11SBram Moolenaar
279*c236c16dSBram Moolenaarsyn match rubyKeywordAsMethod "\<\%(alias\|begin\|case\|class\|def\|do\|end\)[?!]"		transparent contains=NONE
280*c236c16dSBram Moolenaarsyn match rubyKeywordAsMethod "\<\%(if\|module\|undef\|unless\|until\|while\)[?!]"		transparent contains=NONE
281*c236c16dSBram Moolenaar
2826b730e11SBram Moolenaarsyn match rubyKeywordAsMethod "\%(\%(\.\@<!\.\)\|::\)\_s*\%(abort\|at_exit\|attr\|attr_accessor\|attr_reader\)\>"	transparent contains=NONE
2836b730e11SBram Moolenaarsyn match rubyKeywordAsMethod "\%(\%(\.\@<!\.\)\|::\)\_s*\%(attr_writer\|autoload\|callcc\|catch\|caller\)\>"		transparent contains=NONE
2846b730e11SBram Moolenaarsyn match rubyKeywordAsMethod "\%(\%(\.\@<!\.\)\|::\)\_s*\%(eval\|class_eval\|instance_eval\|module_eval\|exit\)\>"	transparent contains=NONE
2856b730e11SBram Moolenaarsyn match rubyKeywordAsMethod "\%(\%(\.\@<!\.\)\|::\)\_s*\%(extend\|fail\|fork\|include\|lambda\)\>"			transparent contains=NONE
2866b730e11SBram Moolenaarsyn match rubyKeywordAsMethod "\%(\%(\.\@<!\.\)\|::\)\_s*\%(load\|loop\|private\|proc\|protected\)\>"			transparent contains=NONE
2876b730e11SBram Moolenaarsyn match rubyKeywordAsMethod "\%(\%(\.\@<!\.\)\|::\)\_s*\%(public\|require\|raise\|throw\|trap\)\>"			transparent contains=NONE
288071d4279SBram Moolenaar
289071d4279SBram Moolenaar" __END__ Directive
2906b730e11SBram Moolenaarsyn region rubyData matchgroup=rubyDataDirective start="^__END__$" end="\%$" fold
291071d4279SBram Moolenaar
292c1762ccbSBram Moolenaarhi def link rubyClass			rubyDefine
293c1762ccbSBram Moolenaarhi def link rubyModule			rubyDefine
294c1762ccbSBram Moolenaarhi def link rubyDefine			Define
295c1762ccbSBram Moolenaarhi def link rubyFunction		Function
296c1762ccbSBram Moolenaarhi def link rubyConditional		Conditional
297c1762ccbSBram Moolenaarhi def link rubyConditionalModifier	rubyConditional
298c1762ccbSBram Moolenaarhi def link rubyRepeat			Repeat
299c1762ccbSBram Moolenaarhi def link rubyRepeatModifier		rubyRepeat
300c1762ccbSBram Moolenaarhi def link rubyOptionalDo		rubyRepeat
301c1762ccbSBram Moolenaarhi def link rubyControl			Statement
302c1762ccbSBram Moolenaarhi def link rubyInclude			Include
303c1762ccbSBram Moolenaarhi def link rubyInteger			Number
304c1762ccbSBram Moolenaarhi def link rubyASCIICode		Character
305c1762ccbSBram Moolenaarhi def link rubyFloat			Float
306c1762ccbSBram Moolenaarhi def link rubyBoolean			Boolean
307c1762ccbSBram Moolenaarhi def link rubyException		Exception
3086b730e11SBram Moolenaarif !exists("ruby_no_identifiers")
309c1762ccbSBram Moolenaar  hi def link rubyIdentifier		Identifier
3106b730e11SBram Moolenaarelse
311c1762ccbSBram Moolenaar  hi def link rubyIdentifier		NONE
3126b730e11SBram Moolenaarendif
313c1762ccbSBram Moolenaarhi def link rubyClassVariable		rubyIdentifier
314c1762ccbSBram Moolenaarhi def link rubyConstant		Type
315c1762ccbSBram Moolenaarhi def link rubyGlobalVariable		rubyIdentifier
316c1762ccbSBram Moolenaarhi def link rubyBlockParameter		rubyIdentifier
317c1762ccbSBram Moolenaarhi def link rubyInstanceVariable	rubyIdentifier
318c1762ccbSBram Moolenaarhi def link rubyPredefinedIdentifier	rubyIdentifier
319c1762ccbSBram Moolenaarhi def link rubyPredefinedConstant	rubyPredefinedIdentifier
320c1762ccbSBram Moolenaarhi def link rubyPredefinedVariable	rubyPredefinedIdentifier
321c1762ccbSBram Moolenaarhi def link rubySymbol			Constant
322c1762ccbSBram Moolenaarhi def link rubyKeyword			Keyword
323c1762ccbSBram Moolenaarhi def link rubyOperator		Operator
324c1762ccbSBram Moolenaarhi def link rubyPseudoOperator		rubyOperator
325c1762ccbSBram Moolenaarhi def link rubyBeginEnd		Statement
326c1762ccbSBram Moolenaarhi def link rubyAccess			Statement
327c1762ccbSBram Moolenaarhi def link rubyAttribute		Statement
328c1762ccbSBram Moolenaarhi def link rubyEval			Statement
329c1762ccbSBram Moolenaarhi def link rubyPseudoVariable		Constant
330071d4279SBram Moolenaar
331c1762ccbSBram Moolenaarhi def link rubyComment			Comment
332c1762ccbSBram Moolenaarhi def link rubyData			Comment
333c1762ccbSBram Moolenaarhi def link rubyDataDirective		Delimiter
334c1762ccbSBram Moolenaarhi def link rubyDocumentation		Comment
335*c236c16dSBram Moolenaarhi def link rubyTodo			Todo
336*c236c16dSBram Moolenaar
337*c236c16dSBram Moolenaarhi def link rubyStringEscape		Special
338c1762ccbSBram Moolenaarhi def link rubyInterpolationDelimiter	Delimiter
339c1762ccbSBram Moolenaarhi def link rubyNoInterpolation		rubyString
340c1762ccbSBram Moolenaarhi def link rubySharpBang		PreProc
341c1762ccbSBram Moolenaarhi def link rubyRegexpDelimiter		rubyStringDelimiter
342*c236c16dSBram Moolenaarhi def link rubySymbolDelimiter		rubyStringDelimiter
343c1762ccbSBram Moolenaarhi def link rubyStringDelimiter		Delimiter
344c1762ccbSBram Moolenaarhi def link rubyString			String
345*c236c16dSBram Moolenaarhi def link rubyRegexpEscape		rubyRegexpSpecial
346*c236c16dSBram Moolenaarhi def link rubyRegexpQuantifier	rubyRegexpSpecial
347*c236c16dSBram Moolenaarhi def link rubyRegexpAnchor		rubyRegexpSpecial
348*c236c16dSBram Moolenaarhi def link rubyRegexpDot		rubyRegexpCharClass
349*c236c16dSBram Moolenaarhi def link rubyRegexpCharClass		rubyRegexpSpecial
350*c236c16dSBram Moolenaarhi def link rubyRegexpSpecial		Special
351*c236c16dSBram Moolenaarhi def link rubyRegexpComment		Comment
352*c236c16dSBram Moolenaarhi def link rubyRegexp			rubyString
3536b730e11SBram Moolenaar
354c1762ccbSBram Moolenaarhi def link rubyInvalidVariable		Error
355c1762ccbSBram Moolenaarhi def link rubyError			Error
356c1762ccbSBram Moolenaarhi def link rubySpaceError		rubyError
357071d4279SBram Moolenaar
358071d4279SBram Moolenaarlet b:current_syntax = "ruby"
359071d4279SBram Moolenaar
360a7241f5fSBram Moolenaar" vim: nowrap sw=2 sts=2 ts=8 noet:
361