diff runtime/indent/erlang.vim @ 48:67300faee616 v7-3-618

v7-3-618
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Wed, 01 Aug 2012 18:08:28 +0900
parents db46d51a3939
children
line wrap: on
line diff
--- a/runtime/indent/erlang.vim	Wed Aug 01 18:03:06 2012 +0900
+++ b/runtime/indent/erlang.vim	Wed Aug 01 18:08:28 2012 +0900
@@ -1,128 +1,144 @@
 " Vim indent file
 " Language:     Erlang
-" Maintainer:   Csaba Hoch <csaba.hoch@gmail.com>
-" Contributor:  Edwin Fine <efine145_nospam01 at usa dot net>
-" Last Change:  2008 Mar 12
+" Author:       Csaba Hoch <csaba.hoch@gmail.com>
+" Contributors: Edwin Fine <efine145_nospam01 at usa dot net>
+"               Pawel 'kTT' Salata <rockplayer.pl@gmail.com>
+"               Ricardo Catalinas Jiménez <jimenezrick@gmail.com>
+" License:      Vim license
+" Version:      2011/09/06
 
-" Only load this indent file when no other was loaded.
+" Only load this indent file when no other was loaded
 if exists("b:did_indent")
-  finish
+    finish
+else
+    let b:did_indent = 1
 endif
-let b:did_indent = 1
 
 setlocal indentexpr=ErlangIndent()
 setlocal indentkeys+==after,=end,=catch,=),=],=}
 
-" Only define the functions once.
+" Only define the functions once
 if exists("*ErlangIndent")
-   finish
+    finish
 endif
 
-" The function go through the whole line, analyses it and sets the indentation
-" (ind variable).
-" l: the number of the line to be examined.
-function s:ErlangIndentAtferLine(l)
-    let i = 0 " the index of the current character in the line
-    let length = strlen(a:l) " the length of the line
+" The function goes through the whole line, analyses it and returns the
+" indentation level.
+"
+" line: the line to be examined
+" return: the indentation level of the examined line
+function s:ErlangIndentAfterLine(line)
+    let linelen = strlen(a:line) " the length of the line
+    let i       = 0 " the index of the current character in the line
     let ind = 0 " how much should be the difference between the indentation of
                 " the current line and the indentation of the next line?
                 " e.g. +1: the indentation of the next line should be equal to
                 " the indentation of the current line plus one shiftwidth
-    let lastFun = 0 " the last token was a 'fun'
-    let lastReceive = 0 " the last token was a 'receive'; needed for 'after'
-    let lastHashMark = 0 " the last token was a 'hashmark'
+    let last_fun      = 0 " the last token was a 'fun'
+    let last_receive  = 0 " the last token was a 'receive'; needed for 'after'
+    let last_hash_sym = 0 " the last token was a '#'
+
+    " Ignore comments
+    if a:line =~# '^\s*%'
+        return 0
+    endif
 
-    while 0<= i && i < length
+    " Partial function head where the guard is missing
+    if a:line =~# "\\(^\\l[[:alnum:]_]*\\)\\|\\(^'[^']\\+'\\)(" && a:line !~# '->'
+        return 2
+    endif
 
+    " The missing guard from the split function head
+    if a:line =~# '^\s*when\s\+.*->'
+        return -1
+    endif
+
+    while 0<=i && i<linelen
         " m: the next value of the i
-        if a:l[i] == '%'
-            break
-        elseif a:l[i] == '"'
-            let m = matchend(a:l,'"\%([^"\\]\|\\.\)*"',i)
-            let lastReceive = 0
-        elseif a:l[i] == "'"
-            let m = matchend(a:l,"'[^']*'",i)
-            let lastReceive = 0
-        elseif a:l[i] =~# "[a-z]"
-            let m = matchend(a:l,".[[:alnum:]_]*",i)
-            if lastFun
+        if a:line[i] == '"'
+            let m = matchend(a:line,'"\%([^"\\]\|\\.\)*"',i)
+            let last_receive = 0
+        elseif a:line[i] == "'"
+            let m = matchend(a:line,"'[^']*'",i)
+            let last_receive = 0
+        elseif a:line[i] =~# "[a-z]"
+            let m = matchend(a:line,".[[:alnum:]_]*",i)
+            if last_fun
                 let ind = ind - 1
-                let lastFun = 0
-                let lastReceive = 0
-            elseif a:l[(i):(m-1)] =~# '^\%(case\|if\|try\)$'
+                let last_fun = 0
+                let last_receive = 0
+            elseif a:line[(i):(m-1)] =~# '^\%(case\|if\|try\)$'
                 let ind = ind + 1
-            elseif a:l[(i):(m-1)] =~# '^receive$'
+            elseif a:line[(i):(m-1)] =~# '^receive$'
                 let ind = ind + 1
-                let lastReceive = 1
-            elseif a:l[(i):(m-1)] =~# '^begin$'
+                let last_receive = 1
+            elseif a:line[(i):(m-1)] =~# '^begin$'
                 let ind = ind + 2
-                let lastReceive = 0
-            elseif a:l[(i):(m-1)] =~# '^end$'
+                let last_receive = 0
+            elseif a:line[(i):(m-1)] =~# '^end$'
                 let ind = ind - 2
-                let lastReceive = 0
-            elseif a:l[(i):(m-1)] =~# '^after$'
-                if lastReceive == 0
+                let last_receive = 0
+            elseif a:line[(i):(m-1)] =~# '^after$'
+                if last_receive == 0
                     let ind = ind - 1
                 else
                     let ind = ind + 0
