Mercurial > vim
annotate runtime/indent/ocaml.vim @ 33939:880988084f3c
Added tag v9.0.2165 for changeset ed2267e507ff2b45e7a527f0eb93835d0aa71e41
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Thu, 14 Dec 2023 20:30:05 +0100 |
parents | 5c220cf30f1f |
children | 7270e1122962 |
rev | line source |
---|---|
7 | 1 " Vim indent file |
20 | 2 " Language: OCaml |
3312 | 3 " Maintainers: Jean-Francois Yuen <jfyuen@happycoders.org> |
4 " Mike Leary <leary@nwlink.com> | |
5 " Markus Mottl <markus.mottl@gmail.com> | |
23466 | 6 " URL: https://github.com/ocaml/vim-ocaml |
33052
5c220cf30f1f
runtime: Set b:undo_indent where missing (#12944)
Christian Brabandt <cb@256bit.org>
parents:
23466
diff
changeset
|
7 " Last Change: 2023 Aug 28 - Add undo_indent (Vim Project) |
5c220cf30f1f
runtime: Set b:undo_indent where missing (#12944)
Christian Brabandt <cb@256bit.org>
parents:
23466
diff
changeset
|
8 " 2017 Jun 13 |
3312 | 9 " 2005 Jun 25 - Fixed multiple bugs due to 'else\nreturn ind' working |
10 " 2005 May 09 - Added an option to not indent OCaml-indents specially (MM) | |
5055 | 11 " 2013 June - commented textwidth (Marc Weber) |
12 " | |
13 " Marc Weber's comment: This file may contain a lot of (very custom) stuff | |
14 " which eventually should be moved somewhere else .. | |
7 | 15 |
16 " Only load this indent file when no other was loaded. | |
17 if exists("b:did_indent") | |
551 | 18 finish |
7 | 19 endif |
20 let b:did_indent = 1 | |
21 | |
22 setlocal expandtab | |
23 setlocal indentexpr=GetOCamlIndent() | |
20 | 24 setlocal indentkeys+=0=and,0=class,0=constraint,0=done,0=else,0=end,0=exception,0=external,0=if,0=in,0=include,0=inherit,0=initializer,0=let,0=method,0=open,0=then,0=type,0=val,0=with,0;;,0>\],0\|\],0>},0\|,0},0\],0) |
7 | 25 setlocal nolisp |
26 setlocal nosmartindent | |
5055 | 27 |
33052
5c220cf30f1f
runtime: Set b:undo_indent where missing (#12944)
Christian Brabandt <cb@256bit.org>
parents:
23466
diff
changeset
|
28 let b:undo_indent = "setl et< inde< indk< lisp< si<" |
5c220cf30f1f
runtime: Set b:undo_indent where missing (#12944)
Christian Brabandt <cb@256bit.org>
parents:
23466
diff
changeset
|
29 |
5055 | 30 " At least Marc Weber and Markus Mottl do not like this: |
31 " setlocal textwidth=80 | |
7 | 32 |
33 " Comment formatting | |
551 | 34 if !exists("no_ocaml_comments") |
35 if (has("comments")) | |
23466 | 36 setlocal comments=sr:(*\ ,mb:\ ,ex:*) |
37 setlocal comments^=sr:(**,mb:\ \ ,ex:*) | |
551 | 38 setlocal fo=cqort |
39 endif | |
7 | 40 endif |
41 | |
42 " Only define the function once. | |
43 if exists("*GetOCamlIndent") | |
551 | 44 finish |
7 | 45 endif |
46 | |
47 " Define some patterns: | |
20 | 48 let s:beflet = '^\s*\(initializer\|method\|try\)\|\(\<\(begin\|do\|else\|in\|then\|try\)\|->\|<-\|=\|;\|(\)\s*$' |
7 | 49 let s:letpat = '^\s*\(let\|type\|module\|class\|open\|exception\|val\|include\|external\)\>' |
50 let s:letlim = '\(\<\(sig\|struct\)\|;;\)\s*$' | |
51 let s:lim = '^\s*\(exception\|external\|include\|let\|module\|open\|type\|val\)\>' | |
52 let s:module = '\<\%(begin\|sig\|struct\|object\)\>' | |
53 let s:obj = '^\s*\(constraint\|inherit\|initializer\|method\|val\)\>\|\<\(object\|object\s*(.*)\)\s*$' | |
20 | 54 let s:type = '^\s*\%(class\|let\|type\)\>.*=' |
7 | 55 |
56 " Skipping pattern, for comments | |
3312 | 57 function! s:GetLineWithoutFullComment(lnum) |
551 | 58 let lnum = prevnonblank(a:lnum - 1) |
59 let lline = substitute(getline(lnum), '(\*.*\*)\s*$', '', '') | |
60 while lline =~ '^\s*$' && lnum > 0 | |
61 let lnum = prevnonblank(lnum - 1) | |
62 let lline = substitute(getline(lnum), '(\*.*\*)\s*$', '', '') | |
63 endwhile | |
64 return lnum | |
7 | 65 endfunction |
66 | |
67 " Indent for ';;' to match multiple 'let' | |
3312 | 68 function! s:GetInd(lnum, pat, lim) |
551 | 69 let llet = search(a:pat, 'bW') |
70 let old = indent(a:lnum) | |
71 while llet > 0 | |
72 let old = indent(llet) | |
73 let nb = s:GetLineWithoutFullComment(llet) | |
74 if getline(nb) =~ a:lim | |
75 return old | |
76 endif | |
77 let llet = search(a:pat, 'bW') | |
78 endwhile | |
79 return old | |
7 | 80 endfunction |
81 | |
82 " Indent pairs | |
3312 | 83 function! s:FindPair(pstart, pmid, pend) |
551 | 84 call search(a:pend, 'bW') |
85 return indent(searchpair(a:pstart, a:pmid, a:pend, 'bWn', 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string\\|comment"')) | |
7 | 86 endfunction |
87 | |
88 " Indent 'let' | |
3312 | 89 function! s:FindLet(pstart, pmid, pend) |
551 | 90 call search(a:pend, 'bW') |
91 return indent(searchpair(a:pstart, a:pmid, a:pend, 'bWn', 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string\\|comment" || getline(".") =~ "^\\s*let\\>.*=.*\\<in\\s*$" || getline(prevnonblank(".") - 1) =~ s:beflet')) | |
7 | 92 endfunction |
93 | |
3312 | 94 function! GetOCamlIndent() |
551 | 95 " Find a non-commented line above the current line. |
96 let lnum = s:GetLineWithoutFullComment(v:lnum) | |
7 | 97 |
551 | 98 " At the start of the file use zero indent. |
99 if lnum == 0 | |
100 return 0 | |
101 endif | |
7 | 102 |
551 | 103 let ind = indent(lnum) |
104 let lline = substitute(getline(lnum), '(\*.*\*)\s*$', '', '') | |
7 | 105 |
551 | 106 " Return double 'shiftwidth' after lines matching: |
107 if lline =~ '^\s*|.*->\s*$' | |
11518 | 108 return ind + 2 * shiftwidth() |
551 | 109 endif |
7 | 110 |
551 | 111 let line = getline(v:lnum) |
7 | 112 |
551 | 113 " Indent if current line begins with 'end': |
114 if line =~ '^\s*end\>' | |
115 return s:FindPair(s:module, '','\<end\>') | |
7 | 116 |
551 | 117 " Indent if current line begins with 'done' for 'do': |
118 elseif line =~ '^\s*done\>' | |
119 return s:FindPair('\<do\>', '','\<done\>') | |
7 | 120 |
551 | 121 " Indent if current line begins with '}' or '>}': |
122 elseif line =~ '^\s*\(\|>\)}' | |
123 return s:FindPair('{', '','}') | |
7 | 124 |
551 | 125 " Indent if current line begins with ']', '|]' or '>]': |
126 elseif line =~ '^\s*\(\||\|>\)\]' | |
127 return s:FindPair('\[', '','\]') | |
7 | 128 |
551 | 129 " Indent if current line begins with ')': |
130 elseif line =~ '^\s*)' | |
131 return s:FindPair('(', '',')') | |
7 | 132 |
551 | 133 " Indent if current line begins with 'let': |
134 elseif line =~ '^\s*let\>' | |
135 if lline !~ s:lim . '\|' . s:letlim . '\|' . s:beflet | |
136 return s:FindLet(s:type, '','\<let\s*$') | |
137 endif | |
7 | 138 |
551 | 139 " Indent if current line begins with 'class' or 'type': |
140 elseif line =~ '^\s*\(class\|type\)\>' | |
141 if lline !~ s:lim . '\|\<and\s*$\|' . s:letlim | |
142 return s:FindLet(s:type, '','\<\(class\|type\)\s*$') | |
143 endif | |
7 | 144 |
551 | 145 " Indent for pattern matching: |
146 elseif line =~ '^\s*|' | |
147 if lline !~ '^\s*\(|[^\]]\|\(match\|type\|with\)\>\)\|\<\(function\|parser\|private\|with\)\s*$' | |
148 call search('|', 'bW') | |
149 return indent(searchpair('^\s*\(match\|type\)\>\|\<\(function\|parser\|private\|with\)\s*$', '', '^\s*|', 'bWn', 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string\\|comment" || getline(".") !~ "^\\s*|.*->"')) | |
150 endif | |
7 | 151 |
551 | 152 " Indent if current line begins with ';;': |
153 elseif line =~ '^\s*;;' | |
154 if lline !~ ';;\s*$' | |
155 return s:GetInd(v:lnum, s:letpat, s:letlim) | |
156 endif | |
7 | 157 |
551 | 158 " Indent if current line begins with 'in': |
159 elseif line =~ '^\s*in\>' | |
160 if lline !~ '^\s*\(let\|and\)\>' | |
161 return s:FindPair('\<let\>', '', '\<in\>') | |
162 endif | |
7 | 163 |
551 | 164 " Indent if current line begins with 'else': |
165 elseif line =~ '^\s*else\>' | |
166 if lline !~ '^\s*\(if\|then\)\>' | |
167 return s:FindPair('\<if\>', '', '\<else\>') | |
168 endif | |
7 | 169 |
551 | 170 " Indent if current line begins with 'then': |
171 elseif line =~ '^\s*then\>' | |
172 if lline !~ '^\s*\(if\|else\)\>' | |
173 return s:FindPair('\<if\>', '', '\<then\>') | |
174 endif | |
7 | 175 |
551 | 176 " Indent if current line begins with 'and': |
177 elseif line =~ '^\s*and\>' | |
178 if lline !~ '^\s*\(and\|let\|type\)\>\|\<end\s*$' | |
11518 | 179 return ind - shiftwidth() |
551 | 180 endif |
7 | 181 |
551 | 182 " Indent if current line begins with 'with': |
183 elseif line =~ '^\s*with\>' | |
184 if lline !~ '^\s*\(match\|try\)\>' | |
185 return s:FindPair('\<\%(match\|try\)\>', '','\<with\>') | |
186 endif | |
7 | 187 |
551 | 188 " Indent if current line begins with 'exception', 'external', 'include' or |
189 " 'open': | |
190 elseif line =~ '^\s*\(exception\|external\|include\|open\)\>' | |
191 if lline !~ s:lim . '\|' . s:letlim | |
192 call search(line) | |
193 return indent(search('^\s*\(\(exception\|external\|include\|open\|type\)\>\|val\>.*:\)', 'bW')) | |
194 endif | |
7 | 195 |
551 | 196 " Indent if current line begins with 'val': |
197 elseif line =~ '^\s*val\>' | |
198 if lline !~ '^\s*\(exception\|external\|include\|open\)\>\|' . s:obj . '\|' . s:letlim | |
199 return indent(search('^\s*\(\(exception\|include\|initializer\|method\|open\|type\|val\)\>\|external\>.*:\)', 'bW')) | |
200 endif | |
7 | 201 |
551 | 202 " Indent if current line begins with 'constraint', 'inherit', 'initializer' |
203 " or 'method': | |
204 elseif line =~ '^\s*\(constraint\|inherit\|initializer\|method\)\>' | |
205 if lline !~ s:obj | |
11518 | 206 return indent(search('\<\(object\|object\s*(.*)\)\s*$', 'bW')) + shiftwidth() |
551 | 207 endif |
208 | |
209 endif | |
210 | |
211 " Add a 'shiftwidth' after lines ending with: | |
212 if lline =~ '\(:\|=\|->\|<-\|(\|\[\|{\|{<\|\[|\|\[<\|\<\(begin\|do\|else\|fun\|function\|functor\|if\|initializer\|object\|parser\|private\|sig\|struct\|then\|try\)\|\<object\s*(.*)\)\s*$' | |
11518 | 213 let ind = ind + shiftwidth() |
7 | 214 |
551 | 215 " Back to normal indent after lines ending with ';;': |
216 elseif lline =~ ';;\s*$' && lline !~ '^\s*;;' | |
217 let ind = s:GetInd(v:lnum, s:letpat, s:letlim) | |
7 | 218 |
551 | 219 " Back to normal indent after lines ending with 'end': |
220 elseif lline =~ '\<end\s*$' | |
221 let ind = s:FindPair(s:module, '','\<end\>') | |
7 | 222 |
551 | 223 " Back to normal indent after lines ending with 'in': |
224 elseif lline =~ '\<in\s*$' && lline !~ '^\s*in\>' | |
225 let ind = s:FindPair('\<let\>', '', '\<in\>') | |
7 | 226 |
551 | 227 " Back to normal indent after lines ending with 'done': |
228 elseif lline =~ '\<done\s*$' | |
229 let ind = s:FindPair('\<do\>', '','\<done\>') | |
7 | 230 |
551 | 231 " Back to normal indent after lines ending with '}' or '>}': |
232 elseif lline =~ '\(\|>\)}\s*$' | |
233 let ind = s:FindPair('{', '','}') | |
7 | 234 |
551 | 235 " Back to normal indent after lines ending with ']', '|]' or '>]': |
236 elseif lline =~ '\(\||\|>\)\]\s*$' | |
237 let ind = s:FindPair('\[', '','\]') | |
7 | 238 |
551 | 239 " Back to normal indent after comments: |
240 elseif lline =~ '\*)\s*$' | |
241 call search('\*)', 'bW') | |
242 let ind = indent(searchpair('(\*', '', '\*)', 'bWn', 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string"')) | |
7 | 243 |
551 | 244 " Back to normal indent after lines ending with ')': |
245 elseif lline =~ ')\s*$' | |
246 let ind = s:FindPair('(', '',')') | |
7 | 247 |
551 | 248 " If this is a multiline comment then align '*': |
249 elseif lline =~ '^\s*(\*' && line =~ '^\s*\*' | |
250 let ind = ind + 1 | |
7 | 251 |
3312 | 252 else |
253 " Don't change indentation of this line | |
254 " for new lines (indent==0) use indentation of previous line | |
255 | |
256 " This is for preventing removing indentation of these args: | |
257 " let f x = | |
258 " let y = x + 1 in | |
259 " Printf.printf | |
260 " "o" << here | |
261 " "oeuth" << don't touch indentation | |
262 | |
263 let i = indent(v:lnum) | |
264 return i == 0 ? ind : i | |
265 | |
551 | 266 endif |
7 | 267 |
551 | 268 " Subtract a 'shiftwidth' after lines matching 'match ... with parser': |
269 if lline =~ '\<match\>.*\<with\>\s*\<parser\s*$' | |
11518 | 270 let ind = ind - shiftwidth() |
551 | 271 endif |
7 | 272 |
551 | 273 return ind |
7 | 274 |
275 endfunction | |
276 | |
277 " vim:sw=2 |