summaryrefslogtreecommitdiffstats
path: root/indent/erlang.vim
diff options
context:
space:
mode:
authorAdam Stankiewicz <sheerun@sher.pl>2013-09-17 02:02:37 +0200
committerAdam Stankiewicz <sheerun@sher.pl>2013-09-17 02:02:37 +0200
commit0fcd056648da760f727a7296bae364ea5c4b5e98 (patch)
treeb935dab5daabd233312525d6a46d0b110c971803 /indent/erlang.vim
parent78cd7e48cb05e99fb2b87abcdc2255ac84d9833e (diff)
downloadvim-polyglot-0fcd056648da760f727a7296bae364ea5c4b5e98.tar.gz
vim-polyglot-0fcd056648da760f727a7296bae364ea5c4b5e98.zip
fix: Switch erlang to oscarh/vimerl (it doesnt use plugin dir)
Diffstat (limited to 'indent/erlang.vim')
-rw-r--r--indent/erlang.vim235
1 files changed, 192 insertions, 43 deletions
diff --git a/indent/erlang.vim b/indent/erlang.vim
index 370a8810..61833f74 100644
--- a/indent/erlang.vim
+++ b/indent/erlang.vim
@@ -1,58 +1,207 @@
" Vim indent file
-" Language: Erlang
-" Author: Ricardo Catalinas Jiménez <jimenezrick@gmail.com>
-" License: Vim license
-" Version: 2013/09/11
+" Language: Erlang
+" Maintainer: Csaba Hoch <csaba.hoch@gmail.com>
+" Contributor: Edwin Fine <efine145_nospam01 at usa dot net>
+" Contributor: Pawel 'kTT' Salata <rockplayer.pl@gmail.com>
+" Last Change: 2010 Aug 30
-if !exists('g:erlang_force_use_vimerl_indent')
- let g:erlang_force_use_vimerl_indent = 0
-endif
-
-if exists('b:did_indent') || (v:version >= 704 && !g:erlang_force_use_vimerl_indent)
- finish
-else
- let b:did_indent = 1
+" Only load this indent file when no other was loaded.
+if exists("b:did_indent")
+ finish
endif
+let b:did_indent = 1
setlocal indentexpr=ErlangIndent()
-setlocal indentkeys=!^F,o,O,=),=},=],=>>,=of,=catch,=after,=end
+setlocal indentkeys+==after,=end,=catch,=),=],=}
-if exists('*ErlangIndent')
- finish
+" Only define the functions once.
+if exists("*ErlangIndent")
+ finish
endif
-let s:erlang_indent_file = expand('<sfile>:p:h') . '/erlang_indent.erl'
-if filewritable(expand('<sfile>:p:h')) == 2
- let s:in_fifo = expand('<sfile>:p:h') . '/vimerl_in_fifo.' . getpid()
- let s:out_fifo = expand('<sfile>:p:h') . '/vimerl_out_fifo.' . getpid()
-else
- let s:in_fifo = '/tmp/vimerl_in_fifo.' . getpid()
- let s:out_fifo = '/tmp/vimerl_out_fifo.' . getpid()
-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:ErlangIndentAfterLine(l)
+ let i = 0 " the index of the current character in the line
+ let length = strlen(a:l) " the length of 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'
+
+ " ignore type annotation lines
+ if a:l =~# '^\s*-type'
+ return 0
+ endif
+
+ while 0<= i && i < length
-execute 'silent !mkfifo' s:in_fifo
-execute 'silent !mkfifo' s:out_fifo
-execute 'silent !' . s:erlang_indent_file s:out_fifo s:in_fifo '&'
+ " 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
+ let ind = ind - 1
+ let lastFun = 0
+ let lastReceive = 0
+ elseif a:l[(i):(m-1)] =~# '^\%(case\|if\|try\)$'
+ let ind = ind + 1
+ elseif a:l[(i):(m-1)] =~# '^receive$'
+ let ind = ind + 1
+ let lastReceive = 1
+ elseif a:l[(i):(m-1)] =~# '^begin$'
+ let ind = ind + 2
+ let lastReceive = 0
+ elseif a:l[(i):(m-1)] =~# '^end$'
+ let ind = ind - 2
+ let lastReceive = 0
+ elseif a:l[(i):(m-1)] =~# '^after$'
+ if lastReceive == 0
+ let ind = ind - 1
+ else
+ let ind = ind + 0
+ endif
+ let lastReceive = 0
+ elseif a:l[(i):(m-1)] =~# '^fun$'
+ let ind = ind + 1
+ let lastFun = 1
+ let lastReceive = 0
+ endif
+ elseif a:l[i] =~# "[A-Z_]"
+ let m = matchend(a:l,".[[:alnum:]_]*",i)
+ let lastReceive = 0
+ elseif a:l[i] == '$'
+ let m = i+2
+ let lastReceive = 0
+ elseif a:l[i] == "." && (i+1>=length || a:l[i+1]!~ "[0-9]")
+ let m = i+1
+ if lastHashMark
+ let lastHashMark = 0
+ else
+ let ind = ind - 1
+ endif
+ let lastReceive = 0
+ elseif a:l[i] == '-' && (i+1<length && a:l[i+1]=='>')
+ let m = i+2
+ let ind = ind + 1
+ let lastReceive = 0
+ elseif a:l[i] == ';' && a:l[(i):(length)] !~# '.*->.*'
+ let m = i+1
+ let ind = ind - 1
+ let lastReceive = 0
+ elseif a:l[i] == '#'
+ let m = i+1
+ let lastHashMark = 1
+ elseif a:l[i] =~# '[({[]'
+ let m = i+1
+ let ind = ind + 1
+ let lastFun = 0
+ let lastReceive = 0
+ let lastHashMark = 0
+ elseif a:l[i] =~# '[)}\]]'
+ let m = i+1
+ let ind = ind - 1
+ let lastReceive = 0
+ else
+ let m = i+1
+ endif
-autocmd VimLeave * call <SID>StopIndenter()
+ let i = m
+
+ endwhile
+
+ return ind
+
+endfunction
-function s:StopIndenter()
- call writefile([], s:out_fifo)
- call delete(s:in_fifo)
- call delete(s:out_fifo)
+function s:FindPrevNonBlankNonComment(lnum)
+ let lnum = prevnonblank(a:lnum)
+ let line = getline(lnum)
+ " continue to search above if the current line begins with a '%'
+ while line =~# '^\s*%.*$'
+ let lnum = prevnonblank(lnum - 1)
+ if 0 == lnum
+ return 0
+ endif
+ let line = getline(lnum)
+ endwhile
+ return lnum
endfunction
function ErlangIndent()
- if v:lnum == 1
- return 0
- else
- call writefile([v:lnum] + getline(1, v:lnum), s:out_fifo)
- let indent = split(readfile(s:in_fifo)[0])
-
- if len(indent) == 1 || !&expandtab
- return indent[0] * &shiftwidth
- else
- return indent[1]
- endif
- endif
+
+ " Find a non-blank line above the current line.
+ let lnum = prevnonblank(v:lnum - 1)
+
+ " Hit the start of the file, use zero indent.
+ if lnum == 0
+ return 0
+ endif
+
+ let prevline = getline(lnum)
+ let currline = getline(v:lnum)
+
+ let ind = indent(lnum) + &sw * s:ErlangIndentAfterLine(prevline)
+
+ " special cases:
+ if prevline =~# '^\s*\%(after\|end\)\>'
+ let ind = ind + 2*&sw
+ endif
+ if currline =~# '^\s*end\>'
+ let ind = ind - 2*&sw
+ endif
+ if currline =~# '^\s*after\>'
+ let plnum = s:FindPrevNonBlankNonComment(v:lnum-1)
+ if getline(plnum) =~# '^[^%]*\<receive\>\s*\%(%.*\)\=$'
+ let ind = ind - 1*&sw
+ " If the 'receive' is not in the same line as the 'after'
+ else
+ let ind = ind - 2*&sw
+ endif
+ endif
+ if prevline =~# '^\s*[)}\]]'
+ let ind = ind + 1*&sw
+ endif
+ if currline =~# '^\s*[)}\]]'
+ let ind = ind - 1*&sw
+ endif
+ if prevline =~# '^\s*\%(catch\)\s*\%(%\|$\)'
+ let ind = ind + 1*&sw
+ endif
+ if currline =~# '^\s*\%(catch\)\s*\%(%\|$\)'
+ let ind = ind - 1*&sw
+ endif
+
+ if ind<0
+ let ind = 0
+ endif
+ return ind
+
endfunction
+
+" TODO:
+"
+" f() ->
+" x("foo
+" bar")
+" ,
+" bad_indent.
+"
+" fun
+" init/0,
+" bad_indent
+"
+" #rec
+" .field,
+" bad_indent