-                end
-                let lastReceive = 0
-            elseif a:l[(i):(m-1)] =~# '^fun$'
+                endif
+                let last_receive = 0
+            elseif a:line[(i):(m-1)] =~# '^fun$'
                 let ind = ind + 1
-                let lastFun = 1
-                let lastReceive = 0
+                let last_fun = 1
+                let last_receive = 0
             endif
-        elseif a:l[i] =~# "[A-Z_]"
-            let m = matchend(a:l,".[[:alnum:]_]*",i)
-            let lastReceive = 0
-        elseif a:l[i] == '$'
+        elseif a:line[i] =~# "[A-Z_]"
+            let m = matchend(a:line,".[[:alnum:]_]*",i)
+            let last_receive = 0
+        elseif a:line[i] == '$'
             let m = i+2
-            let lastReceive = 0
-        elseif a:l[i] == "." && (i+1>=length || a:l[i+1]!~ "[0-9]")
+            let last_receive = 0
+        elseif a:line[i] == "." && (i+1>=linelen || a:line[i+1]!~ "[0-9]")
             let m = i+1
-            if lastHashMark
-                let lastHashMark = 0
+            if last_hash_sym
+                let last_hash_sym = 0
             else
                 let ind = ind - 1
-            end
-            let lastReceive = 0
-        elseif a:l[i] == '-' && (i+1<length && a:l[i+1]=='>')
+            endif
+            let last_receive = 0
+        elseif a:line[i] == '-' && (i+1<linelen && a:line[i+1]=='>')
             let m = i+2
             let ind = ind + 1
-            let lastReceive = 0
-        elseif a:l[i] == ';'
+            let last_receive = 0
+        elseif a:line[i] == ';' && a:line[(i):(linelen)] !~# '.*->.*'
             let m = i+1
             let ind = ind - 1
-            let lastReceive = 0
-        elseif a:l[i] == '#'
+            let last_receive = 0
+        elseif a:line[i] == '#'
             let m = i+1
-            let lastHashMark = 1
-        elseif a:l[i] =~# '[({[]'
+            let last_hash_sym = 1
+        elseif a:line[i] =~# '[({[]'
             let m = i+1
             let ind = ind + 1
-            let lastFun = 0
-            let lastReceive = 0
-            let lastHashMark = 0
-        elseif a:l[i] =~# '[)}\]]'
+            let last_fun = 0
+            let last_receive = 0
+            let last_hash_sym = 0
+        elseif a:line[i] =~# '[)}\]]'
             let m = i+1
             let ind = ind - 1
-            let lastReceive = 0
+            let last_receive = 0
         else
             let m = i+1
         endif
 
         let i = m
-
     endwhile
 
     return ind
-
 endfunction
 
 function s:FindPrevNonBlankNonComment(lnum)
     let lnum = prevnonblank(a:lnum)
     let line = getline(lnum)
-    " continue to search above if the current line begins with a '%'
+    " Continue to search above if the current line begins with a '%'
     while line =~# '^\s*%.*$'
         let lnum = prevnonblank(lnum - 1)
         if 0 == lnum
@@ -133,12 +149,20 @@
     return lnum
 endfunction
 
-function ErlangIndent()
+" The function returns the indentation level of the line adjusted to a mutiple
+" of 'shiftwidth' option.
+"
+" lnum: line number
+" return: the indentation level of the line
+function s:GetLineIndent(lnum)
+    return (indent(a:lnum) / &sw) * &sw
+endfunction
 
-    " Find a non-blank line above the current line.
+function ErlangIndent()
+    " Find a non-blank line above the current line
     let lnum = prevnonblank(v:lnum - 1)
 
-    " Hit the start of the file, use zero indent.
+    " Hit the start of the file, use zero indent
     if lnum == 0
         return 0
     endif
@@ -146,9 +170,14 @@
     let prevline = getline(lnum)
     let currline = getline(v:lnum)
 
-    let ind = indent(lnum) + &sw * s:ErlangIndentAtferLine(prevline)
+    let ind_after = s:ErlangIndentAfterLine(prevline)
+    if ind_after != 0
+        let ind = s:GetLineIndent(lnum) + ind_after * &sw
+    else
+        let ind = indent(lnum) + ind_after * &sw
+    endif
 
-    " special cases:
+    " Special cases:
     if prevline =~# '^\s*\%(after\|end\)\>'
         let ind = ind + 2*&sw
     endif
@@ -158,8 +187,8 @@
     if currline =~# '^\s*after\>'
         let plnum = s:FindPrevNonBlankNonComment(v:lnum-1)
         if getline(plnum) =~# '^[^%]*\<receive\>\s*\%(%.*\)\=$'
+            " If the 'receive' is not in the same line as the 'after'
             let ind = ind - 1*&sw
-            " If the 'receive' is not in the same line as the 'after'
         else
             let ind = ind - 2*&sw
         endif
@@ -181,26 +210,4 @@
         let ind = 0
     endif
     return ind
-
 endfunction
-
-" TODO:
-" 
-" f() ->
-"     x("foo
-"         bar")
-"         ,
-"         bad_indent.
-"
-" fun
-"     init/0,
-"     bad_indent
-"
-"     #rec
-"     .field,
-" bad_indent
-"
-" case X of
-"     1 when A; B ->
-"     bad_indent
-