blob: fadcaf4b4ae24d2e71e495364eabf8821245f8fa [file] [log] [blame]
Bram Moolenaarfa13eef2013-02-06 17:34:04 +01001" Vim indent file
Bram Moolenaar942db232021-02-13 18:14:48 +01002" Language: Clojure
Bram Moolenaar113cb512021-11-07 20:27:04 +00003" Maintainer: Alex Vear <alex@vear.uk>
Bram Moolenaar942db232021-02-13 18:14:48 +01004" 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)
Bram Moolenaar113cb512021-11-07 20:27:04 +00008" Last Change: 2021-10-26
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')
Bram Moolenaar113cb512021-11-07 20:27:04 +000027 let g:clojure_maxlines = 300
Bram Moolenaarbaca7f72013-09-22 14:42:24 +020028 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 Moolenaar113cb512021-11-07 20:27:04 +000074 " Returns 1 if string matches a pattern in 'patterns', which should be
75 " a list of patterns.
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +020076 function! s:match_one(patterns, string)
Bram Moolenaar113cb512021-11-07 20:27:04 +000077 for pat in a:patterns
Bram Moolenaar76f3b1a2014-03-27 22:30:07 +010078 if a:string =~# pat | return 1 | endif
Bram Moolenaarbaca7f72013-09-22 14:42:24 +020079 endfor
80 endfunction
Bram Moolenaarfa13eef2013-02-06 17:34:04 +010081
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +020082 function! s:match_pairs(open, close, stopat)
Bram Moolenaarbaca7f72013-09-22 14:42:24 +020083 " Stop only on vector and map [ resp. {. Ignore the ones in strings and
84 " comments.
Bram Moolenaar942db232021-02-13 18:14:48 +010085 if a:stopat == 0 && g:clojure_maxlines > 0
Bram Moolenaarbaca7f72013-09-22 14:42:24 +020086 let stopat = max([line(".") - g:clojure_maxlines, 0])
87 else
88 let stopat = a:stopat
89 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +010090
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +020091 let pos = searchpairpos(a:open, '', a:close, 'bWn', "!s:is_paren()", stopat)
92 return [pos[0], col(pos)]
Bram Moolenaarbaca7f72013-09-22 14:42:24 +020093 endfunction
Bram Moolenaarfa13eef2013-02-06 17:34:04 +010094
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +020095 function! s:clojure_check_for_string_worker()
Bram Moolenaarbaca7f72013-09-22 14:42:24 +020096 " Check whether there is the last character of the previous line is
97 " highlighted as a string. If so, we check whether it's a ". In this
98 " case we have to check also the previous character. The " might be the
99 " closing one. In case the we are still in the string, we search for the
100 " opening ". If this is not found we take the indent of the line.
101 let nb = prevnonblank(v:lnum - 1)
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100102
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200103 if nb == 0
104 return -1
105 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100106
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200107 call cursor(nb, 0)
108 call cursor(0, col("$") - 1)
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200109 if s:syn_id_name() !~? "string"
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200110 return -1
111 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100112
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200113 " This will not work for a " in the first column...
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200114 if s:current_char() == '"'
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200115 call cursor(0, col("$") - 2)
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200116 if s:syn_id_name() !~? "string"
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200117 return -1
118 endif
Bram Moolenaar942db232021-02-13 18:14:48 +0100119 if s:current_char() != '\'
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200120 return -1
121 endif
122 call cursor(0, col("$") - 1)
123 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100124
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200125 let p = searchpos('\(^\|[^\\]\)\zs"', 'bW')
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100126
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200127 if p != [0, 0]
128 return p[1] - 1
129 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100130
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200131 return indent(".")
132 endfunction
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100133
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200134 function! s:check_for_string()
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200135 let pos = getpos('.')
136 try
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200137 let val = s:clojure_check_for_string_worker()
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200138 finally
139 call setpos('.', pos)
140 endtry
141 return val
142 endfunction
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100143
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200144 function! s:strip_namespace_and_macro_chars(word)
Bram Moolenaar76f3b1a2014-03-27 22:30:07 +0100145 return substitute(a:word, "\\v%(.*/|[#'`~@^,]*)(.*)", '\1', '')
146 endfunction
147
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200148 function! s:clojure_is_method_special_case_worker(position)
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200149 " Find the next enclosing form.
150 call search('\S', 'Wb')
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100151
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200152 " Special case: we are at a '(('.
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200153 if s:current_char() == '('
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200154 return 0
155 endif
156 call cursor(a:position)
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100157
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200158 let next_paren = s:match_pairs('(', ')', 0)
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100159
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200160 " Special case: we are now at toplevel.
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200161 if next_paren == [0, 0]
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200162 return 0
163 endif
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200164 call cursor(next_paren)
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100165
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200166 call search('\S', 'W')
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200167 let w = s:strip_namespace_and_macro_chars(s:current_word())
Bram Moolenaar942db232021-02-13 18:14:48 +0100168
Bram Moolenaar76f3b1a2014-03-27 22:30:07 +0100169 if g:clojure_special_indent_words =~# '\V\<' . w . '\>'
Bram Moolenaar942db232021-02-13 18:14:48 +0100170
171 " `letfn` is a special-special-case.
172 if w ==# 'letfn'
173 " Earlier code left the cursor at:
174 " (letfn [...] ...)
175 " ^
176
177 " Search and get coordinates of first `[`
178 " (letfn [...] ...)
179 " ^
180 call search('\[', 'W')
181 let pos = getcurpos()
182 let letfn_bracket = [pos[1], pos[2]]
183
184 " Move cursor to start of the form this function was
185 " initially called on. Grab the coordinates of the
186 " closest outer `[`.
187 call cursor(a:position)
188 let outer_bracket = s:match_pairs('\[', '\]', 0)
189
190 " If the located square brackets are not the same,
191 " don't use special-case formatting.
192 if outer_bracket != letfn_bracket
193 return 0
194 endif
195 endif
196
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200197 return 1
198 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100199
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200200 return 0
201 endfunction
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100202
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200203 function! s:is_method_special_case(position)
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200204 let pos = getpos('.')
205 try
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200206 let val = s:clojure_is_method_special_case_worker(a:position)
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200207 finally
208 call setpos('.', pos)
209 endtry
210 return val
211 endfunction
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100212
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200213 " Check if form is a reader conditional, that is, it is prefixed by #?
Bram Moolenaar113cb512021-11-07 20:27:04 +0000214 " or #?@
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200215 function! s:is_reader_conditional_special_case(position)
Bram Moolenaar942db232021-02-13 18:14:48 +0100216 return getline(a:position[0])[a:position[1] - 3 : a:position[1] - 2] == "#?"
Bram Moolenaar113cb512021-11-07 20:27:04 +0000217 \|| getline(a:position[0])[a:position[1] - 4 : a:position[1] - 2] == "#?@"
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200218 endfunction
219
220 " Returns 1 for opening brackets, -1 for _anything else_.
221 function! s:bracket_type(char)
222 return stridx('([{', a:char) > -1 ? 1 : -1
223 endfunction
224
225 " Returns: [opening-bracket-lnum, indent]
226 function! s:clojure_indent_pos()
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200227 " Get rid of special case.
228 if line(".") == 1
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200229 return [0, 0]
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200230 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100231
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200232 " We have to apply some heuristics here to figure out, whether to use
233 " normal lisp indenting or not.
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200234 let i = s:check_for_string()
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200235 if i > -1
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200236 return [0, i + !!g:clojure_align_multiline_strings]
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200237 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100238
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200239 call cursor(0, 1)
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100240
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200241 " Find the next enclosing [ or {. We can limit the second search
242 " to the line, where the [ was found. If no [ was there this is
243 " zero and we search for an enclosing {.
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200244 let paren = s:match_pairs('(', ')', 0)
245 let bracket = s:match_pairs('\[', '\]', paren[0])
246 let curly = s:match_pairs('{', '}', bracket[0])
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100247
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200248 " In case the curly brace is on a line later then the [ or - in
249 " case they are on the same line - in a higher column, we take the
250 " curly indent.
251 if curly[0] > bracket[0] || curly[1] > bracket[1]
252 if curly[0] > paren[0] || curly[1] > paren[1]
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200253 return curly
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200254 endif
255 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100256
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200257 " If the curly was not chosen, we take the bracket indent - if
258 " there was one.
259 if bracket[0] > paren[0] || bracket[1] > paren[1]
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200260 return bracket
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200261 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100262
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200263 " There are neither { nor [ nor (, ie. we are at the toplevel.
264 if paren == [0, 0]
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200265 return paren
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200266 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100267
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200268 " Now we have to reimplement lispindent. This is surprisingly easy, as
269 " soon as one has access to syntax items.
270 "
271 " - Check whether we are in a special position after a word in
272 " g:clojure_special_indent_words. These are special cases.
273 " - Get the next keyword after the (.
274 " - If its first character is also a (, we have another sexp and align
275 " one column to the right of the unmatched (.
276 " - In case it is in lispwords, we indent the next line to the column of
277 " the ( + sw.
278 " - If not, we check whether it is last word in the line. In that case
279 " we again use ( + sw for indent.
280 " - In any other case we use the column of the end of the word + 2.
281 call cursor(paren)
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100282
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200283 if s:is_method_special_case(paren)
Bram Moolenaar942db232021-02-13 18:14:48 +0100284 return [paren[0], paren[1] + &shiftwidth - 1]
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200285 endif
286
287 if s:is_reader_conditional_special_case(paren)
288 return paren
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200289 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100290
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200291 " In case we are at the last character, we use the paren position.
292 if col("$") - 1 == paren[1]
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200293 return paren
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200294 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100295
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200296 " In case after the paren is a whitespace, we search for the next word.
297 call cursor(0, col('.') + 1)
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200298 if s:current_char() == ' '
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200299 call search('\v\S', 'W')
300 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100301
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200302 " If we moved to another line, there is no word after the (. We
303 " use the ( position for indent.
304 if line(".") > paren[0]
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200305 return paren
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200306 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100307
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200308 " We still have to check, whether the keyword starts with a (, [ or {.
309 " In that case we use the ( position for indent.
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200310 let w = s:current_word()
311 if s:bracket_type(w[0]) == 1
312 return paren
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200313 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100314
Bram Moolenaar942db232021-02-13 18:14:48 +0100315 " If the keyword begins with #, check if it is an anonymous
316 " function or set, in which case we indent by the shiftwidth
317 " (minus one if g:clojure_align_subforms = 1), or if it is
318 " ignored, in which case we use the ( position for indent.
319 if w[0] == "#"
320 " TODO: Handle #=() and other rare reader invocations?
321 if w[1] == '(' || w[1] == '{'
322 return [paren[0], paren[1] + (g:clojure_align_subforms ? 0 : &shiftwidth - 1)]
323 elseif w[1] == '_'
324 return paren
325 endif
326 endif
327
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200328 " Test words without namespace qualifiers and leading reader macro
329 " metacharacters.
330 "
331 " e.g. clojure.core/defn and #'defn should both indent like defn.
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200332 let ww = s:strip_namespace_and_macro_chars(w)
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100333
Bram Moolenaar76f3b1a2014-03-27 22:30:07 +0100334 if &lispwords =~# '\V\<' . ww . '\>'
Bram Moolenaar942db232021-02-13 18:14:48 +0100335 return [paren[0], paren[1] + &shiftwidth - 1]
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200336 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100337
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200338 if g:clojure_fuzzy_indent
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200339 \ && !s:match_one(g:clojure_fuzzy_indent_blacklist, ww)
340 \ && s:match_one(g:clojure_fuzzy_indent_patterns, ww)
Bram Moolenaar942db232021-02-13 18:14:48 +0100341 return [paren[0], paren[1] + &shiftwidth - 1]
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200342 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100343
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200344 call search('\v\_s', 'cW')
345 call search('\v\S', 'W')
346 if paren[0] < line(".")
Bram Moolenaar942db232021-02-13 18:14:48 +0100347 return [paren[0], paren[1] + (g:clojure_align_subforms ? 0 : &shiftwidth - 1)]
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200348 endif
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100349
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200350 call search('\v\S', 'bW')
Bram Moolenaar6f1d9a02016-07-24 14:12:38 +0200351 return [line('.'), col('.') + 1]
352 endfunction
353
354 function! GetClojureIndent()
355 let lnum = line('.')
356 let orig_lnum = lnum
357 let orig_col = col('.')
358 let [opening_lnum, indent] = s:clojure_indent_pos()
359
360 " Account for multibyte characters
361 if opening_lnum > 0
362 let indent -= indent - virtcol([opening_lnum, indent])
363 endif
364
365 " Return if there are no previous lines to inherit from
366 if opening_lnum < 1 || opening_lnum >= lnum - 1
367 call cursor(orig_lnum, orig_col)
368 return indent
369 endif
370
371 let bracket_count = 0
372
373 " Take the indent of the first previous non-white line that is
374 " at the same sexp level. cf. src/misc1.c:get_lisp_indent()
375 while 1
376 let lnum = prevnonblank(lnum - 1)
377 let col = 1
378
379 if lnum <= opening_lnum
380 break
381 endif
382
383 call cursor(lnum, col)
384
385 " Handle bracket counting edge case
386 if s:is_paren()
387 let bracket_count += s:bracket_type(s:current_char())
388 endif
389
390 while 1
391 if search('\v[(\[{}\])]', '', lnum) < 1
392 break
393 elseif !s:ignored_region()
394 let bracket_count += s:bracket_type(s:current_char())
395 endif
396 endwhile
397
398 if bracket_count == 0
399 " Check if this is part of a multiline string
400 call cursor(lnum, 1)
401 if s:syn_id_name() !~? '\vstring|regex'
402 call cursor(orig_lnum, orig_col)
403 return indent(lnum)
404 endif
405 endif
406 endwhile
407
408 call cursor(orig_lnum, orig_col)
409 return indent
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200410 endfunction
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100411
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200412 setlocal indentexpr=GetClojureIndent()
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100413
414else
415
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200416 " In case we have searchpairpos not available we fall back to
417 " normal lisp indenting.
418 setlocal indentexpr=
419 setlocal lisp
420 let b:undo_indent .= '| setlocal lisp<'
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100421
422endif
423
Bram Moolenaarfa13eef2013-02-06 17:34:04 +0100424let &cpo = s:save_cpo
425unlet! s:save_cpo
426
Bram Moolenaarbaca7f72013-09-22 14:42:24 +0200427" vim:sts=8:sw=8:ts=8:noet