home *** CD-ROM | disk | FTP | other *** search
/ vim.ftp.fu-berlin.de / 2015-02-03.vim.ftp.fu-berlin.de.tar / vim.ftp.fu-berlin.de / runtime / indent / erlang.vim < prev    next >
Encoding:
Text File  |  2012-05-31  |  6.4 KB  |  214 lines

  1. " Vim indent file
  2. " Language:     Erlang
  3. " Author:       Csaba Hoch <csaba.hoch@gmail.com>
  4. " Contributors: Edwin Fine <efine145_nospam01 at usa dot net>
  5. "               Pawel 'kTT' Salata <rockplayer.pl@gmail.com>
  6. "               Ricardo Catalinas Jim├⌐nez <jimenezrick@gmail.com>
  7. " License:      Vim license
  8. " Version:      2011/09/06
  9.  
  10. " Only load this indent file when no other was loaded
  11. if exists("b:did_indent")
  12.     finish
  13. else
  14.     let b:did_indent = 1
  15. endif
  16.  
  17. setlocal indentexpr=ErlangIndent()
  18. setlocal indentkeys+==after,=end,=catch,=),=],=}
  19.  
  20. " Only define the functions once
  21. if exists("*ErlangIndent")
  22.     finish
  23. endif
  24.  
  25. " The function goes through the whole line, analyses it and returns the
  26. " indentation level.
  27. "
  28. " line: the line to be examined
  29. " return: the indentation level of the examined line
  30. function s:ErlangIndentAfterLine(line)
  31.     let linelen = strlen(a:line) " the length of the line
  32.     let i       = 0 " the index of the current character in the line
  33.     let ind = 0 " how much should be the difference between the indentation of
  34.                 " the current line and the indentation of the next line?
  35.                 " e.g. +1: the indentation of the next line should be equal to
  36.                 " the indentation of the current line plus one shiftwidth
  37.     let last_fun      = 0 " the last token was a 'fun'
  38.     let last_receive  = 0 " the last token was a 'receive'; needed for 'after'
  39.     let last_hash_sym = 0 " the last token was a '#'
  40.  
  41.     " Ignore comments
  42.     if a:line =~# '^\s*%'
  43.         return 0
  44.     endif
  45.  
  46.     " Partial function head where the guard is missing
  47.     if a:line =~# "\\(^\\l[[:alnum:]_]*\\)\\|\\(^'[^']\\+'\\)(" && a:line !~# '->'
  48.         return 2
  49.     endif
  50.  
  51.     " The missing guard from the split function head
  52.     if a:line =~# '^\s*when\s\+.*->'
  53.         return -1
  54.     endif
  55.  
  56.     while 0<=i && i<linelen
  57.         " m: the next value of the i
  58.         if a:line[i] == '"'
  59.             let m = matchend(a:line,'"\%([^"\\]\|\\.\)*"',i)
  60.             let last_receive = 0
  61.         elseif a:line[i] == "'"
  62.             let m = matchend(a:line,"'[^']*'",i)
  63.             let last_receive = 0
  64.         elseif a:line[i] =~# "[a-z]"
  65.             let m = matchend(a:line,".[[:alnum:]_]*",i)
  66.             if last_fun
  67.                 let ind = ind - 1
  68.                 let last_fun = 0
  69.                 let last_receive = 0
  70.             elseif a:line[(i):(m-1)] =~# '^\%(case\|if\|try\)$'
  71.                 let ind = ind + 1
  72.             elseif a:line[(i):(m-1)] =~# '^receive$'
  73.                 let ind = ind + 1
  74.                 let last_receive = 1
  75.             elseif a:line[(i):(m-1)] =~# '^begin$'
  76.                 let ind = ind + 2
  77.                 let last_receive = 0
  78.             elseif a:line[(i):(m-1)] =~# '^end$'
  79.                 let ind = ind - 2
  80.                 let last_receive = 0
  81.             elseif a:line[(i):(m-1)] =~# '^after$'
  82.                 if last_receive == 0
  83.                     let ind = ind - 1
  84.                 else
  85.                     let ind = ind + 0
  86.                 endif
  87.                 let last_receive = 0
  88.             elseif a:line[(i):(m-1)] =~# '^fun$'
  89.                 let ind = ind + 1
  90.                 let last_fun = 1
  91.                 let last_receive = 0
  92.             endif
  93.         elseif a:line[i] =~# "[A-Z_]"
  94.             let m = matchend(a:line,".[[:alnum:]_]*",i)
  95.             let last_receive = 0
  96.         elseif a:line[i] == '$'
  97.             let m = i+2
  98.             let last_receive = 0
  99.         elseif a:line[i] == "." && (i+1>=linelen || a:line[i+1]!~ "[0-9]")
  100.             let m = i+1
  101.             if last_hash_sym
  102.                 let last_hash_sym = 0
  103.             else
  104.                 let ind = ind - 1
  105.             endif
  106.             let last_receive = 0
  107.         elseif a:line[i] == '-' && (i+1<linelen && a:line[i+1]=='>')
  108.             let m = i+2
  109.             let ind = ind + 1
  110.             let last_receive = 0
  111.         elseif a:line[i] == ';' && a:line[(i):(linelen)] !~# '.*->.*'
  112.             let m = i+1
  113.             let ind = ind - 1
  114.             let last_receive = 0
  115.         elseif a:line[i] == '#'
  116.             let m = i+1
  117.             let last_hash_sym = 1
  118.         elseif a:line[i] =~# '[({[]'
  119.             let m = i+1
  120.             let ind = ind + 1
  121.             let last_fun = 0
  122.             let last_receive = 0
  123.             let last_hash_sym = 0
  124.         elseif a:line[i] =~# '[)}\]]'
  125.             let m = i+1
  126.             let ind = ind - 1
  127.             let last_receive = 0
  128.         else
  129.             let m = i+1
  130.         endif
  131.  
  132.         let i = m
  133.     endwhile
  134.  
  135.     return ind
  136. endfunction
  137.  
  138. function s:FindPrevNonBlankNonComment(lnum)
  139.     let lnum = prevnonblank(a:lnum)
  140.     let line = getline(lnum)
  141.     " Continue to search above if the current line begins with a '%'
  142.     while line =~# '^\s*%.*$'
  143.         let lnum = prevnonblank(lnum - 1)
  144.         if 0 == lnum
  145.             return 0
  146.         endif
  147.         let line = getline(lnum)
  148.     endwhile
  149.     return lnum
  150. endfunction
  151.  
  152. " The function returns the indentation level of the line adjusted to a mutiple
  153. " of 'shiftwidth' option.
  154. "
  155. " lnum: line number
  156. " return: the indentation level of the line
  157. function s:GetLineIndent(lnum)
  158.     return (indent(a:lnum) / &sw) * &sw
  159. endfunction
  160.  
  161. function ErlangIndent()
  162.     " Find a non-blank line above the current line
  163.     let lnum = prevnonblank(v:lnum - 1)
  164.  
  165.     " Hit the start of the file, use zero indent
  166.     if lnum == 0
  167.         return 0
  168.     endif
  169.  
  170.     let prevline = getline(lnum)
  171.     let currline = getline(v:lnum)
  172.  
  173.     let ind_after = s:ErlangIndentAfterLine(prevline)
  174.     if ind_after != 0
  175.         let ind = s:GetLineIndent(lnum) + ind_after * &sw
  176.     else
  177.         let ind = indent(lnum) + ind_after * &sw
  178.     endif
  179.  
  180.     " Special cases:
  181.     if prevline =~# '^\s*\%(after\|end\)\>'
  182.         let ind = ind + 2*&sw
  183.     endif
  184.     if currline =~# '^\s*end\>'
  185.         let ind = ind - 2*&sw
  186.     endif
  187.     if currline =~# '^\s*after\>'
  188.         let plnum = s:FindPrevNonBlankNonComment(v:lnum-1)
  189.         if getline(plnum) =~# '^[^%]*\<receive\>\s*\%(%.*\)\=$'
  190.             " If the 'receive' is not in the same line as the 'after'
  191.             let ind = ind - 1*&sw
  192.         else
  193.             let ind = ind - 2*&sw
  194.         endif
  195.     endif
  196.     if prevline =~# '^\s*[)}\]]'
  197.         let ind = ind + 1*&sw
  198.     endif
  199.     if currline =~# '^\s*[)}\]]'
  200.         let ind = ind - 1*&sw
  201.     endif
  202.     if prevline =~# '^\s*\%(catch\)\s*\%(%\|$\)'
  203.         let ind = ind + 1*&sw
  204.     endif
  205.     if currline =~# '^\s*\%(catch\)\s*\%(%\|$\)'
  206.         let ind = ind - 1*&sw
  207.     endif
  208.  
  209.     if ind<0
  210.         let ind = 0
  211.     endif
  212.     return ind
  213. endfunction
  214.