blob: 30a0b478e28f160a0fcb967194d3e8436f8d3c08 [file] [log] [blame]
Bram Moolenaarfa13eef2013-02-06 17:34:04 +01001" Vim indent file
Bram Moolenaar942db232021-02-13 18:14:48 +01002" Language: Clojure
3" Maintainer: Alex Vear <av@axvr.io>
4" Former Maintainers: Sung Pae <self@sungpae.com>
5" Meikel Brandmeyer <mb@kotka.de>
6" URL: https://github.com/clojure-vim/clojure.vim
7" License: Vim (see :h license)
8" Last Change: 2021-02-13
Bram Moolenaarbaca7f72013-09-22 14:42:24 +02009
Bram Moolenaarfa13eef2013-02-06 17:34:04 +010010if exists("b:did_indent")
Bram Moolenaarbaca7f72013-09-22 14:42:24 +020011 finish
Bram Moolenaarfa13eef2013-02-06 17:34:04 +010012endif
13let b:did_indent = 1
14
15let s:save_cpo = &cpo
16set cpo&vim
17
Bram Moolenaara6878372014-03-22 21:02:50 +010018let b:undo_indent = 'setlocal autoindent< smartindent< expandtab< softtabstop< shiftwidth< indentexpr< indentkeys<'
Bram Moolenaarfa13eef2013-02-06 17:34:04 +010019
20setlocal noautoindent nosmartindent
21setlocal softtabstop=2 shiftwidth=2 expandtab
22setlocal indentkeys=!,o,O
23
24if exists("*searchpairpos")
25
Bram Moolenaarbaca7f72013-09-22 14:42:24 +020026 if !exists('g:clojure_maxlines')
27 let g:clojure_maxlines = 100
28 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +010029
Bram Moolenaarbaca7f72013-09-22 14:42:24 +020030 if !exists('g:clojure_fuzzy_indent')
31 let g:clojure_fuzzy_indent = 1
32 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +010033
Bram Moolenaarbaca7f72013-09-22 14:42:24 +020034 if !exists('g:clojure_fuzzy_indent_patterns')
35 let g:clojure_fuzzy_indent_patterns = ['^with', '^def', '^let']
36 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +010037
Bram Moolenaarbaca7f72013-09-22 14:42:24 +020038 if !exists('g:clojure_fuzzy_indent_blacklist')
39 let g:clojure_fuzzy_indent_blacklist = ['-fn$', '\v^with-%(meta|out-str|loading-context)$']
40 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +010041
Bram Moolenaarbaca7f72013-09-22 14:42:24 +020042 if !exists('g:clojure_special_indent_words')
43 let g:clojure_special_indent_words = 'deftype,defrecord,reify,proxy,extend-type,extend-protocol,letfn'
44 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +010045
Bram Moolenaarbaca7f72013-09-22 14:42:24 +020046 if !exists('g:clojure_align_multiline_strings')
47 let g:clojure_align_multiline_strings = 0
48 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +010049
Bram Moolenaar438f67a2014-01-07 06:09:28 +010050 if !exists('g:clojure_align_subforms')
51 let g:clojure_align_subforms = 0
52 endif
53
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +020054 function! s:syn_id_name()
Bram Moolenaarbaca7f72013-09-22 14:42:24 +020055 return synIDattr(synID(line("."), col("."), 0), "name")
56 endfunction
Bram Moolenaarfa13eef2013-02-06 17:34:04 +010057
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +020058 function! s:ignored_region()
59 return s:syn_id_name() =~? '\vstring|regex|comment|character'
60 endfunction
61
62 function! s:current_char()
Bram Moolenaarbaca7f72013-09-22 14:42:24 +020063 return getline('.')[col('.')-1]
64 endfunction
Bram Moolenaarfa13eef2013-02-06 17:34:04 +010065
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +020066 function! s:current_word()
Bram Moolenaarbaca7f72013-09-22 14:42:24 +020067 return getline('.')[col('.')-1 : searchpos('\v>', 'n', line('.'))[1]-2]
68 endfunction
Bram Moolenaarfa13eef2013-02-06 17:34:04 +010069
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +020070 function! s:is_paren()
71 return s:current_char() =~# '\v[\(\)\[\]\{\}]' && !s:ignored_region()
Bram Moolenaarbaca7f72013-09-22 14:42:24 +020072 endfunction
Bram Moolenaarfa13eef2013-02-06 17:34:04 +010073
Bram Moolenaarbaca7f72013-09-22 14:42:24 +020074 " Returns 1 if string matches a pattern in 'patterns', which may be a
75 " list of patterns, or a comma-delimited string of implicitly anchored
76 " patterns.
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +020077 function! s:match_one(patterns, string)
Bram Moolenaarbaca7f72013-09-22 14:42:24 +020078 let list = type(a:patterns) == type([])
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +020079 \ ? a:patterns
80 \ : map(split(a:patterns, ','), '"^" . v:val . "$"')
Bram Moolenaarbaca7f72013-09-22 14:42:24 +020081 for pat in list
Bram Moolenaar76f3b1a2014-03-27 22:30:07 +010082 if a:string =~# pat | return 1 | endif
Bram Moolenaarbaca7f72013-09-22 14:42:24 +020083 endfor
84 endfunction
Bram Moolenaarfa13eef2013-02-06 17:34:04 +010085
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +020086 function! s:match_pairs(open, close, stopat)
Bram Moolenaarbaca7f72013-09-22 14:42:24 +020087 " Stop only on vector and map [ resp. {. Ignore the ones in strings and
88 " comments.
Bram Moolenaar942db232021-02-13 18:14:48 +010089 if a:stopat == 0 && g:clojure_maxlines > 0
Bram Moolenaarbaca7f72013-09-22 14:42:24 +020090 let stopat = max([line(".") - g:clojure_maxlines, 0])
91 else
92 let stopat = a:stopat
93 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +010094
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +020095 let pos = searchpairpos(a:open, '', a:close, 'bWn', "!s:is_paren()", stopat)
96 return [pos[0], col(pos)]
Bram Moolenaarbaca7f72013-09-22 14:42:24 +020097 endfunction
Bram Moolenaarfa13eef2013-02-06 17:34:04 +010098
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +020099 function! s:clojure_check_for_string_worker()
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200100 " Check whether there is the last character of the previous line is
101 " highlighted as a string. If so, we check whether it's a ". In this
102 " case we have to check also the previous character. The " might be the
103 " closing one. In case the we are still in the string, we search for the
104 " opening ". If this is not found we take the indent of the line.
105 let nb = prevnonblank(v:lnum - 1)
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100106
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200107 if nb == 0
108 return -1
109 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100110
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200111 call cursor(nb, 0)
112 call cursor(0, col("$") - 1)
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200113 if s:syn_id_name() !~? "string"
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200114 return -1
115 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100116
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200117 " This will not work for a " in the first column...
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200118 if s:current_char() == '"'
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200119 call cursor(0, col("$") - 2)
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200120 if s:syn_id_name() !~? "string"
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200121 return -1
122 endif
Bram Moolenaar942db232021-02-13 18:14:48 +0100123 if s:current_char() != '\'
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200124 return -1
125 endif
126 call cursor(0, col("$") - 1)
127 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100128
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200129 let p = searchpos('\(^\|[^\\]\)\zs"', 'bW')
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100130
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200131 if p != [0, 0]
132 return p[1] - 1
133 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100134
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200135 return indent(".")
136 endfunction
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100137
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200138 function! s:check_for_string()
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200139 let pos = getpos('.')
140 try
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200141 let val = s:clojure_check_for_string_worker()
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200142 finally
143 call setpos('.', pos)
144 endtry
145 return val
146 endfunction
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100147
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200148 function! s:strip_namespace_and_macro_chars(word)
Bram Moolenaar76f3b1a2014-03-27 22:30:07 +0100149 return substitute(a:word, "\\v%(.*/|[#'`~@^,]*)(.*)", '\1', '')
150 endfunction
151
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200152 function! s:clojure_is_method_special_case_worker(position)
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200153 " Find the next enclosing form.
154 call search('\S', 'Wb')
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100155
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200156 " Special case: we are at a '(('.
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200157 if s:current_char() == '('
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200158 return 0
159 endif
160 call cursor(a:position)
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100161
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200162 let next_paren = s:match_pairs('(', ')', 0)
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100163
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200164 " Special case: we are now at toplevel.
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200165 if next_paren == [0, 0]
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200166 return 0
167 endif
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200168 call cursor(next_paren)
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100169
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200170 call search('\S', 'W')
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200171 let w = s:strip_namespace_and_macro_chars(s:current_word())
Bram Moolenaar942db232021-02-13 18:14:48 +0100172
Bram Moolenaar76f3b1a2014-03-27 22:30:07 +0100173 if g:clojure_special_indent_words =~# '\V\<' . w . '\>'
Bram Moolenaar942db232021-02-13 18:14:48 +0100174
175 " `letfn` is a special-special-case.
176 if w ==# 'letfn'
177 " Earlier code left the cursor at:
178 " (letfn [...] ...)
179 " ^
180
181 " Search and get coordinates of first `[`
182 " (letfn [...] ...)
183 " ^
184 call search('\[', 'W')
185 let pos = getcurpos()
186 let letfn_bracket = [pos[1], pos[2]]
187
188 " Move cursor to start of the form this function was
189 " initially called on. Grab the coordinates of the
190 " closest outer `[`.
191 call cursor(a:position)
192 let outer_bracket = s:match_pairs('\[', '\]', 0)
193
194 " If the located square brackets are not the same,
195 " don't use special-case formatting.
196 if outer_bracket != letfn_bracket
197 return 0
198 endif
199 endif
200
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200201 return 1
202 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100203
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200204 return 0
205 endfunction
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100206
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200207 function! s:is_method_special_case(position)
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200208 let pos = getpos('.')
209 try
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200210 let val = s:clojure_is_method_special_case_worker(a:position)
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200211 finally
212 call setpos('.', pos)
213 endtry
214 return val
215 endfunction
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100216
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200217 " Check if form is a reader conditional, that is, it is prefixed by #?
218 " or @#?
219 function! s:is_reader_conditional_special_case(position)
Bram Moolenaar942db232021-02-13 18:14:48 +0100220 return getline(a:position[0])[a:position[1] - 3 : a:position[1] - 2] == "#?"
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200221 endfunction
222
223 " Returns 1 for opening brackets, -1 for _anything else_.
224 function! s:bracket_type(char)
225 return stridx('([{', a:char) > -1 ? 1 : -1
226 endfunction
227
228 " Returns: [opening-bracket-lnum, indent]
229 function! s:clojure_indent_pos()
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200230 " Get rid of special case.
231 if line(".") == 1
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200232 return [0, 0]
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200233 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100234
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200235 " We have to apply some heuristics here to figure out, whether to use
236 " normal lisp indenting or not.
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200237 let i = s:check_for_string()
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200238 if i > -1
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200239 return [0, i + !!g:clojure_align_multiline_strings]
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200240 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100241
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200242 call cursor(0, 1)
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100243
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200244 " Find the next enclosing [ or {. We can limit the second search
245 " to the line, where the [ was found. If no [ was there this is
246 " zero and we search for an enclosing {.
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200247 let paren = s:match_pairs('(', ')', 0)
248 let bracket = s:match_pairs('\[', '\]', paren[0])
249 let curly = s:match_pairs('{', '}', bracket[0])
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100250
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200251 " In case the curly brace is on a line later then the [ or - in
252 " case they are on the same line - in a higher column, we take the
253 " curly indent.
254 if curly[0] > bracket[0] || curly[1] > bracket[1]
255 if curly[0] > paren[0] || curly[1] > paren[1]
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200256 return curly
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200257 endif
258 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100259
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200260 " If the curly was not chosen, we take the bracket indent - if
261 " there was one.
262 if bracket[0] > paren[0] || bracket[1] > paren[1]
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200263 return bracket
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200264 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100265
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200266 " There are neither { nor [ nor (, ie. we are at the toplevel.
267 if paren == [0, 0]
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200268 return paren
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200269 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100270
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200271 " Now we have to reimplement lispindent. This is surprisingly easy, as
272 " soon as one has access to syntax items.
273 "
274 " - Check whether we are in a special position after a word in
275 " g:clojure_special_indent_words. These are special cases.
276 " - Get the next keyword after the (.
277 " - If its first character is also a (, we have another sexp and align
278 " one column to the right of the unmatched (.
279 " - In case it is in lispwords, we indent the next line to the column of
280 " the ( + sw.
281 " - If not, we check whether it is last word in the line. In that case
282 " we again use ( + sw for indent.
283 " - In any other case we use the column of the end of the word + 2.
284 call cursor(paren)
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100285
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200286 if s:is_method_special_case(paren)
Bram Moolenaar942db232021-02-13 18:14:48 +0100287 return [paren[0], paren[1] + &shiftwidth - 1]
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200288 endif
289
290 if s:is_reader_conditional_special_case(paren)
291 return paren
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200292 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100293
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200294 " In case we are at the last character, we use the paren position.
295 if col("$") - 1 == paren[1]
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200296 return paren
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200297 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100298
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200299 " In case after the paren is a whitespace, we search for the next word.
300 call cursor(0, col('.') + 1)
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200301 if s:current_char() == ' '
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200302 call search('\v\S', 'W')
303 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100304
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200305 " If we moved to another line, there is no word after the (. We
306 " use the ( position for indent.
307 if line(".") > paren[0]
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200308 return paren
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200309 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100310
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200311 " We still have to check, whether the keyword starts with a (, [ or {.
312 " In that case we use the ( position for indent.
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200313 let w = s:current_word()
314 if s:bracket_type(w[0]) == 1
315 return paren
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200316 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100317
Bram Moolenaar942db232021-02-13 18:14:48 +0100318 " If the keyword begins with #, check if it is an anonymous
319 " function or set, in which case we indent by the shiftwidth
320 " (minus one if g:clojure_align_subforms = 1), or if it is
321 " ignored, in which case we use the ( position for indent.
322 if w[0] == "#"
323 " TODO: Handle #=() and other rare reader invocations?
324 if w[1] == '(' || w[1] == '{'
325 return [paren[0], paren[1] + (g:clojure_align_subforms ? 0 : &shiftwidth - 1)]
326 elseif w[1] == '_'
327 return paren
328 endif
329 endif
330
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200331 " Test words without namespace qualifiers and leading reader macro
332 " metacharacters.
333 "
334 " e.g. clojure.core/defn and #'defn should both indent like defn.
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200335 let ww = s:strip_namespace_and_macro_chars(w)
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100336
Bram Moolenaar76f3b1a2014-03-27 22:30:07 +0100337 if &lispwords =~# '\V\<' . ww . '\>'
Bram Moolenaar942db232021-02-13 18:14:48 +0100338 return [paren[0], paren[1] + &shiftwidth - 1]
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200339 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100340
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200341 if g:clojure_fuzzy_indent
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200342 \ && !s:match_one(g:clojure_fuzzy_indent_blacklist, ww)
343 \ && s:match_one(g:clojure_fuzzy_indent_patterns, ww)
Bram Moolenaar942db232021-02-13 18:14:48 +0100344 return [paren[0], paren[1] + &shiftwidth - 1]
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200345 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100346
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200347 call search('\v\_s', 'cW')
348 call search('\v\S', 'W')
349 if paren[0] < line(".")
Bram Moolenaar942db232021-02-13 18:14:48 +0100350 return [paren[0], paren[1] + (g:clojure_align_subforms ? 0 : &shiftwidth - 1)]
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200351 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100352
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200353 call search('\v\S', 'bW')
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200354 return [line('.'), col('.') + 1]
355 endfunction
356
357 function! GetClojureIndent()
358 let lnum = line('.')
359 let orig_lnum = lnum
360 let orig_col = col('.')
361 let [opening_lnum, indent] = s:clojure_indent_pos()
362
363 " Account for multibyte characters
364 if opening_lnum > 0
365 let indent -= indent - virtcol([opening_lnum, indent])
366 endif
367
368 " Return if there are no previous lines to inherit from
369 if opening_lnum < 1 || opening_lnum >= lnum - 1
370 call cursor(orig_lnum, orig_col)
371 return indent
372 endif
373
374 let bracket_count = 0
375
376 " Take the indent of the first previous non-white line that is
377 " at the same sexp level. cf. src/misc1.c:get_lisp_indent()
378 while 1
379 let lnum = prevnonblank(lnum - 1)
380 let col = 1
381
382 if lnum <= opening_lnum
383 break
384 endif
385
386 call cursor(lnum, col)
387
388 " Handle bracket counting edge case
389 if s:is_paren()
390 let bracket_count += s:bracket_type(s:current_char())
391 endif
392
393 while 1
394 if search('\v[(\[{}\])]', '', lnum) < 1
395 break
396 elseif !s:ignored_region()
397 let bracket_count += s:bracket_type(s:current_char())
398 endif
399 endwhile
400
401 if bracket_count == 0
402 " Check if this is part of a multiline string
403 call cursor(lnum, 1)
404 if s:syn_id_name() !~? '\vstring|regex'
405 call cursor(orig_lnum, orig_col)
406 return indent(lnum)
407 endif
408 endif
409 endwhile
410
411 call cursor(orig_lnum, orig_col)
412 return indent
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200413 endfunction
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100414
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200415 setlocal indentexpr=GetClojureIndent()
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100416
417else
418
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200419 " In case we have searchpairpos not available we fall back to
420 " normal lisp indenting.
421 setlocal indentexpr=
422 setlocal lisp
423 let b:undo_indent .= '| setlocal lisp<'
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100424
425endif
426
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100427let &cpo = s:save_cpo
428unlet! s:save_cpo
429
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200430" vim:sts=8:sw=8:ts=8:noet