Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 1 | " Vim indent file |
| 2 | " Language: Erlang |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 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 |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 9 | |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 10 | " Only load this indent file when no other was loaded |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 11 | if exists("b:did_indent") |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 12 | finish |
| 13 | else |
| 14 | let b:did_indent = 1 |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 15 | endif |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 16 | |
| 17 | setlocal indentexpr=ErlangIndent() |
| 18 | setlocal indentkeys+==after,=end,=catch,=),=],=} |
| 19 | |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 20 | " Only define the functions once |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 21 | if exists("*ErlangIndent") |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 22 | finish |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 23 | endif |
| 24 | |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 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 |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 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 |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 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 '#' |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 40 | |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 41 | " Ignore comments |
| 42 | if a:line =~# '^\s*%' |
| 43 | return 0 |
| 44 | endif |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 45 | |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 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 |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 57 | " m: the next value of the i |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 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 |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 67 | let ind = ind - 1 |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 68 | let last_fun = 0 |
| 69 | let last_receive = 0 |
| 70 | elseif a:line[(i):(m-1)] =~# '^\%(case\|if\|try\)$' |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 71 | let ind = ind + 1 |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 72 | elseif a:line[(i):(m-1)] =~# '^receive$' |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 73 | let ind = ind + 1 |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 74 | let last_receive = 1 |
| 75 | elseif a:line[(i):(m-1)] =~# '^begin$' |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 76 | let ind = ind + 2 |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 77 | let last_receive = 0 |
| 78 | elseif a:line[(i):(m-1)] =~# '^end$' |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 79 | let ind = ind - 2 |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 80 | let last_receive = 0 |
| 81 | elseif a:line[(i):(m-1)] =~# '^after$' |
| 82 | if last_receive == 0 |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 83 | let ind = ind - 1 |
| 84 | else |
| 85 | let ind = ind + 0 |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 86 | endif |
| 87 | let last_receive = 0 |
| 88 | elseif a:line[(i):(m-1)] =~# '^fun$' |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 89 | let ind = ind + 1 |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 90 | let last_fun = 1 |
| 91 | let last_receive = 0 |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 92 | endif |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 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] == '$' |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 97 | let m = i+2 |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 98 | let last_receive = 0 |
| 99 | elseif a:line[i] == "." && (i+1>=linelen || a:line[i+1]!~ "[0-9]") |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 100 | let m = i+1 |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 101 | if last_hash_sym |
| 102 | let last_hash_sym = 0 |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 103 | else |
| 104 | let ind = ind - 1 |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 105 | endif |
| 106 | let last_receive = 0 |
| 107 | elseif a:line[i] == '-' && (i+1<linelen && a:line[i+1]=='>') |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 108 | let m = i+2 |
| 109 | let ind = ind + 1 |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 110 | let last_receive = 0 |
| 111 | elseif a:line[i] == ';' && a:line[(i):(linelen)] !~# '.*->.*' |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 112 | let m = i+1 |
| 113 | let ind = ind - 1 |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 114 | let last_receive = 0 |
| 115 | elseif a:line[i] == '#' |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 116 | let m = i+1 |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 117 | let last_hash_sym = 1 |
| 118 | elseif a:line[i] =~# '[({[]' |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 119 | let m = i+1 |
| 120 | let ind = ind + 1 |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 121 | let last_fun = 0 |
| 122 | let last_receive = 0 |
| 123 | let last_hash_sym = 0 |
| 124 | elseif a:line[i] =~# '[)}\]]' |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 125 | let m = i+1 |
| 126 | let ind = ind - 1 |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 127 | let last_receive = 0 |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 128 | else |
| 129 | let m = i+1 |
| 130 | endif |
| 131 | |
| 132 | let i = m |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 133 | endwhile |
| 134 | |
| 135 | return ind |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 136 | endfunction |
| 137 | |
| 138 | function s:FindPrevNonBlankNonComment(lnum) |
| 139 | let lnum = prevnonblank(a:lnum) |
| 140 | let line = getline(lnum) |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 141 | " Continue to search above if the current line begins with a '%' |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 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 | |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 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 |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 160 | |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 161 | function ErlangIndent() |
| 162 | " Find a non-blank line above the current line |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 163 | let lnum = prevnonblank(v:lnum - 1) |
| 164 | |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 165 | " Hit the start of the file, use zero indent |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 166 | if lnum == 0 |
| 167 | return 0 |
| 168 | endif |
| 169 | |
| 170 | let prevline = getline(lnum) |
| 171 | let currline = getline(v:lnum) |
| 172 | |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 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 |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 179 | |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 180 | " Special cases: |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 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*\%(%.*\)\=$' |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 190 | " If the 'receive' is not in the same line as the 'after' |
Bram Moolenaar | 6be7f87 | 2012-01-20 21:08:56 +0100 | [diff] [blame] | 191 | let ind = ind - 1*&sw |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 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 |
Bram Moolenaar | 3577c6f | 2008-06-24 21:16:56 +0000 | [diff] [blame] | 213 | endfunction |