diff options
| author | Adam Stankiewicz <sheerun@sher.pl> | 2018-12-26 20:33:28 +0100 | 
|---|---|---|
| committer | Adam Stankiewicz <sheerun@sher.pl> | 2018-12-26 20:33:28 +0100 | 
| commit | c161994e9607399a7b365ab274592bfc4f100306 (patch) | |
| tree | 3e5f8e3ab137f58ecb01fcc59d354cf22f25a6a2 /autoload | |
| parent | f2383782218926011746ea85d7c2539b5980ac87 (diff) | |
| download | vim-polyglot-c161994e9607399a7b365ab274592bfc4f100306.tar.gz vim-polyglot-c161994e9607399a7b365ab274592bfc4f100306.zip | |
Add pony supportv3.4.0
Diffstat (limited to '')
| -rw-r--r-- | autoload/pony.vim | 536 | 
1 files changed, 536 insertions, 0 deletions
| diff --git a/autoload/pony.vim b/autoload/pony.vim new file mode 100644 index 00000000..51568aa4 --- /dev/null +++ b/autoload/pony.vim @@ -0,0 +1,536 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'pony') == -1 +   +" Vim plugin file +" Language:     Pony +" Maintainer:   Jak Wings + +" TODO: Make sure echomsg is off for release. +let s:cpo_save = &cpo +set cpo&vim + + +"let s:skip = '<SID>InCommentOrLiteral(line("."), col("."))' +let s:skip2 = '<SID>InLiteral(line("."), col(".")) || <SID>InComment(line("."), col(".")) == 1' +let s:skip3 = '!<SID>InKeyword(line("."), col("."))' +let s:skip4 = '!<SID>InBracket(line("."), col("."))' +let s:cfstart = '\v<%(ifdef|if|match|while|for|repeat|try|with|recover|object|lambda|iftype)>' +let s:cfmiddle = '\v<%(then|elseif|else|until|do|in|elseiftype)>|\|' +let s:cfend = '\v<end>' +let s:bstartp = '\v<%(ifdef|if|then|elseif|else|(match)|while|for|in|do|try|with|recover|repeat|until|(object)|lambda|iftype|elseiftype)>' + +function! pony#Indent() +  if v:lnum <= 1 +    return 0 +  endif + +  call cursor(v:lnum, 1) +  let l:pnzpos = searchpos('.', 'cbnW') +  if l:pnzpos == [0, 0] +    return 0 +  endif + +  if s:InComment2(l:pnzpos) > 1 +    "echomsg 'Comment' (l:pnzpos[0] . '-' . v:lnum) -1 +    return cindent(v:lnum) +  endif + +  if s:InLiteral2(l:pnzpos) +    "echomsg 'String' (l:pnzpos[0] . '-' . v:lnum) -1 +    return -1 +  endif + +  unlet! l:pnzpos + +  " NOTE: Lines started in comments and strings are checked already. + +  let l:pnblnum = s:PrevNonblank(v:lnum - 1) +  if l:pnblnum < 1 +    return 0 +  endif + +  let l:pnbline = getline(l:pnblnum) +  let l:pnbindent = indent(l:pnblnum) + +  let l:line = getline(v:lnum) +  let l:indent = l:pnbindent +  let l:shiftwidth = shiftwidth() + +  " FIXME? +  let l:continuing = 0 +  " If the previous line ends with a unary or binary operator, +  if s:IsContinued(l:pnblnum) +    let l:contlnum = l:pnblnum +    let l:ppcontinued = 0 +    let l:ppnblnum = s:PrevNonblank(l:pnblnum - 1) +    while s:IsContinued(l:ppnblnum) +      let l:ppcontinued += 1 +      let l:contlnum = l:ppnblnum +      let l:ppnblnum = s:PrevNonblank(l:ppnblnum - 1) +    endwhile +    "echomsg 'Continued1' l:pnblnum l:contlnum +    " If the previous line is also continuing another line, +    if l:ppcontinued +      let l:continuing = 1 +      if getline(l:contlnum) =~# '\v^\s*%(actor|class|struct|primitive|trait|type|interface)>' +        " reset the indent level. +        "echomsg 'Continuing0' (l:contlnum . '-' . v:lnum) (l:shiftwidth * 2) +        let l:indent = l:shiftwidth * 2 +      else +        " keep using the previous indent. +        "echomsg 'Continuing1' (l:pnblnum . '-' . v:lnum) l:pnbindent +        let l:indent = l:pnbindent +      endif +    " if the previous line is part of the definition of a class, +    elseif l:pnbline =~# '\v^\s*%(actor|class|struct|primitive|trait|type|interface)>' +      " reset the indent level. +      "echomsg 'Continuing2' (l:pnblnum . '-' . v:lnum) (l:shiftwidth * 2) +      let l:continuing = 1 +      let l:indent = l:shiftwidth * 2 +    " if the previous line is part of the definition of a method, +    elseif l:pnbline =~# '\v^\s*%(fun|new|be)>' +      " reset the indent level. +      "echomsg 'Continuing3' (l:pnblnum . '-' . v:lnum) (l:pnbindent + l:shiftwidth) +      let l:continuing = 1 +      let l:indent = l:pnbindent + l:shiftwidth +    " if the previous line is the start of a definition body, +    elseif l:pnbline =~# '=>\s*$' +      " indent this line. +      "echomsg 'Continuing4' (l:pnblnum . '-' . v:lnum) (l:pnbindent + l:shiftwidth) +      let l:continuing = 1 +      let l:indent = l:pnbindent + l:shiftwidth +    else +      " indent this line twice as far. +      "echomsg 'Continuing5' (l:pnblnum . '-' . v:lnum) (l:pnbindent + l:shiftwidth * 2) +      let l:continuing = 1 +      let l:indent = l:pnbindent + l:shiftwidth * 2 +    endif + +    unlet! l:contlnum l:ppnblnum l:ppcontinued +  endif + +  " If this line starts a document string, +  if !l:continuing && l:line =~# '^\s*"""' +    let l:ppnblnum = s:PrevNonblank(l:pnblnum - 1) +    if s:IsContinued(l:ppnblnum) +      let l:contlnum = l:ppnblnum +      while s:IsContinued(l:ppnblnum) +        let l:contlnum = l:ppnblnum +        let l:ppnblnum = s:PrevNonblank(l:ppnblnum - 1) +      endwhile +      if getline(l:contlnum) =~# '\v^\s*%(actor|class|struct|primitive|trait|type|interface)>' +        " reset the indent level. +        "echomsg 'DocString' (l:contlnum . '-' . v:lnum) l:shiftwidth +        return l:shiftwidth +      endif +    endif + +    unlet! l:contlnum l:ppnblnum +  endif + +  " If the previous line contains an unmatched opening bracket +  if !l:continuing && l:pnbline =~# '[{[(]' +    " if the line ends with an opening bracket, +    if l:pnbline =~# '[{[(]\s*$' && !s:InCommentOrLiteral(l:pnblnum, col([l:pnblnum, '$']) - 1) +      " indent this line. +      let l:indent += l:shiftwidth +    else +      " find the unmatched opening bracket, +      let l:start = [0, 0] +      let l:end = col([l:pnblnum, '$']) - 1 +      call cursor(l:pnblnum, l:end) +      while l:end > 0 +        let l:start = s:OuterPos(l:start, searchpairpos('(', '', ')', 'bnW', s:skip4, l:pnblnum)) +        let l:start = s:OuterPos(l:start, searchpairpos('\[', '', '\]', 'bnW', s:skip4, l:pnblnum)) +        let l:start = s:OuterPos(l:start, searchpairpos('{', '', '}', 'bnW', s:skip4, l:pnblnum)) +        if l:start == [0, 0] +          break +        endif +        " find the matched closing bracket on the same line, +        call cursor(l:start[0], l:start[1]) +        let l:c = s:CharAtCursor(l:start[0], l:start[1]) +        if searchpair(escape(l:c, '['), '', escape(tr(l:c, '([{', ')]}'), ']'), +              \ 'znW', s:skip4, l:pnblnum) < 1 +          " the unmatched opening bracket is found, +          break +        endif +        let l:end = l:start[1] +        let l:start = [0, 0] +      endwhile +      if l:start != [0, 0] +        " indent this line. +        "echomsg 'Open bracket' (l:pnblnum . '-' . v:lnum) (l:indent + l:shiftwidth) +        let l:indent += l:shiftwidth +      endif +    endif + +    unlet! l:start l:end l:c +  endif + +  " If there is a matched closing bracket on the previous line, +  " NOTE: +  " >|[ +  "  |  (1 - +  "  |      1) * 2] +  "  |  command +  "   ^ +  if !l:continuing +    call cursor(l:pnblnum, 1) +    " find the last closing bracket, +    let l:end = [0, 0] +    let l:end = s:OuterPos(l:end, searchpairpos('(', '', ')', 'zncr', s:skip4, l:pnblnum)) +    let l:end = s:OuterPos(l:end, searchpairpos('\[', '', '\]', 'zncr', s:skip4, l:pnblnum)) +    let l:end = s:OuterPos(l:end, searchpairpos('{', '', '}', 'zncr', s:skip4, l:pnblnum)) +    if l:end != [0, 0] +      " find the matched opening bracket on another line, +      let l:c = s:CharAtCursor(l:end[0], l:end[1]) +      let l:start = searchpairpos(escape(tr(l:c, ')]}', '([{'), '['), '', escape(l:c, ']'), 'nbW', s:skip4) +      if l:start[0] != l:end[0] +        " and then this line has the same indent as the line the matched bracket stays. +        "echomsg 'Matched bracket' (l:start[0] . '-' . v:lnum) indent(l:start[0]) +        let l:indent = indent(l:start[0]) +      endif +    endif + +    unlet! l:start l:end l:c +  endif + +  " If there is a matched closing bracket on this line, +  " NOTE: +  "  |[ +  " >|  (1 - +  "  |      1) * 2 +  "  |] +  "   ^     ^ +  if l:line =~# '^\s*[)\]}]' +    " find the first closing bracket, +    call cursor(v:lnum, 1) +    let l:end = [0, 0] +    let l:end = s:InnerPos(l:end, searchpairpos('(', '', ')', 'zncW', s:skip4, v:lnum)) +    let l:end = s:InnerPos(l:end, searchpairpos('\[', '', '\]', 'zncW', s:skip4, v:lnum)) +    let l:end = s:InnerPos(l:end, searchpairpos('{', '', '}', 'zncW', s:skip4, v:lnum)) +    if l:end != [0, 0] +      " find the matched opening bracket on another line, +      let l:c = s:CharAtCursor(l:end[0], l:end[1]) +      let l:start = searchpairpos(escape(tr(l:c, ')]}', '([{'), '['), '', escape(l:c, ']'), 'nbW', s:skip4) +      if l:start[0] != l:end[0] +        " and then this line has the same indent as the line the matched bracket stays. +        "echomsg 'Closing Bracket' (l:start[0] . '-' . v:lnum) indent(l:start[0]) +        let l:indent = indent(l:start[0]) +      endif +    endif + +    unlet! l:start l:end l:c +  endif + +  " If this line starts the definition of a method, closure or match case, +  if l:line =~# '^\s*=>' +    " find the start of the definition, +    call cursor(v:lnum, 1) +    let l:start = searchpairpos('\v<%(new|be|fun|lambda)>|\|', '', '=>\zs', 'bnW', s:skip3) +    if l:start != [0, 0] +      " then this line has the same indent as the start. +      "echomsg 'Method body' (l:start[0] . '-' . v:lnum) indent(l:start[0]) +      return indent(l:start[0]) +    endif + +    unlet! l:start +  endif + +  " If this line starts a class definition or starts an alias, +  if l:line =~# '\v^\s*%(actor|class|struct|primitive|trait|interface|use|type)>' +    " reset the indent level. +    return 0 +  endif + +  " If this line starts a method definition, +  if l:line =~# '\v^\s*%(new|be|fun)>' +    call cursor(v:lnum, 1) +    let l:start = searchpairpos(s:cfstart, s:cfmiddle, s:cfend, 'bW', s:skip3) +    if l:start != [0, 0] +      let l:start = searchpos(s:bstartp, 'zcnpW', l:start[0]) +      " see if it is in an object block, +      if l:start[2] == 3 +        "echomsg 'Method in object' (l:start[0] . '-' . v:lnum) (l:shiftwidth + indent(l:start[0])) +        return l:shiftwidth + indent(l:start[0]) +      endif +    endif +    return l:shiftwidth +  endif + +  " If this line starts a match case, +  call cursor(v:lnum, 1) +  if l:line =~# '^\s*|' && s:InKeyword(searchpos('|', 'znW', v:lnum)) +    " find the start or the previous case of the match block, +    let l:start = searchpairpos(s:cfstart, s:cfmiddle, s:cfend, 'bnW', s:skip3) +    if l:start != [0, 0] +      " then this line has the same indent as the start. +      "echomsg 'Match case' (l:start[0] . '-' . v:lnum) indent(l:start[0]) +      return indent(l:start[0]) +    endif + +    unlet! l:start +  endif + +  " If this line ends (part of) a control flow, +  if l:line =~# '\v^\s*%(end|elseif|else|then|in|do|until|elseiftype)>' +    " find the start or middle of the control block, +    call cursor(v:lnum, 1) +    let l:start = searchpairpos(s:cfstart, s:cfmiddle, s:cfend, 'bnW', s:skip3) +    if l:start != [0, 0] +      " then this line has the same indent as the start. +      "echomsg 'Block end' (l:start[0] . '-' . v:lnum) indent(l:start[0]) +      return indent(l:start[0]) +    endif + +    unlet! l:start +  endif + +  " If the previous line starts a class definition, +  if l:pnbline =~# '\v^\s*%(actor|class|struct|primitive|trait|type|interface)>' +    " reset the indent level. +    if s:IsContinued(l:pnblnum) +      return l:shiftwidth * 2 +    else +      return l:shiftwidth +    endif +  endif + +  " If the previous line starts a method definition, +  if l:pnbline =~# '\v^\s*%(new|be|fun)>' +    return l:pnbindent + l:shiftwidth +  endif + +  " If the previous line starts (part of) a control flow, +  call cursor(l:pnblnum, 1) +  while 1 +    " find the start of the control block, +    let l:start = searchpos(s:bstartp, 'zcepW', l:pnblnum) +    if l:start[2] == 0 +      break +    endif +    if !s:InKeyword(l:start[0:1]) +      call cursor(l:pnblnum, l:start[1] + 3) +      continue +    endif +    let l:index = l:start[2] +    " find the end of the control block on the same line, +    let l:end = searchpair(s:cfstart, '', s:cfend, 'znW', s:skip3, l:pnblnum) +    " if the control block is not ended, +    if l:end < 1 +      " if this line is a case for a match, +      if l:index == 2 && l:line =~# '^\s*|' +        " then this line has the same indent as the start of the match block. +        return l:pnbindent +      else +        " then indent this line. +        "echomsg 'Block start' (l:pnblnum . '-' . v:lnum) (l:pnbindent + l:shiftwidth) +        return l:pnbindent + l:shiftwidth +      endif +    endif +  endwhile + +  unlet! l:start l:end l:index + +  return l:indent +endfunction + +function! s:PrevNonblank(lnum) +  let l:lnum = prevnonblank(a:lnum) +  while l:lnum > 0 && (s:InComment2(l:lnum, 1) || s:InLiteral2(l:lnum, 1)) +    let l:lnum = prevnonblank(l:lnum - 1) +  endwhile +  return l:lnum +endfunction + +" NOTE: +"                 v +"  |1 /* comment */ +"  |2 +function! s:IsContinued(lnum) +  let l:lnum = s:PrevNonblank(a:lnum) +  if l:lnum < 1 +    return 0 +  endif +  let l:line = getline(l:lnum) +  let l:width = strwidth(substitute(l:line, '\s*$', '', '')) +  " FIXME? +  "  | 1 + // +  "  | // +  "  |     2 +  return !s:InCommentOrLiteral(a:lnum, l:width) +        \ && (l:line =~# '\v<%(and|or|xor|is|isnt|as|not|consume|addressof|digestof)\s*$' +        \ || l:line =~# '\v%([=\-.]\>|[<!=>]\=\~?|\<\<\~?|\>\>\~?|\<:|[+\-*/%<>]\~?|[.,|:@~])\s*$' +        \ ) +endfunction + +function! s:InCommentOrLiteral(...) +  return call('s:InComment', a:000) || call('s:InLiteral', a:000) +endfunction + +function! s:InKeyword(...) +  let [l:lnum, l:col] = (type(a:1) == type([]) ? a:1 : a:000) +  for id in s:Or(synstack(l:lnum, l:col), []) +    if synIDattr(id, 'name') =~# '^ponyKw' +      return 1 +    endif +  endfor +  return 0 +endfunction + +function! s:InBracket(...) +  let [l:lnum, l:col] = (type(a:1) == type([]) ? a:1 : a:000) +  for id in s:Or(synstack(l:lnum, l:col), []) +    if synIDattr(id, 'name') ==# 'ponyBracket' +      return 1 +    endif +  endfor +  return 0 +endfunction + +function! s:InComment(...) +  let [l:lnum, l:col] = (type(a:1) == type([]) ? a:1 : a:000) +  let l:stack = synstack(l:lnum, l:col) +  let l:i = len(l:stack) +  while l:i > 0 +    let l:sname = synIDattr(l:stack[l:i - 1], 'name') +    if l:sname =~# '^ponyNestedCommentX\?$' +      return 1 + l:i - (l:sname =~# 'X$') +    elseif l:sname =~# '^ponyCommentX\?$' +      return 1 +    endif +    let l:i -= 1 +  endwhile +  return 0 +endfunction + +function! s:InLiteral(...) +  let [l:lnum, l:col] = (type(a:1) == type([]) ? a:1 : a:000) +  let l:stack = synstack(l:lnum, l:col) +  let l:i = len(l:stack) +  while l:i > 0 +    let l:sname = synIDattr(l:stack[l:i - 1], 'name') +    if l:sname =~# '^ponyDocumentStringX\?$' +      return 3 +    elseif l:sname =~# '^ponyStringX\?$' +      return 2 +    elseif l:sname =~# '^ponyCharacterX\?$' +      return 1 +    endif +    let l:i -= 1 +  endwhile +  return 0 +endfunction + +" NOTE: +" |// //inside +"   ^^^^^^^^^^ +" |/* /*inside*/ */ +"   ^^^^^^^^^^^^^^ +function! s:InComment2(...) +  let [l:lnum, l:col] = (type(a:1) == type([]) ? a:1 : a:000) +  let l:stack = synstack(l:lnum, l:col) +  let l:i = len(l:stack) +  while l:i > 0 +    let l:sname = synIDattr(l:stack[l:i - 1], 'name') +    if l:sname ==# 'ponyNestedComment' +      return 1 + l:i +    elseif l:sname ==# 'ponyComment' +      return 1 +    elseif l:sname =~# '\v^pony%(Nested)?CommentX$' +      return 0 +    endif +    let l:i -= 1 +  endwhile +  return 0 +endfunction + +" NOTE: +" |"inside" +"   ^^^^^^ +" |"""inside""""" +"   ^^^^^^^^^^^^ +function! s:InLiteral2(...) +  let [l:lnum, l:col] = (type(a:1) == type([]) ? a:1 : a:000) +  let l:stack = synstack(l:lnum, l:col) +  let l:i = len(l:stack) +  while l:i > 0 +    let l:sname = synIDattr(l:stack[l:i - 1], 'name') +    if l:sname ==# 'ponyDocumentString' +      return 3 +    elseif l:sname ==# 'ponyString' +      return 2 +    elseif l:sname ==# 'ponyCharacter' +      return 1 +    elseif l:sname =~# '\v^pony%(DocumentString|String|Character)X$' +      return 0 +    endif +    let l:i -= 1 +  endwhile +  return 0 +endfunction + +function! s:CharAtCursor(...) +  let [l:lnum, l:col] = (type(a:1) == type([]) ? a:1 : a:000) +  return matchstr(getline(l:lnum), '\%' . l:col . 'c.') +endfunction + +function! s:Or(x, y) +  return !empty(a:x) ? a:x : a:y +endfunction + +function! s:InnerPos(x, y) +  if a:x == [0, 0] +    return a:y +  elseif a:y == [0, 0] +    return a:x +  else +    return a:x[1] < a:y[1] ? a:x : a:y +  end +endfunction + +function! s:OuterPos(x, y) +  if a:x == [0, 0] +    return a:y +  elseif a:y == [0, 0] +    return a:x +  else +    return a:x[1] > a:y[1] ? a:x : a:y +  end +endfunction + +function! pony#ClearTrailingSpace(all, alt, ...) +  let l:force = (a:0 > 0 ? a:1 : 0) +  if !l:force && (&readonly || !&modifiable || !&modified) +    return +  endif +  if a:all +    for lnum in range(1, line('$')) +      let l:line = getline(lnum) +      let l:end = col([lnum, '$']) - 1 +      if l:end > 0 && l:line =~# '\s$' && !s:InLiteral(lnum, l:end) +        if a:alt +          call setline(lnum, substitute(l:line, '\S\@<=\s\s*$', '', '')) +        else +          call setline(lnum, substitute(l:line, '\s\+$', '', '')) +        endif +      endif +    endfor +  else +    let l:lnum = line('.') +    let l:end = col('$') - 1 +    let l:line = getline(l:lnum) +    if l:line =~# '\s$' && !s:InLiteral(l:lnum, l:end) +      if a:alt +        call setline(l:lnum, substitute(l:line, '\s\+$', '', '')) +      else +        call setline(l:lnum, substitute(l:line, '\S\@<=\s\s*$', '', '')) +      endif +    endif +  endif +endfunction + + +let &cpo = s:cpo_save +unlet s:cpo_save + +endif | 
