diff options
Diffstat (limited to '')
| -rw-r--r-- | autoload/crystal/indent.vim | 967 | ||||
| -rw-r--r-- | autoload/crystal_lang.vim | 6 | ||||
| -rw-r--r-- | autoload/dart.vim | 14 | ||||
| -rw-r--r-- | autoload/vital/_crystal/ColorEcho.vim | 5 | ||||
| -rw-r--r-- | autoload/vital/_crystal/Data/List.vim | 6 | ||||
| -rw-r--r-- | autoload/vital/_crystal/Data/String.vim | 5 | ||||
| -rw-r--r-- | autoload/vital/_crystal/Process.vim | 6 | ||||
| -rw-r--r-- | autoload/vital/_crystal/Web/JSON.vim | 5 | ||||
| -rw-r--r-- | ftplugin/crystal.vim | 55 | ||||
| -rw-r--r-- | ftplugin/eruby.vim | 2 | ||||
| -rw-r--r-- | indent/crystal.vim | 279 | ||||
| -rw-r--r-- | indent/ecrystal.vim | 3 | ||||
| -rw-r--r-- | indent/plantuml.vim | 2 | ||||
| -rw-r--r-- | syntax/basic/symbols.vim | 10 | ||||
| -rw-r--r-- | syntax/basic/type.vim | 5 | ||||
| -rw-r--r-- | syntax/common.vim | 1 | ||||
| -rw-r--r-- | syntax/crystal.vim | 96 | ||||
| -rw-r--r-- | syntax/dhall.vim | 2 | ||||
| -rw-r--r-- | syntax/plantuml.vim | 8 | ||||
| -rw-r--r-- | syntax/vifm.vim | 50 | 
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 | 
