summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Stankiewicz <sheerun@sher.pl>2020-07-06 19:13:39 +0200
committerAdam Stankiewicz <sheerun@sher.pl>2020-07-06 19:13:39 +0200
commit8500ae8bb9f4da69273eace4d9cef54ae7f18627 (patch)
tree85acb09cdf450251a775e23a76a42db7003303d0
parentd09a56a494863afd789cba1850e123dfc1dd26cf (diff)
downloadvim-polyglot-8500ae8bb9f4da69273eace4d9cef54ae7f18627.tar.gz
vim-polyglot-8500ae8bb9f4da69273eace4d9cef54ae7f18627.zip
Update
-rw-r--r--autoload/crystal/indent.vim967
-rw-r--r--autoload/crystal_lang.vim6
-rw-r--r--autoload/dart.vim14
-rw-r--r--autoload/vital/_crystal/ColorEcho.vim5
-rw-r--r--autoload/vital/_crystal/Data/List.vim6
-rw-r--r--autoload/vital/_crystal/Data/String.vim5
-rw-r--r--autoload/vital/_crystal/Process.vim6
-rw-r--r--autoload/vital/_crystal/Web/JSON.vim5
-rw-r--r--ftplugin/crystal.vim55
-rw-r--r--ftplugin/eruby.vim2
-rw-r--r--indent/crystal.vim279
-rw-r--r--indent/ecrystal.vim3
-rw-r--r--indent/plantuml.vim2
-rw-r--r--syntax/basic/symbols.vim10
-rw-r--r--syntax/basic/type.vim5
-rw-r--r--syntax/common.vim1
-rw-r--r--syntax/crystal.vim96
-rw-r--r--syntax/dhall.vim2
-rw-r--r--syntax/plantuml.vim8
-rw-r--r--syntax/vifm.vim50
20 files changed, 998 insertions, 529 deletions
diff --git a/autoload/crystal/indent.vim b/autoload/crystal/indent.vim
index d5a02de9..96d32990 100644
--- a/autoload/crystal/indent.vim
+++ b/autoload/crystal/indent.vim
@@ -3,162 +3,853 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'crystal') == -1
" Variables {{{1
" =========
-" Regex of syntax group names that are strings or characters.
+" Syntax group names that are strings.
let g:crystal#indent#syng_string =
- \ '\<crystal\%(String\|Interpolation\|NoInterpolation\|StringEscape\|CharLiteral\|ASCIICode\)\>'
+ \ '\<crystal\%(String\|Interpolation\|NoInterpolation\|StringEscape\)\>'
lockvar g:crystal#indent#syng_string
-" Regex of syntax group names that are strings, characters, symbols,
-" regexps, or comments.
+" Syntax group names that are strings/symbols/regexes or comments.
let g:crystal#indent#syng_strcom =
- \ g:crystal#indent#syng_string.'\|' .
- \ '\<crystal\%(Regexp\|RegexpEscape\|Symbol\|Comment\)\>'
+ \ g:crystal#indent#syng_string .
+ \ '\|' .
+ \ '\<crystal\%(CharLiteral\|Comment\|Regexp\|RegexpCharClass\|RegexpEscape\|Symbol\|ASCIICode\)\>'
lockvar g:crystal#indent#syng_strcom
+" Syntax group names that are string/regex/symbol delimiters.
+let g:crystal#indent#syng_delim =
+ \ '\<crystal\%(StringDelimiter\|RegexpDelimiter\|SymbolDelimiter\|InterpolationDelim\)\>'
+lockvar g:crystal#indent#syng_delim
+
+" Syntax group that represents all of the above combined.
+let g:crystal#indent#syng_strcomdelim =
+ \ g:crystal#indent#syng_strcom .
+ \ '\|' .
+ \ g:crystal#indent#syng_delim
+lockvar g:crystal#indent#syng_strcomdelim
+
+" Regex for the start of a line
+let g:crystal#indent#sol = '\%(\_^\|;\)\s*\zs'
+lockvar g:crystal#indent#sol
+
+" Regex for the end of a line
+let g:crystal#indent#eol = '\ze\s*\%(#.*\)\=\%(\_$\|;\)'
+lockvar g:crystal#indent#eol
+
" Expression used to check whether we should skip a match with searchpair().
let g:crystal#indent#skip_expr =
- \ 'synIDattr(synID(line("."), col("."), 1), "name") =~# "'.g:crystal#indent#syng_strcom.'"'
+ \ 'crystal#indent#IsInStringOrComment(line("."), col("."))'
lockvar g:crystal#indent#skip_expr
-" Regex for the start of a line:
-" start of line + whitespace + optional opening macro delimiter
-let g:crystal#indent#sol = '^\s*\zs\%(\\\={%\s*\)\='
-lockvar g:crystal#indent#sol
+" Regex that defines a link attribute
+let g:crystal#indent#link_attribute_regex =
+ \ g:crystal#indent#sol.'@\[.*]'
+lockvar g:crystal#indent#link_attribute_regex
-" Regex for the end of a line:
-" whitespace + optional closing macro delimiter + whitespace +
-" optional comment + end of line
-let g:crystal#indent#eol = '\s*\%(%}\)\=\ze\s*\%(#.*\)\=$'
-lockvar g:crystal#indent#eol
+" Regex that defines a type declaration
+let g:crystal#indent#type_declaration_regex =
+ \ g:crystal#indent#sol .
+ \ '\%(\<\%(private\|protected\)\s\+\)\=' .
+ \ '\%(\<\%(getter\|setter\|property\)?\=\s\+\)\=' .
+ \ '@\=\h\k*\s\+:\s\+\S.*'
+lockvar g:crystal#indent#type_declaration_regex
+
+" Regex for operator symbols:
+" , : / + * - = ~ < & ^ \
+" | that is not part of a block opening
+" % that is not part of a macro delimiter
+" ! that is not part of a method name
+" ? that is not part of a method name
+" > that is not part of a ->
+"
+" Additionally, all symbols must not be part of a global variable name,
+" like $~.
+let g:crystal#indent#operator_regex =
+ \ '\$\@1<!' .
+ \ '\%(' .
+ \ '[.,:/+*\-=~<&^\\]' .
+ \ '\|' .
+ \ '\%(\%(\<do\>\|%\@1<!{\)\s*|[^|]*\)\@<!|' .
+ \ '\|' .
+ \ '{\@1<!%' .
+ \ '\|' .
+ \ '\%(\k\|]\)\@1<!\!' .
+ \ '\|' .
+ \ '\%(\k\|]\)\@1<!?' .
+ \ '\|' .
+ \ '-\@1<!>' .
+ \ '\)'
+lockvar g:crystal#indent#operator_regex
" Regex that defines blocks.
let g:crystal#indent#block_regex =
- \ '\%(\<do\>\|%\@1<!{\)\s*\%(|[^|]*|\)\='.g:crystal#indent#eol
+ \ '\%(' .
+ \ '\%('.g:crystal#indent#operator_regex.'\s*\)\@<!{\@1<!{' .
+ \ '\|' .
+ \ '\<do\>' .
+ \ '\)' .
+ \ '\s*\%(|[^|]*|\)\=' .
+ \ g:crystal#indent#eol
lockvar g:crystal#indent#block_regex
+" Regex that defines the beginning of a hanging expression.
+let g:crystal#indent#hanging_assignment_regex =
+ \ '\%('.g:crystal#indent#operator_regex.'\s*\)\@<=' .
+ \ '\.\@1<!\<\%(if\||unless\|case\|begin\)\>'
+lockvar g:crystal#indent#hanging_assignment_regex
+
" Regex that defines the start-match for the 'end' keyword.
-" NOTE: This *should* properly match the 'do' only at the end of the
-" line
let g:crystal#indent#end_start_regex =
+ \ '\%(' .
\ g:crystal#indent#sol .
\ '\%(' .
\ '\%(\<\%(private\|protected\)\s\+\)\=' .
- \ '\%(\<\%(abstract\s\+\)\=\%(class\|struct\)\>\|\<\%(def\|module\|macro\|lib\|enum\)\>\)' .
+ \ '\%(\<\%(abstract\s\+\)\=\%(class\|struct\)\>\|\<\%(def\|module\|macro\|lib\|enum\|annotation\)\>\)' .
\ '\|' .
- \ '\<\%(if\|unless\|while\|until\|case\|begin\|for\|union\)\>' .
+ \ '\<\%(if\|unless\|while\|until\|case\|begin\|union\)\>' .
\ '\)' .
\ '\|' .
- \ g:crystal#indent#block_regex
+ \ g:crystal#indent#hanging_assignment_regex .
+ \ '\|' .
+ \ g:crystal#indent#block_regex .
+ \ '\)'
lockvar g:crystal#indent#end_start_regex
" Regex that defines the middle-match for the 'end' keyword.
let g:crystal#indent#end_middle_regex =
\ g:crystal#indent#sol .
- \ '\<\%(else\|elsif\|rescue\|ensure\|when\)\>'
+ \ '\<\%(else\|elsif\|when\|rescue\|ensure\)\>'
lockvar g:crystal#indent#end_middle_regex
" Regex that defines the end-match for the 'end' keyword.
let g:crystal#indent#end_end_regex =
- \ g:crystal#indent#sol .
- \ '\<end\>'
+ \ g:crystal#indent#sol.'\%(\<end\>\|%\@1<!}\@1<!}}\@!\)'
lockvar g:crystal#indent#end_end_regex
-" Regex used for words that add a level of indent.
+" Regex used for words that, at the start of a line, add a level of indent.
let g:crystal#indent#crystal_indent_keywords =
\ g:crystal#indent#end_start_regex .
\ '\|' .
\ g:crystal#indent#end_middle_regex
lockvar g:crystal#indent#crystal_indent_keywords
-" Regex used for words that remove a level of indent.
+" Regex used for words that, at the start of a line, remove a level of indent.
let g:crystal#indent#crystal_deindent_keywords =
\ g:crystal#indent#end_middle_regex .
\ '\|' .
\ g:crystal#indent#end_end_regex
lockvar g:crystal#indent#crystal_deindent_keywords
-" Regex that defines a type declaration
-let g:crystal#indent#crystal_type_declaration =
- \ '@\=\h\k*\s\+:\s\+\S.*'
-lockvar g:crystal#indent#crystal_type_declaration
+" Regex that defines hanging expressions for macro control tags.
+let g:crystal#indent#macro_hanging_assignment_regex =
+ \ '\%('.g:crystal#indent#operator_regex.'\s*\)\@<=' .
+ \ '\\\=\zs{%\s*\%(if\|unless\|begin\)\>.*%}'
+lockvar g:crystal#indent#macro_hanging_assignment_regex
-" Regex that defines continuation lines, not including (, {, or [.
-let g:crystal#indent#non_bracket_continuation_regex =
+" Regex that defines the start-match for the 'end' keyword in macro
+" control tags.
+let g:crystal#indent#macro_end_start_regex =
\ '\%(' .
- \ '[\\.,:/%+\-=~<>&^]' .
+ \ g:crystal#indent#sol .
+ \ '\%(' .
+ \ '\\\=\zs{%\s*\%(if\|unless\|for\|begin\)\>.*%}' .
\ '\|' .
- \ '\%(\%(\<do\>\|%\@1<!{\)\s*|[^|]*\)\@<!|' .
+ \ '\\\=\zs{%.*\<do\s*%}' .
+ \ '\)' .
\ '\|' .
- \ '\%(]\|\w\)\@1<!?' .
+ \ g:crystal#indent#macro_hanging_assignment_regex .
+ \ '\)'
+lockvar g:crystal#indent#macro_end_start_regex
+
+" Regex that defines the middle-match for the 'end' keyword in macro
+" control tags.
+let g:crystal#indent#macro_end_middle_regex =
+ \ g:crystal#indent#sol.'\\\=\zs{%\s*\%(else\|elsif\)\>.*%}'
+lockvar g:crystal#indent#macro_end_middle_regex
+
+" Regex that defines the end-match for the 'end' keyword in macro
+" control tags.
+let g:crystal#indent#macro_end_end_regex =
+ \ g:crystal#indent#sol.'\\\=\zs{%\s*end\s*%}'
+lockvar g:crystal#indent#macro_end_end_regex
+
+" Regex used for words that, at the start of a line, add a level of
+" indent after macro control tags.
+let g:crystal#indent#crystal_macro_indent_keywords =
+ \ g:crystal#indent#macro_end_start_regex .
\ '\|' .
- \ '\<\%(if\|unless\)\>' .
+ \ g:crystal#indent#macro_end_middle_regex
+lockvar g:crystal#indent#crystal_macro_indent_keywords
+
+" Regex used for words that, at the start of a line, remove a level of
+" indent after macro control tags.
+let g:crystal#indent#crystal_macro_deindent_keywords =
+ \ g:crystal#indent#macro_end_middle_regex .
\ '\|' .
- \ '\%('.g:crystal#indent#crystal_type_declaration.'\h\k*\)\@<!\*' .
- \ '\)' .
- \ g:crystal#indent#eol
-lockvar g:crystal#indent#non_bracket_continuation_regex
+ \ g:crystal#indent#macro_end_end_regex
+lockvar g:crystal#indent#crystal_macro_deindent_keywords
" Regex that defines bracket continuations
-let g:crystal#indent#bracket_continuation_regex = '%\@1<!\%([({[]\)\s*\%(#.*\)\=$'
+let g:crystal#indent#bracket_continuation_regex =
+ \ '%\@1<![({[]'.g:crystal#indent#eol
lockvar g:crystal#indent#bracket_continuation_regex
+" Regex that defines continuation lines, not including (, {, or [.
+let g:crystal#indent#non_bracket_continuation_regex =
+ \ '\%(' .
+ \ g:crystal#indent#operator_regex .
+ \ '\|' .
+ \ '\<\%(if\|unless\|then\)\>' .
+ \ '\)' .
+ \ g:crystal#indent#eol
+lockvar g:crystal#indent#non_bracket_continuation_regex
+
" Regex that defines continuation lines.
let g:crystal#indent#continuation_regex =
- \ g:crystal#indent#non_bracket_continuation_regex .
+ \ g:crystal#indent#bracket_continuation_regex .
\ '\|' .
- \ g:crystal#indent#bracket_continuation_regex
+ \ g:crystal#indent#non_bracket_continuation_regex
lockvar g:crystal#indent#continuation_regex
+" Regex that defines dot continuations
+let g:crystal#indent#dot_continuation_regex = '\.'.g:crystal#indent#eol
+lockvar g:crystal#indent#dot_continuation_regex
+
" Regex that defines end of bracket continuation followed by another continuation
let g:crystal#indent#bracket_switch_continuation_regex =
- \ '^\([^(]\+\zs).\+\)\+'.g:crystal#indent#continuation_regex
+ \ '^\%([^(]\+\zs).\+\)\+\%('.g:crystal#indent#continuation_regex.'\)'
lockvar g:crystal#indent#bracket_switch_continuation_regex
-" Regex that defines continuable keywords
-let g:crystal#indent#continuable_regex =
- \ '\%(^\s*\|[=,*/%+\-|;{]\|<<\|>>\|:\s\)\s*\zs' .
- \ '\<\%(if\|for\|while\|until\|unless\):\@!\>'
-lockvar g:crystal#indent#continuable_regex
-
-" Regex that defines the first part of a splat pattern
-let g:crystal#indent#splat_regex = '[[,(]\s*\*\s*\%(#.*\)\=$'
-lockvar g:crystal#indent#splat_regex
-
-let g:crystal#indent#block_continuation_regex = '^\s*[^])}\t ].*'.g:crystal#indent#block_regex
+let g:crystal#indent#block_continuation_regex =
+ \ '^\s*[^])}\t ].*'.g:crystal#indent#block_regex
lockvar g:crystal#indent#block_continuation_regex
" Regex that describes a leading operator (only a method call's dot for now)
-let g:crystal#indent#leading_operator_regex = '^\s*[.]'
+let g:crystal#indent#leading_operator_regex = g:crystal#indent#sol.'\.'
lockvar g:crystal#indent#leading_operator_regex
+" Indent callbacks for the current line
+let g:crystal#indent#curr_line_callbacks = [
+ \ 'crystal#indent#MultilineString',
+ \ 'crystal#indent#ClosingBracketOnEmptyLine',
+ \ 'crystal#indent#DeindentingMacroTag',
+ \ 'crystal#indent#DeindentingKeyword',
+ \ 'crystal#indent#LeadingOperator'
+ \ ]
+lockvar g:crystal#indent#curr_line_callbacks
+
+" Indent callbacks for the previous line
+let g:crystal#indent#prev_line_callbacks = [
+ \ 'crystal#indent#StartOfFile',
+ \ 'crystal#indent#AfterTypeDeclaration',
+ \ 'crystal#indent#AfterLinkAttribute',
+ \ 'crystal#indent#ContinuedLine',
+ \ 'crystal#indent#AfterBlockOpening',
+ \ 'crystal#indent#AfterUnbalancedBracket',
+ \ 'crystal#indent#AfterLeadingOperator',
+ \ 'crystal#indent#AfterEndMacroTag',
+ \ 'crystal#indent#AfterEndKeyword',
+ \ 'crystal#indent#AfterIndentMacroTag',
+ \ 'crystal#indent#AfterIndentKeyword'
+ \ ]
+lockvar g:crystal#indent#prev_line_callbacks
+
+" Indent callbacks for the MSL
+let g:crystal#indent#msl_callbacks = [
+ \ 'crystal#indent#PreviousNotMSL',
+ \ 'crystal#indent#IndentingKeywordInMSL',
+ \ 'crystal#indent#ContinuedHangingOperator'
+ \ ]
+lockvar g:crystal#indent#msl_callbacks
+
+" Indenting Logic Callbacks {{{1
+" =========================
+
+function! crystal#indent#ClosingBracketOnEmptyLine(cline_info) abort
+ let info = a:cline_info
+
+ " If we got a closing bracket on an empty line, find its match and indent
+ " according to it. For parentheses we indent to its column - 1, for the
+ " others we indent to the containing line's MSL's level. Return -1 if fail.
+
+ let idx = match(info.cline, g:crystal#indent#sol.'[]})]')
+
+ if idx >= 0
+ let closing_bracket = info.cline[idx]
+
+ if closing_bracket ==# ')'
+ let opening_bracket = '('
+ elseif closing_bracket ==# ']'
+ let opening_bracket = '\['
+ elseif closing_bracket ==# '}'
+ let opening_bracket = '{'
+ endif
+
+ call searchpair(
+ \ opening_bracket,
+ \ '',
+ \ closing_bracket,
+ \ 'bW',
+ \ g:crystal#indent#skip_expr)
+
+ if line('.') == info.clnum
+ return indent('.')
+ endif
+
+ if g:crystal_indent_block_style ==# 'do' &&
+ \ getline('.') =~# g:crystal#indent#block_regex
+ return col('.') - 1
+ else
+ return indent(crystal#indent#GetMSL(line('.')))
+ endif
+ endif
+
+ return -1
+endfunction
+
+function! crystal#indent#DeindentingKeyword(cline_info) abort
+ let info = a:cline_info
+
+ " If we have a deindenting keyword, find its match and indent to its level.
+ let idx = match(info.cline, g:crystal#indent#crystal_deindent_keywords)
+
+ if idx >= 0
+ call cursor(0, idx + 1)
+
+ call searchpair(
+ \ g:crystal#indent#end_start_regex,
+ \ g:crystal#indent#end_middle_regex,
+ \ g:crystal#indent#end_end_regex,
+ \ 'bW',
+ \ g:crystal#indent#skip_expr)
+
+ let lnum = line('.')
+
+ " If the search did not change the current line, then either 1) the
+ " code is malformed or 2) the indenting keyword is on the same line
+ " as this one: in either case, do nothing and exit the indent
+ " expression.
+ if lnum == info.clnum
+ return indent('.')
+ endif
+
+ " Count the number of both opening and closing macro control tags
+ " between this line and the starting line: if the number of
+ " opening tags is greater than the number of closing tags, then we
+ " must be inside of a macro block, so indent accordingly.
+ let diff = crystal#indent#RelativeMacroDepth(lnum, info.clnum)
+
+ if diff > 0
+ return indent(lnum) + info.sw * (diff + 1)
+ elseif diff < 0
+ return indent(lnum) + info.sw * (diff - 1)
+ endif
+
+ " If none of the above special cases apply, proceed normally.
+ let line = getline(lnum)
+
+ if g:crystal_indent_block_style ==# 'do' &&
+ \ line =~# g:crystal#indent#block_regex
+ return col('.') - 1
+ elseif g:crystal_indent_assignment_style ==# 'hanging' &&
+ \ line =~# g:crystal#indent#hanging_assignment_regex
+ return col('.') - 1
+ else
+ return indent(crystal#indent#GetMSL(lnum))
+ endif
+ endif
+
+ return -1
+endfunction
+
+function! crystal#indent#DeindentingMacroTag(cline_info) abort
+ let info = a:cline_info
+
+ " If we have a deindenting tag, find its match and indent to its level.
+ let idx = match(info.cline, g:crystal#indent#crystal_macro_deindent_keywords)
+
+ if idx >= 0
+ call cursor(0, idx + 1)
+
+ call searchpair(
+ \ g:crystal#indent#macro_end_start_regex,
+ \ g:crystal#indent#macro_end_middle_regex,
+ \ g:crystal#indent#macro_end_end_regex,
+ \ 'bW',
+ \ g:crystal#indent#skip_expr)
+
+ " If this tag was preceded by a \, we need to keep searching until
+ " we find a tag that also has a \.
+ if info.cline[idx - 1] ==# '\'
+ while getline('.')[col('.') - 2] !=# '\'
+ call searchpair(
+ \ g:crystal#indent#macro_end_start_regex,
+ \ g:crystal#indent#macro_end_middle_regex,
+ \ g:crystal#indent#macro_end_end_regex,
+ \ 'bW',
+ \ g:crystal#indent#skip_expr)
+ endwhile
+
+ " Position the cursor on the \ for later
+ call cursor(0, col('.') - 1)
+ endif
+
+ " If the search did not change the current line, then either 1) the
+ " code is malformed or 2) the indenting tag is on the same line as
+ " this one: in either case, do nothing and exit the indent
+ " expression.
+ if line('.') == info.clnum
+ return indent('.')
+ endif
+
+ if g:crystal_indent_assignment_style ==# 'hanging' &&
+ \ getline('.') =~# g:crystal#indent#macro_hanging_assignment_regex
+ return col('.') - 1
+ else
+ return indent('.')
+ endif
+ endif
+
+ return -1
+endfunction
+
+function! crystal#indent#MultilineString(cline_info) abort
+ let info = a:cline_info
+
+ " If we are in a multi-line string, don't do anything to it.
+ if crystal#indent#IsInString(info.clnum, 1)
+ return indent('.')
+ endif
+
+ return -1
+endfunction
+
+function! crystal#indent#LeadingOperator(cline_info) abort
+ let info = a:cline_info
+
+ " If the current line starts with a leading operator, add a level of indent.
+ if info.cline =~# g:crystal#indent#leading_operator_regex
+ return indent(crystal#indent#GetMSL(info.clnum)) + info.sw
+ endif
+
+ return -1
+endfunction
+
+function! crystal#indent#EmptyInsideString(pline_info) abort
+ let info = a:pline_info
+
+ " If the line is empty and inside a string (the previous line is a string,
+ " too), use the previous line's indent
+
+ let plnum = prevnonblank(info.clnum - 1)
+ let pline = getline(plnum)
+
+ if info.cline =~# '^\s*$'
+ \ && crystal#indent#IsInString(plnum, 1)
+ \ && crystal#indent#IsInString(plnum, strlen(pline))
+ return indent(plnum)
+ endif
+
+ return -1
+endfunction
+
+function! crystal#indent#StartOfFile(pline_info) abort
+ let info = a:pline_info
+
+ " At the start of the file use zero indent.
+ if info.plnum == 0
+ return 0
+ endif
+
+ return -1
+endfunction
+
+function! crystal#indent#AfterTypeDeclaration(pline_info) abort
+ let info = a:pline_info
+
+ " Short circuit if the previous line was a type declaration; this
+ " allows us to skip checking for type declarations before * and
+ " ? later on, which will save a lot of time.
+
+ if info.pline =~# g:crystal#indent#type_declaration_regex
+ if info.pline =~# ','.g:crystal#indent#eol
+ return indent(info.plnum)
+ else
+ let idx = match(info.pline, g:crystal#indent#block_regex)
+
+ if idx >= 0
+ if g:crystal_indent_block_style ==# 'do'
+ return idx + info.sw
+ else
+ return indent(info.plnum)
+ endif
+ endif
+
+ return indent(crystal#indent#GetMSL(info.plnum))
+ endif
+ endif
+
+ return -1
+endfunction
+
+function! crystal#indent#AfterLinkAttribute(pline_info) abort
+ let info = a:pline_info
+
+ " Short circuit if the previous line was a link attribute.
+
+ if info.pline =~# g:crystal#indent#link_attribute_regex
+ return indent(info.plnum)
+ endif
+
+ return -1
+endfunction
+
+" Example:
+"
+" if foo || bar ||
+" baz || bing
+" puts "foo"
+" end
+"
+function! crystal#indent#ContinuedLine(pline_info) abort
+ let info = a:pline_info
+
+ let idx = match(info.pline, g:crystal#indent#end_start_regex)
+
+ if idx >= 0 && info.pline =~# g:crystal#indent#non_bracket_continuation_regex
+ if info.pline =~# g:crystal#indent#hanging_assignment_regex
+ if g:crystal_indent_assignment_style ==# 'hanging'
+ " hanging indent
+ let ind = idx
+ else
+ " align with variable
+ let ind = indent(info.plnum)
+ endif
+ else
+ let ind = indent(crystal#indent#GetMSL(info.plnum))
+ endif
+
+ return ind + info.sw * 2
+ endif
+
+ return -1
+endfunction
+
+function! crystal#indent#AfterBlockOpening(pline_info) abort
+ let info = a:pline_info
+
+ " If the previous line ended with a block opening, add a level of indent.
+ let idx = match(info.pline, g:crystal#indent#block_regex)
+
+ if idx >= 0
+ if g:crystal_indent_block_style ==# 'do'
+ " don't align to the msl, align to the "do"
+ let ind = idx + info.sw
+ else
+ let plnum_msl = crystal#indent#GetMSL(info.plnum)
+
+ if getline(plnum_msl) =~# '='.g:crystal#indent#eol
+ " in the case of assignment to the msl, align to the starting line,
+ " not to the msl
+ let ind = indent(info.plnum) + info.sw
+ else
+ let ind = indent(plnum_msl) + info.sw
+ endif
+ endif
+
+ return ind
+ endif
+
+ return -1
+endfunction
+
+function! crystal#indent#AfterLeadingOperator(pline_info) abort
+ let info = a:pline_info
+
+ " If the previous line started with a leading operator, use its MSL's level
+ " of indent
+ if info.pline =~# g:crystal#indent#leading_operator_regex
+ return indent(crystal#indent#GetMSL(info.plnum))
+ endif
+
+ return -1
+endfunction
+
+function! crystal#indent#AfterUnbalancedBracket(pline_info) abort
+ let info = a:pline_info
+
+ " If the previous line contained unclosed opening brackets and we are still
+ " in them, find the rightmost one and add indent depending on the bracket
+ " type.
+ "
+ " If it contained hanging closing brackets, find the rightmost one, find its
+ " match and indent according to that.
+
+ if info.pline =~# '[[({]\|[])}]'.g:crystal#indent#eol
+ let [opening, closing] = crystal#indent#ExtraBrackets(info.plnum)
+
+ if opening.pos != -1
+ if strpart(info.pline, opening.pos + 1) =~# '^'.g:crystal#indent#eol
+ return indent(crystal#indent#GetMSL(info.plnum)) + info.sw
+ else
+ return opening.pos + 1
+ endif
+ elseif closing.pos != -1
+ call cursor(info.plnum, closing.pos + 1)
+
+ if closing.type ==# ')'
+ let target = '('
+ elseif closing.type ==# ']'
+ let target = '\['
+ elseif closing.type ==# '}'
+ let target = '{'
+ endif
+
+ call searchpair(target, '', closing.type, 'bW', g:crystal#indent#skip_expr)
+
+ return indent(crystal#indent#GetMSL(line('.')))
+ end
+ endif
+
+ return -1
+endfunction
+
+function! crystal#indent#AfterEndKeyword(pline_info) abort
+ let info = a:pline_info
+
+ let idx = match(info.pline, g:crystal#indent#end_end_regex)
+
+ if idx >= 0
+ if g:crystal_indent_assignment_style ==# 'variable' &&
+ \ g:crystal_indent_block_style ==# 'expression'
+ " Simply align with the "end"
+ return idx
+ endif
+
+ " Return the indent of the nearest indenting line
+ call cursor(info.plnum, idx + 1)
+
+ let lnum = searchpair(
+ \ g:crystal#indent#end_start_regex,
+ \ '',
+ \ g:crystal#indent#end_end_regex,
+ \ 'bW',
+ \ g:crystal#indent#skip_expr)
+
+ return indent(crystal#indent#GetMSL(lnum))
+ endif
+
+ return -1
+endfunction
+
+function! crystal#indent#AfterEndMacroTag(pline_info) abort
+ let info = a:pline_info
+
+ " If the previous line ended with an "end" macro tag, match the indent
+ " of that tag's corresponding opening tag.
+ let idx = match(info.pline, g:crystal#indent#macro_end_end_regex)
+
+ if idx >= 0
+ call cursor(info.plnum, idx + 1)
+
+ if g:crystal_indent_assignment_style ==# 'hanging'
+ let lnum = searchpair(
+ \ g:crystal#indent#macro_end_start_regex,
+ \ '',
+ \ g:crystal#indent#macro_end_end_regex,
+ \ 'bW',
+ \ g:crystal#indent#skip_expr)
+ else
+ let lnum = searchpair(
+ \ g:crystal#indent#macro_end_start_regex,
+ \ g:crystal#indent#macro_end_middle_regex,
+ \ g:crystal#indent#macro_end_end_regex,
+ \ 'bW',
+ \ g:crystal#indent#skip_expr)
+ endif
+
+ return indent(lnum)
+ end
+
+ return -1
+endfunction
+
+function! crystal#indent#AfterIndentKeyword(pline_info) abort
+ let info = a:pline_info
+
+ let idx = match(info.pline, g:crystal#indent#crystal_indent_keywords)
+
+ if idx >= 0
+ " If there is an "end" after the indenting keyword on the same line,
+ " do nothing.
+ let idx2 = match(info.pline, g:crystal#indent#end_end_regex)
+
+ if idx2 > idx
+ return indent('.')
+ endif
+
+ if g:crystal_indent_assignment_style ==# 'hanging' &&
+ \ info.pline =~# g:crystal#indent#hanging_assignment_regex
+ return idx + info.sw
+ else
+ return indent(info.plnum) + info.sw
+ endif
+ endif
+
+ return -1
+endfunction
+
+function! crystal#indent#AfterIndentMacroTag(pline_info) abort
+ let info = a:pline_info
+
+ let idx = match(info.pline, g:crystal#indent#crystal_macro_indent_keywords)
+
+ if idx >= 0
+ if g:crystal_indent_assignment_style ==# 'hanging' &&
+ \ info.pline =~# g:crystal#indent#macro_hanging_assignment_regex
+ " If the indenting tag was preceded by a \, we must shift over an
+ " additional space.
+ let shift = info.pline[idx - 1] ==# '\'
+ return idx + info.sw - shift
+ else
+ return indent(info.plnum) + info.sw
+ endif
+ endif
+
+ return -1
+endfunction
+
+function! crystal#indent#PreviousNotMSL(msl_info) abort
+ let info = a:msl_info
+
+ if info.plnum != info.plnum_msl
+ if info.pline =~# g:crystal#indent#bracket_switch_continuation_regex
+ return indent(info.plnum) - 1
+ elseif info.pline =~# g:crystal#indent#non_bracket_continuation_regex
+ return indent(info.plnum)
+ endif
+ endif
+
+ return -1
+endfunction
+
+function! crystal#indent#IndentingKeywordInMSL(msl_info) abort
+ let info = a:msl_info
+
+ " If the MSL line had an indenting keyword in it, add a level of indent.
+ let idx = match(info.pline_msl, g:crystal#indent#crystal_indent_keywords)
+
+ if idx >= 0
+ let ind = indent(info.plnum_msl) + info.sw
+
+ if info.pline_msl =~# g:crystal#indent#end_end_regex
+ let ind = ind - info.sw
+ elseif info.pline =~# g:crystal#indent#hanging_assignment_regex
+ if g:crystal_indent_assignment_style ==# 'hanging'
+ " hanging indent
+ let ind = idx + info.sw
+ else
+ " align with variable
+ let ind = indent(info.plnum_msl) + info.sw
+ endif
+ endif
+
+ return ind
+ endif
+
+ return -1
+endfunction
+
+function! crystal#indent#ContinuedHangingOperator(msl_info) abort
+ let info = a:msl_info
+
+ " If the previous line ended with an operator but wasn't a block
+ " ending or a closing bracket, indent one extra level.
+ if crystal#indent#Match(info.plnum_msl, g:crystal#indent#non_bracket_continuation_regex) &&
+ \ info.pline_msl !~# g:crystal#indent#sol.'\%([\])}]\|\<end\>\)'
+ if info.plnum_msl == info.plnum
+ let ind = indent(info.plnum_msl) + info.sw
+ else
+ let ind = indent(info.plnum_msl)
+ endif
+
+ return ind
+ endif
+
+ return -1
+endfunction
+
" Auxiliary Functions {{{1
" ===================
-" Check if the character at lnum:col is inside a string, comment, or is ascii.
+" Check if the character at lnum:col is inside a string.
+function! crystal#indent#IsInString(lnum, col) abort
+ return synIDattr(synID(a:lnum, a:col, 1), 'name') =~# g:crystal#indent#syng_string
+endfunction
+
+" Check if the character at lnum:col is inside a string delimiter.
+function! crystal#indent#IsInStringDelimiter(lnum, col) abort
+ return synIDattr(synID(a:lnum, a:col, 1), 'name') =~# g:crystal#indent#syng_delim
+endfunction
+
+" Check if the character at lnum:col is inside a string, comment, regexp, etc.
function! crystal#indent#IsInStringOrComment(lnum, col) abort
return synIDattr(synID(a:lnum, a:col, 1), 'name') =~# g:crystal#indent#syng_strcom
endfunction
-" Check if the character at lnum:col is inside a string or character.
-function! crystal#indent#IsInString(lnum, col) abort
- return synIDattr(synID(a:lnum, a:col, 1), 'name') =~# g:crystal#indent#syng_string
+" Check if the character lnum:col is inside a string, comment, regexp,
+" delimiter, etc.
+function! crystal#indent#IsInStringOrCommentOrDelimiter(lnum, col) abort
+ return synIDattr(synID(a:lnum, a:col, 1), 'name') =~# g:crystal#indent#syng_strcomdelim
endfunction
-" Check if the character at lnum:col is inside a string or regexp
-" delimiter
-function! crystal#indent#IsInStringDelimiter(lnum, col) abort
- return synIDattr(synID(a:lnum, a:col, 1), 'name') =~# '\<crystal\%(StringDelimiter\|RegexpDelimiter\)\>'
+function! crystal#indent#IsAssignment(str, pos) abort
+ return strpart(a:str, 0, a:pos - 1) =~# '=\s*$'
+endfunction
+
+function! crystal#indent#IsLineComment(lnum) abort
+ return getline(a:lnum) =~# g:crystal#indent#sol.'#'
+endfunction
+
+" Determine the relative macro block depth of one line versus another.
+" 'a' and 'b' are the line numbers for said lines.
+"
+" For example:
+"
+" A return value of 2 would indicate that line A is inside two macro
+" blocks relative to line B.
+"
+" A return value of -2 would indicate that line B is inside two macro
+" blocks relative to line A.
+"
+" A return value of 0 would indicate that line A and line B are either
+" in the same macro block or at the same relative macro block depth.
+"
+" NOTE: It is assumed that a < b - 2; otherwise, the return value will
+" always be 0.
+function! crystal#indent#RelativeMacroDepth(a, b) abort
+ let diff = 0
+
+ for i in range(a:a + 1, a:b - 1)
+ if crystal#indent#Match(i, g:crystal#indent#macro_end_start_regex)
+ let diff += 1
+ elseif crystal#indent#Match(i, g:crystal#indent#macro_end_end_regex)
+ let diff -= 1
+ endif
+ endfor
+
+ return diff
endfunction
-" Find line above 'lnum' that isn't empty, in a comment, or in a string.
-function! crystal#indent#PrevNonBlankNonString(lnum) abort
+" Wrapper for prevnonblank() that skips lines that are line comments or
+" inside of multiline strings.
+function! crystal#indent#PrevNonBlank(lnum) abort
let lnum = prevnonblank(a:lnum)
while lnum > 0
let line = getline(lnum)
- let start = match(line, '\S')
+ let start = match(line, '\S') + 1
- if !crystal#indent#IsInStringOrComment(lnum, start + 1)
+ if !crystal#indent#IsInStringOrComment(lnum, start)
break
endif
@@ -171,95 +862,104 @@ endfunction
" Find line above 'lnum' that started the continuation 'lnum' may be part of.
function! crystal#indent#GetMSL(lnum) abort
" Start on the line we're at and use its indent.
- let msl = a:lnum
- let msl_body = getline(msl)
- let lnum = crystal#indent#PrevNonBlankNonString(a:lnum - 1)
+ let mslnum = a:lnum
+ let lnum = crystal#indent#PrevNonBlank(a:lnum - 1)
while lnum > 0
" If we have a continuation line, or we're in a string, use line as MSL.
" Otherwise, terminate search as we have found our MSL already.
+ let msl = getline(mslnum)
let line = getline(lnum)
- if crystal#indent#Match(msl, g:crystal#indent#leading_operator_regex)
+ if msl =~# g:crystal#indent#leading_operator_regex
" If the current line starts with a leading operator, keep its indent
" and keep looking for an MSL.
- let msl = lnum
- elseif crystal#indent#Match(lnum, g:crystal#indent#splat_regex)
- " If the above line looks like the "*" of a splat, use the current one's
- " indentation.
+ let mslnum = lnum
+ elseif line =~# g:crystal#indent#type_declaration_regex &&
+ \ line !~# ','.g:crystal#indent#eol &&
+ \ line !~# g:crystal#indent#block_regex
+ " If the previous line is a type declaration that doesn't end with
+ " a comman or a block opening, it is the MSL.
"
" Example:
- " Hash[*
- " method_call do
- " something
+ " record ColorRGB,
+ " red : UInt8,
+ " green : UInt8,
+ " blue : UInt8 do
+ " def fore(io : IO) : Nil
+ " io << "38;2;"
+ " io << red << ";"
+ " io << green << ";"
+ " io << blue
+ " end
+ " end
"
- return msl
- elseif crystal#indent#Match(lnum, g:crystal#indent#non_bracket_continuation_regex) &&
- \ crystal#indent#Match(msl, g:crystal#indent#non_bracket_continuation_regex)
+ return mslnum
+ elseif line =~# g:crystal#indent#non_bracket_continuation_regex &&
+ \ msl =~# g:crystal#indent#non_bracket_continuation_regex
" If the current line is a non-bracket continuation and so is the
- " previous one, keep its indent and continue looking for an MSL.
+ " previous one, keep its indent and continue looking for an mslnum.
"
" Example:
" method_call one,
" two,
" three
"
- let msl = lnum
- elseif crystal#indent#Match(lnum, g:crystal#indent#non_bracket_continuation_regex) &&
+ let mslnum = lnum
+ elseif line =~# g:crystal#indent#non_bracket_continuation_regex &&
\ (
- \ crystal#indent#Match(msl, g:crystal#indent#bracket_continuation_regex) ||
- \ crystal#indent#Match(msl, g:crystal#indent#block_continuation_regex)
+ \ msl =~# g:crystal#indent#bracket_continuation_regex ||
+ \ msl =~# g:crystal#indent#block_continuation_regex
\ )
" If the current line is a bracket continuation or a block-starter, but
- " the previous is a non-bracket one, respect the previous' indentation,
- " and stop here.
+ " the previous is a non-bracket one, keep looking for an mslnum.
"
" Example:
" method_call one,
" two {
" three
"
- return lnum
- elseif crystal#indent#Match(lnum, g:crystal#indent#bracket_continuation_regex) &&
+ " method_call one,
+ " two,
+ " three {
+ " four
+ "
+ let mslnum = lnum
+ elseif line =~# g:crystal#indent#bracket_continuation_regex &&
\ (
- \ crystal#indent#Match(msl, g:crystal#indent#bracket_continuation_regex) ||
- \ crystal#indent#Match(msl, g:crystal#indent#block_continuation_regex)
+ \ msl =~# g:crystal#indent#bracket_continuation_regex ||
+ \ msl =~# g:crystal#indent#block_continuation_regex
\ )
" If both lines are bracket continuations (the current may also be a
- " block-starter), use the current one's and stop here
+ " block-starter), use the current one's and stop here.
"
" Example:
" method_call(
" other_method_call(
" foo
- return msl
- elseif crystal#indent#Match(lnum, g:crystal#indent#block_regex) &&
- \ !crystal#indent#Match(msl, g:crystal#indent#continuation_regex) &&
- \ !crystal#indent#Match(msl, g:crystal#indent#block_continuation_regex)
+ "
+ return mslnum
+ elseif line =~# g:crystal#indent#block_regex &&
+ \ msl !~# g:crystal#indent#continuation_regex
" If the previous line is a block-starter and the current one is
- " mostly ordinary, use the current one as the MSL.
+ " mostly ordinary, use the current one as the mslnum.
"
" Example:
" method_call do
" something
" something_else
- return msl
+ "
+ return mslnum
+ elseif line =~# g:crystal#indent#continuation_regex
+ let mslnum = lnum
else
- let col = match(line, g:crystal#indent#continuation_regex) + 1
-
- if (col > 0 && !crystal#indent#IsInStringOrComment(lnum, col))
- \ || crystal#indent#IsInString(lnum, strlen(line))
- let msl = lnum
- else
- break
- endif
+ break
endif
- let msl_body = getline(msl)
- let lnum = crystal#indent#PrevNonBlankNonString(lnum - 1)
+ let lnum = crystal#indent#PrevNonBlank(lnum - 1)
endwhile
- return msl
+ return mslnum
endfunction
" Check if line 'lnum' has more opening brackets than closing ones.
@@ -268,7 +968,7 @@ function! crystal#indent#ExtraBrackets(lnum) abort
let closing = {'parentheses': [], 'braces': [], 'brackets': []}
let line = getline(a:lnum)
- let pos = match(line, '[][(){}]', 0)
+ let pos = match(line, '[][(){}]')
" Save any encountered opening brackets, and remove them once a matching
" closing one has been found. If a closing bracket shows up that doesn't
@@ -326,42 +1026,19 @@ function! crystal#indent#ExtraBrackets(lnum) abort
endfunction
function! crystal#indent#Match(lnum, regex) abort
- let regex = '\C'.a:regex
-
- let line = getline(a:lnum)
- let col = match(line, regex) + 1
-
- while col &&
- \ crystal#indent#IsInStringOrComment(a:lnum, col) ||
- \ crystal#indent#IsInStringDelimiter(a:lnum, col)
- let col = match(line, regex, col) + 1
- endwhile
-
- return col
-endfunction
+ let line = getline(a:lnum)
+ let offset = match(line, '\C'.a:regex)
+ let col = offset + 1
-" Locates the containing class/module/struct/enum/lib's definition line,
-" ignoring nested classes along the way.
-function! crystal#indent#FindContainingClass() abort
- let saved_position = getcurpos()
-
- while searchpair(
- \ g:crystal#indent#end_start_regex,
- \ g:crystal#indent#end_middle_regex,
- \ g:crystal#indent#end_end_regex,
- \ 'bWz',
- \ g:crystal#indent#skip_expr) > 0
- if expand('<cword>') =~# '\<\%(class\|module\|struct\|enum\|lib\)\>'
- let found_lnum = line('.')
- call setpos('.', saved_position)
- return found_lnum
- endif
+ while col && crystal#indent#IsInStringOrCommentOrDelimiter(a:lnum, col)
+ let offset = match(line, '\C'.a:regex, offset + 1)
+ let col = offset + 1
endwhile
- call setpos('.', saved_position)
- return 0
+ return col ? col : 0
endfunction
-" vim: sw=2 sts=2 et:
+" }}}1
+" vim:sw=2 sts=2 ts=8 fdm=marker et:
endif
diff --git a/autoload/crystal_lang.vim b/autoload/crystal_lang.vim
index a697a943..b0e63ea2 100644
--- a/autoload/crystal_lang.vim
+++ b/autoload/crystal_lang.vim
@@ -1,8 +1,5 @@
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'crystal') == -1
-let s:save_cpo = &cpo
-set cpo&vim
-
let s:V = vital#crystal#new()
let s:P = s:V.import('Process')
let s:C = s:V.import('ColorEcho')
@@ -365,9 +362,6 @@ function! crystal_lang#expand(file, pos, ...) abort
return crystal_lang#tool('expand', a:file, a:pos, get(a:, 1, ''))
endfunction
-let &cpo = s:save_cpo
-unlet s:save_cpo
-
" vim: sw=2 sts=2 et:
endif
diff --git a/autoload/dart.vim b/autoload/dart.vim
index 367e54e4..52d76c02 100644
--- a/autoload/dart.vim
+++ b/autoload/dart.vim
@@ -27,12 +27,16 @@ function! s:clearQfList(reason) abort
endif
endfunction
-function! dart#fmt(q_args) abort
- let cmd = s:FindDartFmt()
- if type(cmd) != type('') | return | endif
+function! dart#fmt(...) abort
+ let l:dartfmt = s:FindDartFmt()
+ if type(l:dartfmt) != type('') | return | endif
let buffer_content = getline(1, '$')
- let args = '--stdin-name '.expand('%').' '.a:q_args
- let lines = systemlist(printf('%s %s', cmd, args), join(buffer_content, "\n"))
+ let l:cmd = [l:dartfmt, '--stdin-name', shellescape(expand('%'))]
+ if exists('g:dartfmt_options')
+ call extend(l:cmd, g:dartfmt_options)
+ endif
+ call extend(l:cmd, a:000)
+ let lines = systemlist(join(l:cmd), join(buffer_content, "\n"))
" TODO(https://github.com/dart-lang/sdk/issues/38507) - Remove once the
" tool no longer emits this line on SDK upgrades.
if lines[-1] ==# 'Isolate creation failed'
diff --git a/autoload/vital/_crystal/ColorEcho.vim b/autoload/vital/_crystal/ColorEcho.vim
index af9b4374..f93c5215 100644
--- a/autoload/vital/_crystal/ColorEcho.vim
+++ b/autoload/vital/_crystal/ColorEcho.vim
@@ -10,8 +10,6 @@ execute join(['function! vital#_crystal#ColorEcho#import() abort', printf("retur
delfunction s:_SID
" ___vital___
scriptencoding utf-8
-let s:save_cpo = &cpo
-set cpo&vim
function! s:_is_available() abort
if has('gui_running')
@@ -185,7 +183,4 @@ function! s:echo(str) abort
call echorizer.echo()
endfunction
-let &cpo = s:save_cpo
-unlet s:save_cpo
-
endif
diff --git a/autoload/vital/_crystal/Data/List.vim b/autoload/vital/_crystal/Data/List.vim
index c84e1ffa..18a7a947 100644
--- a/autoload/vital/_crystal/Data/List.vim
+++ b/autoload/vital/_crystal/Data/List.vim
@@ -11,9 +11,6 @@ delfunction s:_SID
" ___vital___
" Utilities for list.
-let s:save_cpo = &cpo
-set cpo&vim
-
function! s:pop(list) abort
return remove(a:list, -1)
endfunction
@@ -460,9 +457,6 @@ function! s:combinations(list, r) abort
return result
endfunction
-let &cpo = s:save_cpo
-unlet s:save_cpo
-
" vim:set et ts=2 sts=2 sw=2 tw=0:
endif
diff --git a/autoload/vital/_crystal/Data/String.vim b/autoload/vital/_crystal/Data/String.vim
index fe37c6a5..d5124081 100644
--- a/autoload/vital/_crystal/Data/String.vim
+++ b/autoload/vital/_crystal/Data/String.vim
@@ -11,9 +11,6 @@ delfunction s:_SID
" ___vital___
" Utilities for string.
-let s:save_cpo = &cpo
-set cpo&vim
-
function! s:_vital_loaded(V) abort
let s:V = a:V
let s:L = s:V.import('Data.List')
@@ -624,8 +621,6 @@ function! s:split_posix_text(text, ...) abort
return split(text, newline, 1)
endfunction
-let &cpo = s:save_cpo
-unlet s:save_cpo
" vim:set et ts=2 sts=2 sw=2 tw=0:
endif
diff --git a/autoload/vital/_crystal/Process.vim b/autoload/vital/_crystal/Process.vim
index 9a159932..ecbfc0d4 100644
--- a/autoload/vital/_crystal/Process.vim
+++ b/autoload/vital/_crystal/Process.vim
@@ -15,9 +15,6 @@ delfunction s:_SID
" FIXME: This module name should be Vital.System ?
" But the name has been already taken.
-let s:save_cpo = &cpo
-set cpo&vim
-
" FIXME: Unfortunately, can't use s:_vital_loaded() for this purpose.
" Because these variables are used when this script file is loaded.
@@ -169,9 +166,6 @@ else
endif
-let &cpo = s:save_cpo
-unlet s:save_cpo
-
" vim:set et ts=2 sts=2 sw=2 tw=0:
endif
diff --git a/autoload/vital/_crystal/Web/JSON.vim b/autoload/vital/_crystal/Web/JSON.vim
index e9567fef..c6892b4e 100644
--- a/autoload/vital/_crystal/Web/JSON.vim
+++ b/autoload/vital/_crystal/Web/JSON.vim
@@ -9,8 +9,6 @@ endfunction
execute join(['function! vital#_crystal#Web#JSON#import() abort', printf("return map({'decode': '', '_vital_depends': '', '_vital_created': '', 'encode': '', '_vital_loaded': ''}, \"vital#_crystal#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
-let s:save_cpo = &cpo
-set cpo&vim
function! s:_true() abort
return 1
@@ -174,9 +172,6 @@ function! s:_encode_dict(val, settings) abort
endfunction
" @vimlint(EVL102, 0, l:ns)
-let &cpo = s:save_cpo
-unlet s:save_cpo
-
" vim:set et ts=2 sts=2 sw=2 tw=0:
endif
diff --git a/ftplugin/crystal.vim b/ftplugin/crystal.vim
index 1a2b5970..f5b7e3a9 100644
--- a/ftplugin/crystal.vim
+++ b/ftplugin/crystal.vim
@@ -5,34 +5,6 @@ if exists('b:did_ftplugin')
endif
let b:did_ftplugin = 1
-" This file is loaded on 'ecrystal' filetype
-if &filetype !=# 'crystal'
- finish
-endif
-
-let s:save_cpo = &cpo
-set cpo&vim
-
-if exists('loaded_matchit') && !exists('b:match_words')
- let b:match_ignorecase = 0
-
- let b:match_words =
- \ '\<\%(if\|unless\|case\|while\|until\|for\|do\|class\|module\|struct\|lib\|macro\|ifdef\|def\|fun\|begin\|enum\)\>=\@!' .
- \ ':' .
- \ '\<\%(else\|elsif\|ensure\|when\|rescue\|break\|redo\|next\|retry\)\>' .
- \ ':' .
- \ '\<end\>' .
- \ ',{:},\[:\],(:)'
-
- let b:match_skip =
- \ "synIDattr(synID(line('.'),col('.'),0),'name') =~ '" .
- \ "\\<crystal\\%(String\\|StringDelimiter\\|ASCIICode\\|Escape\\|" .
- \ "Interpolation\\|NoInterpolation\\|Comment\\|Documentation\\|" .
- \ "ConditionalModifier\\|RepeatModifier\\|OptionalDo\\|" .
- \ "Function\\|BlockArgument\\|KeywordAsMethod\\|ClassVariable\\|" .
- \ "InstanceVariable\\|GlobalVariable\\|Symbol\\)\\>'"
-endif
-
setlocal comments=:#
setlocal commentstring=#\ %s
setlocal suffixesadd=.cr
@@ -81,14 +53,33 @@ if &l:ofu ==# ''
setlocal omnifunc=crystal_lang#complete
endif
-if exists('AutoPairsLoaded')
+" Options for vim-matchit
+if exists('g:loaded_matchit') && !exists('b:match_words')
+ let b:match_ignorecase = 0
+
+ let b:match_words =
+ \ '\<\%(if\|unless\|case\|while\|until\|for\|do\|class\|module\|struct\|lib\|macro\|ifdef\|def\|begin\|enum\|annotation\)\>=\@!' .
+ \ ':' .
+ \ '\<\%(else\|elsif\|ensure\|when\|rescue\|break\|next\)\>' .
+ \ ':' .
+ \ '\<end\>' .
+ \ ',{:},\[:\],(:)'
+
+ let b:match_skip =
+ \ 'synIDattr(synID(line("."), col("."), 0), "name") =~# ''' .
+ \ '\<crystal\%(String\|StringDelimiter\|ASCIICode\|Escape\|' .
+ \ 'Interpolation\|NoInterpolation\|Comment\|Documentation\|' .
+ \ 'ConditionalModifier\|' .
+ \ 'Function\|BlockArgument\|KeywordAsMethod\|ClassVariable\|' .
+ \ 'InstanceVariable\|GlobalVariable\|Symbol\)\>'''
+endif
+
+" Options for jiangmiao/auto-pairs
+if exists('g:AutoPairsLoaded')
let b:AutoPairs = { '{%': '%}' }
call extend(b:AutoPairs, g:AutoPairs, 'force')
endif
-let &cpo = s:save_cpo
-unlet s:save_cpo
-
" vim: sw=2 sts=2 et:
endif
diff --git a/ftplugin/eruby.vim b/ftplugin/eruby.vim
index 2add9e90..342283b0 100644
--- a/ftplugin/eruby.vim
+++ b/ftplugin/eruby.vim
@@ -119,7 +119,7 @@ endif
" TODO: comments=
setlocal commentstring=<%#%s%>
-let b:undo_ftplugin = "setl cms< "
+let b:undo_ftplugin = "setl cms< " .
\ " | unlet! b:browsefilter b:match_words | " . s:undo_ftplugin
let &cpo = s:save_cpo
diff --git a/indent/crystal.vim b/indent/crystal.vim
index 96cdd586..c69b2a28 100644
--- a/indent/crystal.vim
+++ b/indent/crystal.vim
@@ -1,21 +1,21 @@
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'crystal') == -1
+" Initialization {{{1
+" ==============
+
" Only load this indent file when no other was loaded.
if exists('b:did_indent')
finish
endif
+
let b:did_indent = 1
setlocal nosmartindent
" Now, set up our indentation expression and keys that trigger it.
setlocal indentexpr=GetCrystalIndent(v:lnum)
-setlocal indentkeys=0{,0},0),0],!^F,o,O,e,:,.
+setlocal indentkeys=0{,0},0),0],!^F,o,O,e,.
setlocal indentkeys+==end,=else,=elsif,=when,=ensure,=rescue
-setlocal indentkeys+==private,=protected
-
-let s:cpo_save = &cpo
-set cpo&vim
" Only define the function once.
if exists('*GetCrystalIndent')
@@ -26,7 +26,7 @@ endif
if exists('*shiftwidth')
let s:sw = function('shiftwidth')
else
- function s:sw()
+ function! s:sw()
return &shiftwidth
endfunction
endif
@@ -34,262 +34,81 @@ endif
" GetCrystalIndent Function {{{1
" =========================
-function GetCrystalIndent(...)
+function! GetCrystalIndent(...) abort
" Setup {{{2
" -----
+ let indent_info = {}
+
+ " The value of a single shift-width
+ let indent_info.sw = s:sw()
+
" For the current line, use the first argument if given, else v:lnum
- let clnum = a:0 ? a:1 : v:lnum
+ let indent_info.clnum = a:0 ? a:1 : v:lnum
+ let indent_info.cline = getline(indent_info.clnum)
- " Set up variables for restoring position in file
- let vcol = col('.')
+ " Set up variables for restoring position in file.
+ let indent_info.col = col('.')
" Work on the current line {{{2
" ------------------------
- " Get the current line.
- let line = getline(clnum)
- let ind = -1
+ for callback_name in g:crystal#indent#curr_line_callbacks
+ let indent = call(function(callback_name), [indent_info])
- " If we got a closing bracket on an empty line, find its match and indent
- " according to it. For parentheses we indent to its column - 1, for the
- " others we indent to the containing line's MSL's level. Return -1 if fail.
- let col = matchend(line, '^\s*[]})]')
- if col > 0 && !crystal#indent#IsInStringOrComment(clnum, col)
- call cursor(clnum, col)
- let bs = strpart('(){}[]', stridx(')}]', line[col - 1]) * 2, 2)
- if searchpair(escape(bs[0], '\['), '', bs[1], 'bW', g:crystal#indent#skip_expr)
- if line[col-1] ==# ')' && col('.') != col('$') - 1
- let ind = virtcol('.') - 1
- else
- let ind = indent(crystal#indent#GetMSL(line('.')))
- endif
+ if indent >= 0
+ return indent
endif
- return ind
- endif
-
- " If we have a deindenting keyword, find its match and indent to its level.
- " TODO: this is messy
- if crystal#indent#Match(clnum, g:crystal#indent#crystal_deindent_keywords)
- call cursor(clnum, 1)
- if searchpair(
- \ g:crystal#indent#end_start_regex,
- \ g:crystal#indent#end_middle_regex,
- \ g:crystal#indent#end_end_regex,
- \ 'bW', g:crystal#indent#skip_expr)
- let msl = crystal#indent#GetMSL(line('.'))
- let line = getline(line('.'))
-
- if strpart(line, 0, col('.') - 1) =~# '=\s*$' &&
- \ strpart(line, col('.') - 1, 2) !~# 'do'
- " assignment to case/begin/etc, on the same line, hanging indent
- let ind = virtcol('.') - 1
- elseif getline(msl) =~# '=\s*\(#.*\)\=$'
- " in the case of assignment to the msl, align to the starting line,
- " not to the msl
- let ind = indent(line('.'))
- else
- " align to the msl
- let ind = indent(msl)
- endif
- endif
- return ind
- endif
-
- " If we are in a multi-line string, don't do anything to it.
- if crystal#indent#IsInString(clnum, matchend(line, '^\s*') + 1)
- return indent('.')
- endif
-
- " If we are at the closing delimiter of a "<<" heredoc-style string, set the
- " indent to 0.
- if line =~# '^\k\+\s*$'
- \ && crystal#indent#IsInStringDelimiter(clnum, 1)
- \ && search('\V<<'.line, 'nbW')
- return 0
- endif
-
- " If the current line starts with a leading operator, add a level of indent.
- if crystal#indent#Match(clnum, g:crystal#indent#leading_operator_regex)
- return indent(crystal#indent#GetMSL(clnum)) + s:sw()
- endif
+ endfor
" Work on the previous line. {{{2
" --------------------------
- " Find a non-blank, non-multi-line string line above the current line.
- let lnum = crystal#indent#PrevNonBlankNonString(clnum - 1)
-
- " If the line is empty and inside a string, use the previous line.
- if line =~# '^\s*$' && lnum != prevnonblank(clnum - 1)
- return indent(prevnonblank(clnum))
- endif
-
- " At the start of the file use zero indent.
- if lnum == 0
- return 0
- endif
-
- " Set up variables for the previous line.
- let line = getline(lnum)
- let ind = indent(lnum)
+ " Special case: we don't need the real PrevNonBlank for an empty line
+ " inside a string. And that call can be quite expensive in that
+ " particular situation.
+ let indent = crystal#indent#EmptyInsideString(indent_info)
- if crystal#indent#Match(lnum, g:crystal#indent#continuable_regex) &&
- \ crystal#indent#Match(lnum, g:crystal#indent#continuation_regex)
- return indent(crystal#indent#GetMSL(lnum)) + s:sw() * 2
+ if indent >= 0
+ return indent
endif
- " If the previous line ended with a block opening, add a level of indent.
- if crystal#indent#Match(lnum, g:crystal#indent#block_regex)
- let msl = crystal#indent#GetMSL(lnum)
+ " Previous line number
+ let indent_info.plnum = crystal#indent#PrevNonBlank(indent_info.clnum - 1)
+ let indent_info.pline = getline(indent_info.plnum)
- if getline(msl) =~# '=\s*\(#.*\)\=$'
- " in the case of assignment to the msl, align to the starting line,
- " not to the msl
- let ind = indent(lnum) + s:sw()
- else
- let ind = indent(msl) + s:sw()
- endif
- return ind
- endif
-
- " If the previous line started with a leading operator, use its MSL's level
- " of indent
- if crystal#indent#Match(lnum, g:crystal#indent#leading_operator_regex)
- return indent(crystal#indent#GetMSL(lnum))
- endif
-
- " If the previous line ended with the "*" of a splat, add a level of indent
- if line =~ g:crystal#indent#splat_regex
- return indent(lnum) + s:sw()
- endif
+ for callback_name in g:crystal#indent#prev_line_callbacks
+ let indent = call(function(callback_name), [indent_info])
- " If the previous line contained unclosed opening brackets and we are still
- " in them, find the rightmost one and add indent depending on the bracket
- " type.
- "
- " If it contained hanging closing brackets, find the rightmost one, find its
- " match and indent according to that.
- if line =~# '[[({]' || line =~# '[])]\s*\%(#.*\)\=$'
- let [opening, closing] = crystal#indent#ExtraBrackets(lnum)
-
- if opening.pos != -1
- if opening.type ==# '(' && searchpair('(', '', ')', 'bW', g:crystal#indent#skip_expr)
- if col('.') + 1 == col('$')
- return ind + s:sw()
- else
- return virtcol('.')
- endif
- else
- let nonspace = matchend(line, '\S', opening.pos + 1) - 1
- return nonspace > 0 ? nonspace : ind + s:sw()
- endif
- elseif closing.pos != -1
- call cursor(lnum, closing.pos + 1)
- keepjumps normal! %
-
- if crystal#indent#Match(line('.'), g:crystal#indent#crystal_indent_keywords)
- return indent('.') + s:sw()
- else
- return indent('.')
- endif
- else
- call cursor(clnum, vcol)
- end
- endif
-
- " If the previous line ended with an "end", match that "end"s beginning's
- " indent.
- let col = crystal#indent#Match(lnum, g:crystal#indent#end_end_regex)
- if col
- call cursor(lnum, col)
- if searchpair(
- \ g:crystal#indent#end_start_regex,
- \ g:crystal#indent#end_middle_regex,
- \ g:crystal#indent#end_end_regex,
- \ 'bW',
- \ g:crystal#indent#skip_expr)
- let n = line('.')
- let ind = indent('.')
- let msl = crystal#indent#GetMSL(n)
- if msl != n
- let ind = indent(msl)
- end
- return ind
+ if indent >= 0
+ return indent
endif
- end
+ endfor
- let col = crystal#indent#Match(lnum, g:crystal#indent#crystal_indent_keywords)
- if col
- call cursor(lnum, col)
- let ind = virtcol('.') - 1 + s:sw()
- " TODO: make this better (we need to count them) (or, if a searchpair
- " fails, we know that something is lacking an end and thus we indent a
- " level
- if crystal#indent#Match(lnum, g:crystal#indent#end_end_regex)
- let ind = indent('.')
- endif
- return ind
- endif
-
- " Work on the MSL line. {{{2
- " ---------------------
-
- " Set up variables to use and search for MSL to the previous line.
- let p_lnum = lnum
- let lnum = crystal#indent#GetMSL(lnum)
-
- " If the previous line wasn't a MSL.
- if p_lnum != lnum
- " If previous line ends bracket and begins non-bracket continuation decrease indent by 1.
- if crystal#indent#Match(p_lnum, g:crystal#indent#bracket_switch_continuation_regex)
- return ind - 1
- " If previous line is a continuation return its indent.
- " TODO: the || crystal#indent#IsInString() thing worries me a bit.
- elseif crystal#indent#Match(p_lnum, g:crystal#indent#non_bracket_continuation_regex) ||
- \ crystal#indent#IsInString(p_lnum,strlen(line))
- return ind
- endif
- endif
+ " Work on the MSL. {{{2
+ " ----------------
- " Set up more variables, now that we know we wasn't continuation bound.
- let line = getline(lnum)
- let msl_ind = indent(lnum)
+ " Most Significant line based on the previous one -- in case it's a
+ " contination of something above
+ let indent_info.plnum_msl = crystal#indent#GetMSL(indent_info.plnum)
+ let indent_info.pline_msl = getline(indent_info.plnum_msl)
- " If the MSL line had an indenting keyword in it, add a level of indent.
- " TODO: this does not take into account contrived things such as
- " module Foo; class Bar; end
- if crystal#indent#Match(lnum, g:crystal#indent#crystal_indent_keywords)
- let ind = msl_ind + s:sw()
- if crystal#indent#Match(lnum, g:crystal#indent#end_end_regex)
- let ind = ind - s:sw()
- endif
- return ind
- endif
+ for callback_name in g:crystal#indent#msl_callbacks
+ let indent = call(function(callback_name), [indent_info])
- " If the previous line ended with an operator -- but wasn't a block
- " ending, closing bracket, or type declaration -- indent one extra
- " level.
- if crystal#indent#Match(lnum, g:crystal#indent#non_bracket_continuation_regex) &&
- \ !crystal#indent#Match(lnum, '^\s*\([\])}]\|end\)')
- if lnum == p_lnum
- let ind = msl_ind + s:sw()
- else
- let ind = msl_ind
+ if indent >= 0
+ return indent
endif
- return ind
- endif
+ endfor
" }}}2
- return ind
+ " By default, just return the previous line's indent
+ return indent(indent_info.plnum)
endfunction
" }}}1
-let &cpo = s:cpo_save
-unlet s:cpo_save
-
-" vim:set sw=2 sts=2 ts=8 et:
+" vim:sw=2 sts=2 ts=8 fdm=marker et:
endif
diff --git a/indent/ecrystal.vim b/indent/ecrystal.vim
index 0d474587..9826cd7c 100644
--- a/indent/ecrystal.vim
+++ b/indent/ecrystal.vim
@@ -71,8 +71,7 @@ let s:ecr_control_open = '<%%\@!-\=[=#]\@!'
let s:ecr_comment_open = '<%%\@!-\=#'
let s:ecr_indent_regex =
- \ '\<\%(if\|unless\|else\|elsif\|case\|for\|when\|while\|until\|begin\|do\|rescue\|ensure\|' .
- \ 'class\|module\|struct\|lib\|enum\|union\)\>'
+ \ '\<\%(if\|unless\|else\|elsif\|case\|when\|while\|until\|begin\|do\|rescue\|ensure\|\)\>'
let s:ecr_dedent_regex =
\ '\<\%(end\|else\|elsif\|when\|rescue\|ensure\)\>'
diff --git a/indent/plantuml.vim b/indent/plantuml.vim
index 0d17276e..0553e706 100644
--- a/indent/plantuml.vim
+++ b/indent/plantuml.vim
@@ -77,7 +77,7 @@ endfunction
function! s:getIncIndent() abort
" Function to determine the s:incIndent pattern
return
- \ '^\s*\%(class\|entity\|object\|interface\|partition\|rectangle\|enum\|namespace\|package\)\>.*{\s*$\|' .
+ \ '^\s*\%(artifact\|class\|cloud\|database\|entity\|enum\|file\|folder\|frame\|interface\|namespace\|node\|object\|package\|partition\|rectangle\|skinparam\|state\|storage\|together\)\>.*{\s*$\|' .
\ '^\s*\%(loop\|alt\|opt\|group\|critical\|else\|legend\|box\|if\|while\|fork\|split\)\>\|' .
\ '^\s*ref\>[^:]*$\|' .
\ '^\s*[hr]\?note\>\%(\%("[^"]*" \<as\>\)\@![^:]\)*$\|' .
diff --git a/syntax/basic/symbols.vim b/syntax/basic/symbols.vim
index c4c025ac..2799ed39 100644
--- a/syntax/basic/symbols.vim
+++ b/syntax/basic/symbols.vim
@@ -16,10 +16,12 @@ syntax match typescriptBinaryOp contained /===\?/ nextgroup=@typescriptValue s
syntax match typescriptBinaryOp contained />\(>>=\|>>\|>=\|>\|=\)\?/ nextgroup=@typescriptValue skipwhite skipempty
" 4: <<=, <<, <=, <
syntax match typescriptBinaryOp contained /<\(<=\|<\|=\)\?/ nextgroup=@typescriptValue skipwhite skipempty
-" 3: ||, |=, |
-syntax match typescriptBinaryOp contained /|\(|\|=\)\?/ nextgroup=@typescriptValue skipwhite skipempty
-" 3: &&, &=, &
-syntax match typescriptBinaryOp contained /&\(&\|=\)\?/ nextgroup=@typescriptValue skipwhite skipempty
+" 3: ||, |=, |, ||=
+syntax match typescriptBinaryOp contained /||\?=\?/ nextgroup=@typescriptValue skipwhite skipempty
+" 4: &&, &=, &, &&=
+syntax match typescriptBinaryOp contained /&&\?=\?/ nextgroup=@typescriptValue skipwhite skipempty
+" 2: ??, ??=
+syntax match typescriptBinaryOp contained /??=\?/ nextgroup=@typescriptValue skipwhite skipempty
" 2: *=, *
syntax match typescriptBinaryOp contained /\*=\?/ nextgroup=@typescriptValue skipwhite skipempty
" 2: %=, %
diff --git a/syntax/basic/type.vim b/syntax/basic/type.vim
index ca7374a4..616c3271 100644
--- a/syntax/basic/type.vim
+++ b/syntax/basic/type.vim
@@ -94,9 +94,12 @@ syntax cluster typescriptTypeMember contains=
\ typescriptIndexSignature,
\ @typescriptMembers
+syntax match typescriptTupleLable /\K\k*?\?:/
+ \ contained
+
syntax region typescriptTupleType matchgroup=typescriptBraces
\ start=/\[/ end=/\]/
- \ contains=@typescriptType,@typescriptComments
+ \ contains=@typescriptType,@typescriptComments,typescriptRestOrSpread,typescriptTupleLable
\ contained skipwhite
syntax cluster typescriptTypeOperator
diff --git a/syntax/common.vim b/syntax/common.vim
index 6b451cec..11c71acf 100644
--- a/syntax/common.vim
+++ b/syntax/common.vim
@@ -101,6 +101,7 @@ if exists("did_typescript_hilink")
HiLink typescriptBoolean Boolean
HiLink typescriptObjectLabel typescriptLabel
HiLink typescriptLabel Label
+ HiLink typescriptTupleLable Label
HiLink typescriptStringProperty String
HiLink typescriptImport Special
HiLink typescriptImportType Special
diff --git a/syntax/crystal.vim b/syntax/crystal.vim
index 217cb6db..c3ed4c18 100644
--- a/syntax/crystal.vim
+++ b/syntax/crystal.vim
@@ -150,6 +150,7 @@ syn match crystalModuleName "\%(\%([.@$]\@1<!\.\)\@1<!\<\|::\)\_s*\zs\u\w
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
@@ -247,53 +248,56 @@ SynFold '<<' syn region crystalString start=+\%(\%(class\|::\)\_s*\|\%([]}).]\)\
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,crystalGlobalVariable,crystalPredefinedVariable nextgroup=crystalAliasDeclaration2 skipwhite
-syn match crystalAliasDeclaration2 "[^[:space:];#.()]\+" contained contains=crystalSymbol,crystalGlobalVariable,crystalPredefinedVariable
-syn match crystalMethodDeclaration "[^[:space:];#(]\+" contained contains=crystalConstant,crystalFunction,crystalBoolean,crystalPseudoVariable,crystalInstanceVariable,crystalClassVariable,crystalGlobalVariable
-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 crystalAliasDeclaration "[^[:space:];#.()]\+" contained contains=crystalSymbol,crystalGlobalVariable,crystalPredefinedVariable nextgroup=crystalAliasDeclaration2 skipwhite
+syn match crystalAliasDeclaration2 "[^[:space:];#.()]\+" contained contains=crystalSymbol,crystalGlobalVariable,crystalPredefinedVariable
+syn match crystalMethodDeclaration "[^[:space:];#(]\+" contained contains=crystalConstant,crystalFunction,crystalBoolean,crystalPseudoVariable,crystalInstanceVariable,crystalClassVariable,crystalGlobalVariable
+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
+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 crystalOperator "\<defined?" display
syn match crystalKeyword "\<\%(super\|previous_def\|yield\|of\|with\|uninitialized\|union\)\>[?!]\@!"
syn match crystalBoolean "\<\%(true\|false\)\>[?!]\@!"
-syn match crystalPseudoVariable "\<\%(nil\|self\|__DIR__\|__FILE__\|__LINE__\|__END_LINE__\)\>[?!]\@!" " TODO: reorganise
+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 "\<undef\>" nextgroup=crystalFunction 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
-
- SynFold 'def' syn region crystalMethodBlock start="\<\%(def\|macro\)\>" matchgroup=crystalDefine end="\%(\<\%(def\|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
+ 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 "\<undef\>" nextgroup=crystalFunction 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\|macro\)\>" matchgroup=crystalDefine end="\%(\<\%(def\|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
" modifiers
syn match crystalConditionalModifier "\<\%(if\|unless\|ifdef\)\>" display
@@ -326,14 +330,15 @@ if !exists('b:crystal_no_expensive') && !exists('g:crystal_no_expensive')
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 "\<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\|until\|else\|elsif\|ensure\|then\|when\|end\)\>[?!]\@!"
syn match crystalKeyword "\<\%(alias\|undef\)\>[?!]\@!"
endif
@@ -358,8 +363,8 @@ endif
" Macro
" Note: This definition must be put after crystalNestedCurlyBraces to give higher priority
-syn region crystalMacroRegion matchgroup=crystalMacroDelim start="\\\={%" end="%}" oneline display contains=@crystalMacroGroup containedin=ALL
-syn region crystalMacroRegion matchgroup=crystalMacroDelim start="\\\={{" end="}}" oneline display contains=@crystalMacroGroup containedin=ALL
+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
@@ -375,8 +380,7 @@ syn cluster crystalMacroGroup remove=@crystalExpensive
" Some keywords will have to be redefined for them to be highlighted
" properly
syn keyword crystalMacroKeyword contained
- \ if else elsif end for in begin do case when while until loop
- \ rescue ensure
+ \ if unless else elsif end for in do while until loop begin
syn cluster crystalMacroGroup add=crystalMacroKeyword
@@ -414,6 +418,7 @@ 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
@@ -442,6 +447,7 @@ 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 crystalGlobalVariable crystalIdentifier
hi def link crystalBlockParameter crystalIdentifier
hi def link crystalInstanceVariable crystalIdentifier
@@ -478,7 +484,7 @@ hi def link crystalRegexp crystalString
hi def link crystalMacro PreProc
hi def link crystalMacroDelim crystalMacro
hi def link crystalMacroKeyword crystalKeyword
-hi def link crystalLinkAttrDelim crystalMacro
+hi def link crystalLinkAttrDelim crystalMacroDelim
hi def link crystalError Error
hi def link crystalInvalidVariable crystalError
hi def link crystalSpaceError crystalError
diff --git a/syntax/dhall.vim b/syntax/dhall.vim
index dbbb43d1..a28a4bc4 100644
--- a/syntax/dhall.vim
+++ b/syntax/dhall.vim
@@ -24,7 +24,7 @@ syntax match dhallLabel "\v[a-z_][A-Za-z0-9\-]*"
syntax match dhallType "\v[a-zA-Z]+\.[A-Z][a-z0-9A-Z_]*"
syntax match dhallParens "(\|)\|\[\|\]\|,"
syntax match dhallRecord "{\|}\|:"
-syntax keyword dhallKeyword let in forall constructors if then else merge env as
+syntax keyword dhallKeyword let in forall constructors if then else merge env as with
syntax match dhallEsc +\\["\\abfnrtv$/]+
syntax match dhallSingleSpecial +'''+
syntax match dhallSingleSpecial +''${+
diff --git a/syntax/plantuml.vim b/syntax/plantuml.vim
index 3968f7dd..f8d7f4e6 100644
--- a/syntax/plantuml.vim
+++ b/syntax/plantuml.vim
@@ -91,7 +91,7 @@ syntax region plantumlText oneline start=/\[/ms=s+1 end=/\]/me=s-1 contained
syntax match plantumlArrowDirectedLine /\([-.]\)\%(l\%[eft]\|r\%[ight]\|up\?\|d\%[own]\)\1/ contained
" Note and legend
-syntax region plantumlNoteMultiLine start=/\%(^\s*[rh]\?\%(note\|legend\)\)\@<=\s\%([^:"]\+$\)\@=/ end=/^\%(\s*end\s*[rh]\?\%(note\|legend\)$\)\|endlegend\@=/ contains=plantumlSpecialString,plantumlNoteMultiLineStart,plantumlTag
+syntax region plantumlNoteMultiLine start=/\%(^\s*[rh]\?\%(note\|legend\)\)\@<=\s\%([^:"]\+$\)\@=/ end=/^\%(\s*\zeend\s*[rh]\?\%(note\|legend\)$\)\|endlegend\@=/ contains=plantumlSpecialString,plantumlNoteMultiLineStart,plantumlTag
syntax match plantumlNoteMultiLineStart /\%(^\s*[rh]\?\%(note\|legend\)\)\@<=\s\%([^:]\+$\)/ contained contains=plantumlKeyword,plantumlColor,plantumlString,plantumlTag
" Class
@@ -140,11 +140,11 @@ syntax match plantumlActivityLabel /\%(^\%(#\S\+\)\?\)\@<=:\_[^;|<>/\]}]\+[;|<>/
syntax match plantumlSequenceDivider /^\s*==[^=]\+==\s*$/
syntax match plantumlSequenceSpace /^\s*|||\+\s*$/
syntax match plantumlSequenceSpace /^\s*||\d\+||\+\s*$/
-syntax match plantumlSequenceDelay /^\.\{3}$/
-syntax region plantumlText oneline matchgroup=plantumlSequenceDelay start=/^\.\{3}/ end=/\.\{3}$/
+syntax match plantumlSequenceDelay /^\s*\.\{3}$/
+syntax region plantumlText oneline matchgroup=plantumlSequenceDelay start=/^\s*\.\{3}/ end=/\.\{3}$/
" Usecase diagram
-syntax match plantumlUsecaseActor /:.\{-1,}:/ contains=plantumlSpecialString
+syntax match plantumlUsecaseActor /^\s*:.\{-1,}:/ contains=plantumlSpecialString
" Mindmap diagram
diff --git a/syntax/vifm.vim b/syntax/vifm.vim
index c5eb9bf1..ffe684b3 100644
--- a/syntax/vifm.vim
+++ b/syntax/vifm.vim
@@ -2,7 +2,7 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vifm') == -1
" vifm syntax file
" Maintainer: xaizek <xaizek@posteo.net>
-" Last Change: May 26, 2020
+" Last Change: June 22, 2020
" Inspired By: Vim syntax file by Dr. Charles E. Campbell, Jr.
if exists('b:current_syntax')
@@ -17,27 +17,27 @@ set cpo-=C
" General commands
syntax keyword vifmCommand contained
\ alink apropos bmark bmarks bmgo cds change chmod chown clone compare
- \ cope[n] co[py] cq[uit] d[elete] delbmarks delm[arks] di[splay] dirs e[dit]
- \ el[se] empty en[dif] exi[t] file fin[d] fini[sh] go[to] gr[ep] h[elp]
- \ hideui histnext his[tory] histprev jobs locate ls lstrash marks media
- \ mes[sages] mkdir m[ove] noh[lsearch] on[ly] popd pushd pu[t] pw[d] qa[ll]
- \ q[uit] redr[aw] reg[isters] regular rename restart restore rlink screen
- \ sh[ell] siblnext siblprev sor[t] sp[lit] s[ubstitute] tabc[lose] tabm[ove]
- \ tabname tabnew tabn[ext] tabo[nly] tabp[revious] touch tr trashes tree
- \ sync undol[ist] ve[rsion] vie[w] vifm vs[plit] winc[md] w[rite] wq wqa[ll]
- \ xa[ll] x[it] y[ank]
+ \ cope[n] co[py] cq[uit] d[elete] delbmarks delm[arks] delsession di[splay]
+ \ dirs e[dit] el[se] empty en[dif] exi[t] file fin[d] fini[sh] go[to] gr[ep]
+ \ h[elp] hideui histnext his[tory] histprev jobs locate ls lstrash marks
+ \ media mes[sages] mkdir m[ove] noh[lsearch] on[ly] popd pushd pu[t] pw[d]
+ \ qa[ll] q[uit] redr[aw] reg[isters] regular rename restart restore rlink
+ \ screen sh[ell] siblnext siblprev sor[t] sp[lit] s[ubstitute] tabc[lose]
+ \ tabm[ove] tabname tabnew tabn[ext] tabo[nly] tabp[revious] touch tr
+ \ trashes tree session sync undol[ist] ve[rsion] vie[w] vifm vs[plit]
+ \ winc[md] w[rite] wq wqa[ll] xa[ll] x[it] y[ank]
\ nextgroup=vifmArgs
syntax keyword vifmCommandCN contained
\ alink apropos bmark bmarks bmgo cds change chmod chown clone compare
- \ cope[n] co[py] cq[uit] d[elete] delbmarks delm[arks] di[splay] dirs e[dit]
- \ el[se] empty en[dif] exi[t] file fin[d] fini[sh] go[to] gr[ep] h[elp]
- \ hideui histnext his[tory] histprev jobs locate ls lstrash marks media
- \ mes[sages] mkdir m[ove] noh[lsearch] on[ly] popd pushd pu[t] pw[d] qa[ll]
- \ q[uit] redr[aw] reg[isters] regular rename restart restore rlink screen
- \ sh[ell] siblnext siblprev sor[t] sp[lit] s[ubstitute] tabc[lose] tabm[ove]
- \ tabname tabnew tabn[ext] tabp[revious] touch tr trashes tree sync
- \ undol[ist] ve[rsion] vie[w] vifm vs[plit] winc[md] w[rite] wq wqa[ll]
- \ xa[ll] x[it] y[ank]
+ \ cope[n] co[py] cq[uit] d[elete] delbmarks delm[arks] delsession di[splay]
+ \ dirs e[dit] el[se] empty en[dif] exi[t] file fin[d] fini[sh] go[to] gr[ep]
+ \ h[elp] hideui histnext his[tory] histprev jobs locate ls lstrash marks
+ \ media mes[sages] mkdir m[ove] noh[lsearch] on[ly] popd pushd pu[t] pw[d]
+ \ qa[ll] q[uit] redr[aw] reg[isters] regular rename restart restore rlink
+ \ screen sh[ell] siblnext siblprev sor[t] sp[lit] s[ubstitute] tabc[lose]
+ \ tabm[ove] tabname tabnew tabn[ext] tabo[nly] tabp[revious] touch tr
+ \ trashes tree session sync undol[ist] ve[rsion] vie[w] vifm vs[plit]
+ \ winc[md] w[rite] wq wqa[ll] xa[ll] x[it] y[ank]
\ nextgroup=vifmArgsCN
" commands that might be prepended to a command without changing everything else
@@ -144,12 +144,12 @@ syntax keyword vifmOption contained aproposprg autochpos caseoptions cdpath cd
\ iec ignorecase ic iooptions incsearch is laststatus lines locateprg ls
\ lsoptions lsview mediaprg milleroptions millerview mintimeoutlen number nu
\ numberwidth nuw previewprg quickview relativenumber rnu rulerformat ruf
- \ runexec scrollbind scb scrolloff so sort sortgroups sortorder sortnumbers
- \ shell sh shellflagcmd shcf shortmess shm showtabline stal sizefmt slowfs
- \ smartcase scs statusline stl suggestoptions syncregs syscalls tablabel
- \ tabscope tabstop timefmt timeoutlen title tm trash trashdir ts tuioptions
- \ to undolevels ul vicmd viewcolumns vifminfo vimhelp vixcmd wildmenu wmnu
- \ wildstyle wordchars wrap wrapscan ws
+ \ runexec scrollbind scb scrolloff sessionoptions ssop so sort sortgroups
+ \ sortorder sortnumbers shell sh shellflagcmd shcf shortmess shm showtabline
+ \ stal sizefmt slowfs smartcase scs statusline stl suggestoptions syncregs
+ \ syscalls tablabel tabscope tabstop timefmt timeoutlen title tm trash
+ \ trashdir ts tuioptions to undolevels ul vicmd viewcolumns vifminfo vimhelp
+ \ vixcmd wildmenu wmnu wildstyle wordchars wrap wrapscan ws
" Disabled boolean options
syntax keyword vifmOption contained noautochpos nocf nochaselinks nodotfiles