xref: /vim-8.2.3635/runtime/indent/clojure.vim (revision 113cb513)
1fa13eef3SBram Moolenaar" Vim indent file
2fa13eef3SBram Moolenaar" Language:           Clojure
3*113cb513SBram Moolenaar" Maintainer:         Alex Vear <[email protected]>
4942db23cSBram Moolenaar" Former Maintainers: Sung Pae <[email protected]>
5942db23cSBram Moolenaar"                     Meikel Brandmeyer <[email protected]>
6942db23cSBram Moolenaar" URL:                https://github.com/clojure-vim/clojure.vim
7942db23cSBram Moolenaar" License:            Vim (see :h license)
8*113cb513SBram Moolenaar" Last Change:        2021-10-26
9baca7f70SBram Moolenaar
10fa13eef3SBram Moolenaarif exists("b:did_indent")
11fa13eef3SBram Moolenaar	finish
12fa13eef3SBram Moolenaarendif
13fa13eef3SBram Moolenaarlet b:did_indent = 1
14fa13eef3SBram Moolenaar
15fa13eef3SBram Moolenaarlet s:save_cpo = &cpo
16fa13eef3SBram Moolenaarset cpo&vim
17fa13eef3SBram Moolenaar
18a6878375SBram Moolenaarlet b:undo_indent = 'setlocal autoindent< smartindent< expandtab< softtabstop< shiftwidth< indentexpr< indentkeys<'
19fa13eef3SBram Moolenaar
20fa13eef3SBram Moolenaarsetlocal noautoindent nosmartindent
21fa13eef3SBram Moolenaarsetlocal softtabstop=2 shiftwidth=2 expandtab
22fa13eef3SBram Moolenaarsetlocal indentkeys=!,o,O
23fa13eef3SBram Moolenaar
24fa13eef3SBram Moolenaarif exists("*searchpairpos")
25fa13eef3SBram Moolenaar
26fa13eef3SBram Moolenaar	if !exists('g:clojure_maxlines')
27*113cb513SBram Moolenaar		let g:clojure_maxlines = 300
28fa13eef3SBram Moolenaar	endif
29fa13eef3SBram Moolenaar
30fa13eef3SBram Moolenaar	if !exists('g:clojure_fuzzy_indent')
31fa13eef3SBram Moolenaar		let g:clojure_fuzzy_indent = 1
32fa13eef3SBram Moolenaar	endif
33fa13eef3SBram Moolenaar
34fa13eef3SBram Moolenaar	if !exists('g:clojure_fuzzy_indent_patterns')
35fa13eef3SBram Moolenaar		let g:clojure_fuzzy_indent_patterns = ['^with', '^def', '^let']
36fa13eef3SBram Moolenaar	endif
37fa13eef3SBram Moolenaar
38fa13eef3SBram Moolenaar	if !exists('g:clojure_fuzzy_indent_blacklist')
39fa13eef3SBram Moolenaar		let g:clojure_fuzzy_indent_blacklist = ['-fn$', '\v^with-%(meta|out-str|loading-context)$']
40fa13eef3SBram Moolenaar	endif
41fa13eef3SBram Moolenaar
42fa13eef3SBram Moolenaar	if !exists('g:clojure_special_indent_words')
43fa13eef3SBram Moolenaar		let g:clojure_special_indent_words = 'deftype,defrecord,reify,proxy,extend-type,extend-protocol,letfn'
44fa13eef3SBram Moolenaar	endif
45fa13eef3SBram Moolenaar
46fa13eef3SBram Moolenaar	if !exists('g:clojure_align_multiline_strings')
47fa13eef3SBram Moolenaar		let g:clojure_align_multiline_strings = 0
48fa13eef3SBram Moolenaar	endif
49fa13eef3SBram Moolenaar
50438f67a0SBram Moolenaar	if !exists('g:clojure_align_subforms')
51438f67a0SBram Moolenaar		let g:clojure_align_subforms = 0
52438f67a0SBram Moolenaar	endif
53438f67a0SBram Moolenaar
546f1d9a09SBram Moolenaar	function! s:syn_id_name()
55fa13eef3SBram Moolenaar		return synIDattr(synID(line("."), col("."), 0), "name")
56fa13eef3SBram Moolenaar	endfunction
57fa13eef3SBram Moolenaar
586f1d9a09SBram Moolenaar	function! s:ignored_region()
596f1d9a09SBram Moolenaar		return s:syn_id_name() =~? '\vstring|regex|comment|character'
606f1d9a09SBram Moolenaar	endfunction
616f1d9a09SBram Moolenaar
626f1d9a09SBram Moolenaar	function! s:current_char()
63fa13eef3SBram Moolenaar		return getline('.')[col('.')-1]
64fa13eef3SBram Moolenaar	endfunction
65fa13eef3SBram Moolenaar
666f1d9a09SBram Moolenaar	function! s:current_word()
67fa13eef3SBram Moolenaar		return getline('.')[col('.')-1 : searchpos('\v>', 'n', line('.'))[1]-2]
68fa13eef3SBram Moolenaar	endfunction
69fa13eef3SBram Moolenaar
706f1d9a09SBram Moolenaar	function! s:is_paren()
716f1d9a09SBram Moolenaar		return s:current_char() =~# '\v[\(\)\[\]\{\}]' && !s:ignored_region()
72fa13eef3SBram Moolenaar	endfunction
73fa13eef3SBram Moolenaar
74*113cb513SBram Moolenaar	" Returns 1 if string matches a pattern in 'patterns', which should be
75*113cb513SBram Moolenaar	" a list of patterns.
766f1d9a09SBram Moolenaar	function! s:match_one(patterns, string)
77*113cb513SBram Moolenaar		for pat in a:patterns
7876f3b1adSBram Moolenaar			if a:string =~# pat | return 1 | endif
79fa13eef3SBram Moolenaar		endfor
80fa13eef3SBram Moolenaar	endfunction
81fa13eef3SBram Moolenaar
826f1d9a09SBram Moolenaar	function! s:match_pairs(open, close, stopat)
83fa13eef3SBram Moolenaar		" Stop only on vector and map [ resp. {. Ignore the ones in strings and
84fa13eef3SBram Moolenaar		" comments.
85942db23cSBram Moolenaar		if a:stopat == 0 && g:clojure_maxlines > 0
86fa13eef3SBram Moolenaar			let stopat = max([line(".") - g:clojure_maxlines, 0])
87fa13eef3SBram Moolenaar		else
88fa13eef3SBram Moolenaar			let stopat = a:stopat
89fa13eef3SBram Moolenaar		endif
90fa13eef3SBram Moolenaar
916f1d9a09SBram Moolenaar		let pos = searchpairpos(a:open, '', a:close, 'bWn', "!s:is_paren()", stopat)
926f1d9a09SBram Moolenaar		return [pos[0], col(pos)]
93fa13eef3SBram Moolenaar	endfunction
94fa13eef3SBram Moolenaar
956f1d9a09SBram Moolenaar	function! s:clojure_check_for_string_worker()
96fa13eef3SBram Moolenaar		" Check whether there is the last character of the previous line is
97fa13eef3SBram Moolenaar		" highlighted as a string. If so, we check whether it's a ". In this
98fa13eef3SBram Moolenaar		" case we have to check also the previous character. The " might be the
99fa13eef3SBram Moolenaar		" closing one. In case the we are still in the string, we search for the
100fa13eef3SBram Moolenaar		" opening ". If this is not found we take the indent of the line.
101fa13eef3SBram Moolenaar		let nb = prevnonblank(v:lnum - 1)
102fa13eef3SBram Moolenaar
103fa13eef3SBram Moolenaar		if nb == 0
104fa13eef3SBram Moolenaar			return -1
105fa13eef3SBram Moolenaar		endif
106fa13eef3SBram Moolenaar
107fa13eef3SBram Moolenaar		call cursor(nb, 0)
108fa13eef3SBram Moolenaar		call cursor(0, col("$") - 1)
1096f1d9a09SBram Moolenaar		if s:syn_id_name() !~? "string"
110fa13eef3SBram Moolenaar			return -1
111fa13eef3SBram Moolenaar		endif
112fa13eef3SBram Moolenaar
113fa13eef3SBram Moolenaar		" This will not work for a " in the first column...
1146f1d9a09SBram Moolenaar		if s:current_char() == '"'
115fa13eef3SBram Moolenaar			call cursor(0, col("$") - 2)
1166f1d9a09SBram Moolenaar			if s:syn_id_name() !~? "string"
117fa13eef3SBram Moolenaar				return -1
118fa13eef3SBram Moolenaar			endif
119942db23cSBram Moolenaar			if s:current_char() != '\'
120fa13eef3SBram Moolenaar				return -1
121fa13eef3SBram Moolenaar			endif
122fa13eef3SBram Moolenaar			call cursor(0, col("$") - 1)
123fa13eef3SBram Moolenaar		endif
124fa13eef3SBram Moolenaar
125fa13eef3SBram Moolenaar		let p = searchpos('\(^\|[^\\]\)\zs"', 'bW')
126fa13eef3SBram Moolenaar
127fa13eef3SBram Moolenaar		if p != [0, 0]
128fa13eef3SBram Moolenaar			return p[1] - 1
129fa13eef3SBram Moolenaar		endif
130fa13eef3SBram Moolenaar
131fa13eef3SBram Moolenaar		return indent(".")
132fa13eef3SBram Moolenaar	endfunction
133fa13eef3SBram Moolenaar
1346f1d9a09SBram Moolenaar	function! s:check_for_string()
135baca7f70SBram Moolenaar		let pos = getpos('.')
136fa13eef3SBram Moolenaar		try
1376f1d9a09SBram Moolenaar			let val = s:clojure_check_for_string_worker()
138fa13eef3SBram Moolenaar		finally
139baca7f70SBram Moolenaar			call setpos('.', pos)
140fa13eef3SBram Moolenaar		endtry
141fa13eef3SBram Moolenaar		return val
142fa13eef3SBram Moolenaar	endfunction
143fa13eef3SBram Moolenaar
1446f1d9a09SBram Moolenaar	function! s:strip_namespace_and_macro_chars(word)
14576f3b1adSBram Moolenaar		return substitute(a:word, "\\v%(.*/|[#'`~@^,]*)(.*)", '\1', '')
14676f3b1adSBram Moolenaar	endfunction
14776f3b1adSBram Moolenaar
1486f1d9a09SBram Moolenaar	function! s:clojure_is_method_special_case_worker(position)
149fa13eef3SBram Moolenaar		" Find the next enclosing form.
150fa13eef3SBram Moolenaar		call search('\S', 'Wb')
151fa13eef3SBram Moolenaar
152fa13eef3SBram Moolenaar		" Special case: we are at a '(('.
1536f1d9a09SBram Moolenaar		if s:current_char() == '('
154fa13eef3SBram Moolenaar			return 0
155fa13eef3SBram Moolenaar		endif
156fa13eef3SBram Moolenaar		call cursor(a:position)
157fa13eef3SBram Moolenaar
1586f1d9a09SBram Moolenaar		let next_paren = s:match_pairs('(', ')', 0)
159fa13eef3SBram Moolenaar
160fa13eef3SBram Moolenaar		" Special case: we are now at toplevel.
1616f1d9a09SBram Moolenaar		if next_paren == [0, 0]
162fa13eef3SBram Moolenaar			return 0
163fa13eef3SBram Moolenaar		endif
1646f1d9a09SBram Moolenaar		call cursor(next_paren)
165fa13eef3SBram Moolenaar
166fa13eef3SBram Moolenaar		call search('\S', 'W')
1676f1d9a09SBram Moolenaar		let w = s:strip_namespace_and_macro_chars(s:current_word())
168942db23cSBram Moolenaar
16976f3b1adSBram Moolenaar		if g:clojure_special_indent_words =~# '\V\<' . w . '\>'
170942db23cSBram Moolenaar
171942db23cSBram Moolenaar			" `letfn` is a special-special-case.
172942db23cSBram Moolenaar			if w ==# 'letfn'
173942db23cSBram Moolenaar				" Earlier code left the cursor at:
174942db23cSBram Moolenaar				"     (letfn [...] ...)
175942db23cSBram Moolenaar				"      ^
176942db23cSBram Moolenaar
177942db23cSBram Moolenaar				" Search and get coordinates of first `[`
178942db23cSBram Moolenaar				"     (letfn [...] ...)
179942db23cSBram Moolenaar				"            ^
180942db23cSBram Moolenaar				call search('\[', 'W')
181942db23cSBram Moolenaar				let pos = getcurpos()
182942db23cSBram Moolenaar				let letfn_bracket = [pos[1], pos[2]]
183942db23cSBram Moolenaar
184942db23cSBram Moolenaar				" Move cursor to start of the form this function was
185942db23cSBram Moolenaar				" initially called on.  Grab the coordinates of the
186942db23cSBram Moolenaar				" closest outer `[`.
187942db23cSBram Moolenaar				call cursor(a:position)
188942db23cSBram Moolenaar				let outer_bracket = s:match_pairs('\[', '\]', 0)
189942db23cSBram Moolenaar
190942db23cSBram Moolenaar				" If the located square brackets are not the same,
191942db23cSBram Moolenaar				" don't use special-case formatting.
192942db23cSBram Moolenaar				if outer_bracket != letfn_bracket
193942db23cSBram Moolenaar					return 0
194942db23cSBram Moolenaar				endif
195942db23cSBram Moolenaar			endif
196942db23cSBram Moolenaar
197fa13eef3SBram Moolenaar			return 1
198fa13eef3SBram Moolenaar		endif
199fa13eef3SBram Moolenaar
200fa13eef3SBram Moolenaar		return 0
201fa13eef3SBram Moolenaar	endfunction
202fa13eef3SBram Moolenaar
2036f1d9a09SBram Moolenaar	function! s:is_method_special_case(position)
204baca7f70SBram Moolenaar		let pos = getpos('.')
205fa13eef3SBram Moolenaar		try
2066f1d9a09SBram Moolenaar			let val = s:clojure_is_method_special_case_worker(a:position)
207fa13eef3SBram Moolenaar		finally
208baca7f70SBram Moolenaar			call setpos('.', pos)
209fa13eef3SBram Moolenaar		endtry
210fa13eef3SBram Moolenaar		return val
211fa13eef3SBram Moolenaar	endfunction
212fa13eef3SBram Moolenaar
2136f1d9a09SBram Moolenaar	" Check if form is a reader conditional, that is, it is prefixed by #?
214*113cb513SBram Moolenaar	" or #?@
2156f1d9a09SBram Moolenaar	function! s:is_reader_conditional_special_case(position)
216942db23cSBram Moolenaar		return getline(a:position[0])[a:position[1] - 3 : a:position[1] - 2] == "#?"
217*113cb513SBram Moolenaar			\|| getline(a:position[0])[a:position[1] - 4 : a:position[1] - 2] == "#?@"
2186f1d9a09SBram Moolenaar	endfunction
2196f1d9a09SBram Moolenaar
2206f1d9a09SBram Moolenaar	" Returns 1 for opening brackets, -1 for _anything else_.
2216f1d9a09SBram Moolenaar	function! s:bracket_type(char)
2226f1d9a09SBram Moolenaar		return stridx('([{', a:char) > -1 ? 1 : -1
2236f1d9a09SBram Moolenaar	endfunction
2246f1d9a09SBram Moolenaar
2256f1d9a09SBram Moolenaar	" Returns: [opening-bracket-lnum, indent]
2266f1d9a09SBram Moolenaar	function! s:clojure_indent_pos()
227fa13eef3SBram Moolenaar		" Get rid of special case.
228fa13eef3SBram Moolenaar		if line(".") == 1
2296f1d9a09SBram Moolenaar			return [0, 0]
230fa13eef3SBram Moolenaar		endif
231fa13eef3SBram Moolenaar
232fa13eef3SBram Moolenaar		" We have to apply some heuristics here to figure out, whether to use
233fa13eef3SBram Moolenaar		" normal lisp indenting or not.
2346f1d9a09SBram Moolenaar		let i = s:check_for_string()
235fa13eef3SBram Moolenaar		if i > -1
2366f1d9a09SBram Moolenaar			return [0, i + !!g:clojure_align_multiline_strings]
237fa13eef3SBram Moolenaar		endif
238fa13eef3SBram Moolenaar
239fa13eef3SBram Moolenaar		call cursor(0, 1)
240fa13eef3SBram Moolenaar
241fa13eef3SBram Moolenaar		" Find the next enclosing [ or {. We can limit the second search
242fa13eef3SBram Moolenaar		" to the line, where the [ was found. If no [ was there this is
243fa13eef3SBram Moolenaar		" zero and we search for an enclosing {.
2446f1d9a09SBram Moolenaar		let paren = s:match_pairs('(', ')', 0)
2456f1d9a09SBram Moolenaar		let bracket = s:match_pairs('\[', '\]', paren[0])
2466f1d9a09SBram Moolenaar		let curly = s:match_pairs('{', '}', bracket[0])
247fa13eef3SBram Moolenaar
248fa13eef3SBram Moolenaar		" In case the curly brace is on a line later then the [ or - in
249fa13eef3SBram Moolenaar		" case they are on the same line - in a higher column, we take the
250fa13eef3SBram Moolenaar		" curly indent.
251fa13eef3SBram Moolenaar		if curly[0] > bracket[0] || curly[1] > bracket[1]
252fa13eef3SBram Moolenaar			if curly[0] > paren[0] || curly[1] > paren[1]
2536f1d9a09SBram Moolenaar				return curly
254fa13eef3SBram Moolenaar			endif
255fa13eef3SBram Moolenaar		endif
256fa13eef3SBram Moolenaar
257fa13eef3SBram Moolenaar		" If the curly was not chosen, we take the bracket indent - if
258fa13eef3SBram Moolenaar		" there was one.
259fa13eef3SBram Moolenaar		if bracket[0] > paren[0] || bracket[1] > paren[1]
2606f1d9a09SBram Moolenaar			return bracket
261fa13eef3SBram Moolenaar		endif
262fa13eef3SBram Moolenaar
263fa13eef3SBram Moolenaar		" There are neither { nor [ nor (, ie. we are at the toplevel.
264fa13eef3SBram Moolenaar		if paren == [0, 0]
2656f1d9a09SBram Moolenaar			return paren
266fa13eef3SBram Moolenaar		endif
267fa13eef3SBram Moolenaar
268fa13eef3SBram Moolenaar		" Now we have to reimplement lispindent. This is surprisingly easy, as
269fa13eef3SBram Moolenaar		" soon as one has access to syntax items.
270fa13eef3SBram Moolenaar		"
271fa13eef3SBram Moolenaar		" - Check whether we are in a special position after a word in
272fa13eef3SBram Moolenaar		"   g:clojure_special_indent_words. These are special cases.
273fa13eef3SBram Moolenaar		" - Get the next keyword after the (.
274fa13eef3SBram Moolenaar		" - If its first character is also a (, we have another sexp and align
275fa13eef3SBram Moolenaar		"   one column to the right of the unmatched (.
276fa13eef3SBram Moolenaar		" - In case it is in lispwords, we indent the next line to the column of
277fa13eef3SBram Moolenaar		"   the ( + sw.
278fa13eef3SBram Moolenaar		" - If not, we check whether it is last word in the line. In that case
279fa13eef3SBram Moolenaar		"   we again use ( + sw for indent.
280fa13eef3SBram Moolenaar		" - In any other case we use the column of the end of the word + 2.
281fa13eef3SBram Moolenaar		call cursor(paren)
282fa13eef3SBram Moolenaar
2836f1d9a09SBram Moolenaar		if s:is_method_special_case(paren)
284942db23cSBram Moolenaar			return [paren[0], paren[1] + &shiftwidth - 1]
2856f1d9a09SBram Moolenaar		endif
2866f1d9a09SBram Moolenaar
2876f1d9a09SBram Moolenaar		if s:is_reader_conditional_special_case(paren)
2886f1d9a09SBram Moolenaar			return paren
289fa13eef3SBram Moolenaar		endif
290fa13eef3SBram Moolenaar
291fa13eef3SBram Moolenaar		" In case we are at the last character, we use the paren position.
292fa13eef3SBram Moolenaar		if col("$") - 1 == paren[1]
2936f1d9a09SBram Moolenaar			return paren
294fa13eef3SBram Moolenaar		endif
295fa13eef3SBram Moolenaar
296fa13eef3SBram Moolenaar		" In case after the paren is a whitespace, we search for the next word.
297baca7f70SBram Moolenaar		call cursor(0, col('.') + 1)
2986f1d9a09SBram Moolenaar		if s:current_char() == ' '
299baca7f70SBram Moolenaar			call search('\v\S', 'W')
300fa13eef3SBram Moolenaar		endif
301fa13eef3SBram Moolenaar
302fa13eef3SBram Moolenaar		" If we moved to another line, there is no word after the (. We
303fa13eef3SBram Moolenaar		" use the ( position for indent.
304fa13eef3SBram Moolenaar		if line(".") > paren[0]
3056f1d9a09SBram Moolenaar			return paren
306fa13eef3SBram Moolenaar		endif
307fa13eef3SBram Moolenaar
308fa13eef3SBram Moolenaar		" We still have to check, whether the keyword starts with a (, [ or {.
309fa13eef3SBram Moolenaar		" In that case we use the ( position for indent.
3106f1d9a09SBram Moolenaar		let w = s:current_word()
3116f1d9a09SBram Moolenaar		if s:bracket_type(w[0]) == 1
3126f1d9a09SBram Moolenaar			return paren
313fa13eef3SBram Moolenaar		endif
314fa13eef3SBram Moolenaar
315942db23cSBram Moolenaar		" If the keyword begins with #, check if it is an anonymous
316942db23cSBram Moolenaar		" function or set, in which case we indent by the shiftwidth
317942db23cSBram Moolenaar		" (minus one if g:clojure_align_subforms = 1), or if it is
318942db23cSBram Moolenaar		" ignored, in which case we use the ( position for indent.
319942db23cSBram Moolenaar		if w[0] == "#"
320942db23cSBram Moolenaar			" TODO: Handle #=() and other rare reader invocations?
321942db23cSBram Moolenaar			if w[1] == '(' || w[1] == '{'
322942db23cSBram Moolenaar				return [paren[0], paren[1] + (g:clojure_align_subforms ? 0 : &shiftwidth - 1)]
323942db23cSBram Moolenaar			elseif w[1] == '_'
324942db23cSBram Moolenaar				return paren
325942db23cSBram Moolenaar			endif
326942db23cSBram Moolenaar		endif
327942db23cSBram Moolenaar
328fa13eef3SBram Moolenaar		" Test words without namespace qualifiers and leading reader macro
329fa13eef3SBram Moolenaar		" metacharacters.
330fa13eef3SBram Moolenaar		"
331fa13eef3SBram Moolenaar		" e.g. clojure.core/defn and #'defn should both indent like defn.
3326f1d9a09SBram Moolenaar		let ww = s:strip_namespace_and_macro_chars(w)
333fa13eef3SBram Moolenaar
33476f3b1adSBram Moolenaar		if &lispwords =~# '\V\<' . ww . '\>'
335942db23cSBram Moolenaar			return [paren[0], paren[1] + &shiftwidth - 1]
336fa13eef3SBram Moolenaar		endif
337fa13eef3SBram Moolenaar
338fa13eef3SBram Moolenaar		if g:clojure_fuzzy_indent
3396f1d9a09SBram Moolenaar			\ && !s:match_one(g:clojure_fuzzy_indent_blacklist, ww)
3406f1d9a09SBram Moolenaar			\ && s:match_one(g:clojure_fuzzy_indent_patterns, ww)
341942db23cSBram Moolenaar			return [paren[0], paren[1] + &shiftwidth - 1]
342fa13eef3SBram Moolenaar		endif
343fa13eef3SBram Moolenaar
344baca7f70SBram Moolenaar		call search('\v\_s', 'cW')
345baca7f70SBram Moolenaar		call search('\v\S', 'W')
346fa13eef3SBram Moolenaar		if paren[0] < line(".")
347942db23cSBram Moolenaar			return [paren[0], paren[1] + (g:clojure_align_subforms ? 0 : &shiftwidth - 1)]
348fa13eef3SBram Moolenaar		endif
349fa13eef3SBram Moolenaar
350baca7f70SBram Moolenaar		call search('\v\S', 'bW')
3516f1d9a09SBram Moolenaar		return [line('.'), col('.') + 1]
3526f1d9a09SBram Moolenaar	endfunction
3536f1d9a09SBram Moolenaar
3546f1d9a09SBram Moolenaar	function! GetClojureIndent()
3556f1d9a09SBram Moolenaar		let lnum = line('.')
3566f1d9a09SBram Moolenaar		let orig_lnum = lnum
3576f1d9a09SBram Moolenaar		let orig_col = col('.')
3586f1d9a09SBram Moolenaar		let [opening_lnum, indent] = s:clojure_indent_pos()
3596f1d9a09SBram Moolenaar
3606f1d9a09SBram Moolenaar		" Account for multibyte characters
3616f1d9a09SBram Moolenaar		if opening_lnum > 0
3626f1d9a09SBram Moolenaar			let indent -= indent - virtcol([opening_lnum, indent])
3636f1d9a09SBram Moolenaar		endif
3646f1d9a09SBram Moolenaar
3656f1d9a09SBram Moolenaar		" Return if there are no previous lines to inherit from
3666f1d9a09SBram Moolenaar		if opening_lnum < 1 || opening_lnum >= lnum - 1
3676f1d9a09SBram Moolenaar			call cursor(orig_lnum, orig_col)
3686f1d9a09SBram Moolenaar			return indent
3696f1d9a09SBram Moolenaar		endif
3706f1d9a09SBram Moolenaar
3716f1d9a09SBram Moolenaar		let bracket_count = 0
3726f1d9a09SBram Moolenaar
3736f1d9a09SBram Moolenaar		" Take the indent of the first previous non-white line that is
3746f1d9a09SBram Moolenaar		" at the same sexp level. cf. src/misc1.c:get_lisp_indent()
3756f1d9a09SBram Moolenaar		while 1
3766f1d9a09SBram Moolenaar			let lnum = prevnonblank(lnum - 1)
3776f1d9a09SBram Moolenaar			let col = 1
3786f1d9a09SBram Moolenaar
3796f1d9a09SBram Moolenaar			if lnum <= opening_lnum
3806f1d9a09SBram Moolenaar				break
3816f1d9a09SBram Moolenaar			endif
3826f1d9a09SBram Moolenaar
3836f1d9a09SBram Moolenaar			call cursor(lnum, col)
3846f1d9a09SBram Moolenaar
3856f1d9a09SBram Moolenaar			" Handle bracket counting edge case
3866f1d9a09SBram Moolenaar			if s:is_paren()
3876f1d9a09SBram Moolenaar				let bracket_count += s:bracket_type(s:current_char())
3886f1d9a09SBram Moolenaar			endif
3896f1d9a09SBram Moolenaar
3906f1d9a09SBram Moolenaar			while 1
3916f1d9a09SBram Moolenaar				if search('\v[(\[{}\])]', '', lnum) < 1
3926f1d9a09SBram Moolenaar					break
3936f1d9a09SBram Moolenaar				elseif !s:ignored_region()
3946f1d9a09SBram Moolenaar					let bracket_count += s:bracket_type(s:current_char())
3956f1d9a09SBram Moolenaar				endif
3966f1d9a09SBram Moolenaar			endwhile
3976f1d9a09SBram Moolenaar
3986f1d9a09SBram Moolenaar			if bracket_count == 0
3996f1d9a09SBram Moolenaar				" Check if this is part of a multiline string
4006f1d9a09SBram Moolenaar				call cursor(lnum, 1)
4016f1d9a09SBram Moolenaar				if s:syn_id_name() !~? '\vstring|regex'
4026f1d9a09SBram Moolenaar					call cursor(orig_lnum, orig_col)
4036f1d9a09SBram Moolenaar					return indent(lnum)
4046f1d9a09SBram Moolenaar				endif
4056f1d9a09SBram Moolenaar			endif
4066f1d9a09SBram Moolenaar		endwhile
4076f1d9a09SBram Moolenaar
4086f1d9a09SBram Moolenaar		call cursor(orig_lnum, orig_col)
4096f1d9a09SBram Moolenaar		return indent
410fa13eef3SBram Moolenaar	endfunction
411fa13eef3SBram Moolenaar
412fa13eef3SBram Moolenaar	setlocal indentexpr=GetClojureIndent()
413fa13eef3SBram Moolenaar
414fa13eef3SBram Moolenaarelse
415fa13eef3SBram Moolenaar
416fa13eef3SBram Moolenaar	" In case we have searchpairpos not available we fall back to
417fa13eef3SBram Moolenaar	" normal lisp indenting.
418fa13eef3SBram Moolenaar	setlocal indentexpr=
419fa13eef3SBram Moolenaar	setlocal lisp
420fa13eef3SBram Moolenaar	let b:undo_indent .= '| setlocal lisp<'
421fa13eef3SBram Moolenaar
422fa13eef3SBram Moolenaarendif
423fa13eef3SBram Moolenaar
424fa13eef3SBram Moolenaarlet &cpo = s:save_cpo
425fa13eef3SBram Moolenaarunlet! s:save_cpo
426fa13eef3SBram Moolenaar
427baca7f70SBram Moolenaar" vim:sts=8:sw=8:ts=8:noet
428