| 
									
										
										
										
											2013-02-06 17:34:04 +01:00
										 |  |  |  | " Vim indent file | 
					
						
							| 
									
										
										
										
											2021-02-13 18:14:48 +01:00
										 |  |  |  | " Language:           Clojure | 
					
						
							| 
									
										
										
										
											2021-11-07 20:27:04 +00:00
										 |  |  |  | " Maintainer:         Alex Vear <alex@vear.uk> | 
					
						
							| 
									
										
										
										
											2021-02-13 18:14:48 +01:00
										 |  |  |  | " Former Maintainers: Sung Pae <self@sungpae.com> | 
					
						
							|  |  |  |  | "                     Meikel Brandmeyer <mb@kotka.de> | 
					
						
							|  |  |  |  | " URL:                https://github.com/clojure-vim/clojure.vim | 
					
						
							|  |  |  |  | " License:            Vim (see :h license) | 
					
						
							| 
									
										
										
										
											2022-03-30 10:51:39 +01:00
										 |  |  |  | " Last Change:        2022-03-24 | 
					
						
							| 
									
										
										
										
											2013-02-06 17:34:04 +01:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | if exists("b:did_indent") | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 	finish | 
					
						
							| 
									
										
										
										
											2013-02-06 17:34:04 +01:00
										 |  |  |  | endif | 
					
						
							|  |  |  |  | let b:did_indent = 1 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | let s:save_cpo = &cpo | 
					
						
							|  |  |  |  | set cpo&vim | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-22 21:02:50 +01:00
										 |  |  |  | let b:undo_indent = 'setlocal autoindent< smartindent< expandtab< softtabstop< shiftwidth< indentexpr< indentkeys<' | 
					
						
							| 
									
										
										
										
											2013-02-06 17:34:04 +01:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | setlocal noautoindent nosmartindent | 
					
						
							|  |  |  |  | setlocal softtabstop=2 shiftwidth=2 expandtab | 
					
						
							|  |  |  |  | setlocal indentkeys=!,o,O | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | if exists("*searchpairpos") | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 	if !exists('g:clojure_maxlines') | 
					
						
							| 
									
										
										
										
											2021-11-07 20:27:04 +00:00
										 |  |  |  | 		let g:clojure_maxlines = 300 | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 	endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if !exists('g:clojure_fuzzy_indent') | 
					
						
							|  |  |  |  | 		let g:clojure_fuzzy_indent = 1 | 
					
						
							|  |  |  |  | 	endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if !exists('g:clojure_fuzzy_indent_patterns') | 
					
						
							|  |  |  |  | 		let g:clojure_fuzzy_indent_patterns = ['^with', '^def', '^let'] | 
					
						
							|  |  |  |  | 	endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if !exists('g:clojure_fuzzy_indent_blacklist') | 
					
						
							|  |  |  |  | 		let g:clojure_fuzzy_indent_blacklist = ['-fn$', '\v^with-%(meta|out-str|loading-context)$'] | 
					
						
							|  |  |  |  | 	endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if !exists('g:clojure_special_indent_words') | 
					
						
							|  |  |  |  | 		let g:clojure_special_indent_words = 'deftype,defrecord,reify,proxy,extend-type,extend-protocol,letfn' | 
					
						
							|  |  |  |  | 	endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if !exists('g:clojure_align_multiline_strings') | 
					
						
							|  |  |  |  | 		let g:clojure_align_multiline_strings = 0 | 
					
						
							|  |  |  |  | 	endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-07 06:09:28 +01:00
										 |  |  |  | 	if !exists('g:clojure_align_subforms') | 
					
						
							|  |  |  |  | 		let g:clojure_align_subforms = 0 | 
					
						
							|  |  |  |  | 	endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 	function! s:syn_id_name() | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 		return synIDattr(synID(line("."), col("."), 0), "name") | 
					
						
							|  |  |  |  | 	endfunction | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 	function! s:ignored_region() | 
					
						
							|  |  |  |  | 		return s:syn_id_name() =~? '\vstring|regex|comment|character' | 
					
						
							|  |  |  |  | 	endfunction | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	function! s:current_char() | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 		return getline('.')[col('.')-1] | 
					
						
							|  |  |  |  | 	endfunction | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 	function! s:current_word() | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 		return getline('.')[col('.')-1 : searchpos('\v>', 'n', line('.'))[1]-2] | 
					
						
							|  |  |  |  | 	endfunction | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 	function! s:is_paren() | 
					
						
							|  |  |  |  | 		return s:current_char() =~# '\v[\(\)\[\]\{\}]' && !s:ignored_region() | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 	endfunction | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-07 20:27:04 +00:00
										 |  |  |  | 	" Returns 1 if string matches a pattern in 'patterns', which should be | 
					
						
							|  |  |  |  | 	" a list of patterns. | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 	function! s:match_one(patterns, string) | 
					
						
							| 
									
										
										
										
											2021-11-07 20:27:04 +00:00
										 |  |  |  | 		for pat in a:patterns | 
					
						
							| 
									
										
										
										
											2014-03-27 22:30:07 +01:00
										 |  |  |  | 			if a:string =~# pat | return 1 | endif | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 		endfor | 
					
						
							|  |  |  |  | 	endfunction | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 	function! s:match_pairs(open, close, stopat) | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 		" Stop only on vector and map [ resp. {. Ignore the ones in strings and | 
					
						
							|  |  |  |  | 		" comments. | 
					
						
							| 
									
										
										
										
											2021-02-13 18:14:48 +01:00
										 |  |  |  | 		if a:stopat == 0 && g:clojure_maxlines > 0 | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 			let stopat = max([line(".") - g:clojure_maxlines, 0]) | 
					
						
							|  |  |  |  | 		else | 
					
						
							|  |  |  |  | 			let stopat = a:stopat | 
					
						
							|  |  |  |  | 		endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 		let pos = searchpairpos(a:open, '', a:close, 'bWn', "!s:is_paren()", stopat) | 
					
						
							|  |  |  |  | 		return [pos[0], col(pos)] | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 	endfunction | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 	function! s:clojure_check_for_string_worker() | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 		" Check whether there is the last character of the previous line is | 
					
						
							|  |  |  |  | 		" highlighted as a string. If so, we check whether it's a ". In this | 
					
						
							|  |  |  |  | 		" case we have to check also the previous character. The " might be the | 
					
						
							|  |  |  |  | 		" closing one. In case the we are still in the string, we search for the | 
					
						
							|  |  |  |  | 		" opening ". If this is not found we take the indent of the line. | 
					
						
							|  |  |  |  | 		let nb = prevnonblank(v:lnum - 1) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if nb == 0 | 
					
						
							|  |  |  |  | 			return -1 | 
					
						
							|  |  |  |  | 		endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		call cursor(nb, 0) | 
					
						
							|  |  |  |  | 		call cursor(0, col("$") - 1) | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 		if s:syn_id_name() !~? "string" | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 			return -1 | 
					
						
							|  |  |  |  | 		endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		" This will not work for a " in the first column... | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 		if s:current_char() == '"' | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 			call cursor(0, col("$") - 2) | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 			if s:syn_id_name() !~? "string" | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 				return -1 | 
					
						
							|  |  |  |  | 			endif | 
					
						
							| 
									
										
										
										
											2021-02-13 18:14:48 +01:00
										 |  |  |  | 			if s:current_char() != '\' | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 				return -1 | 
					
						
							|  |  |  |  | 			endif | 
					
						
							|  |  |  |  | 			call cursor(0, col("$") - 1) | 
					
						
							|  |  |  |  | 		endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		let p = searchpos('\(^\|[^\\]\)\zs"', 'bW') | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if p != [0, 0] | 
					
						
							|  |  |  |  | 			return p[1] - 1 | 
					
						
							|  |  |  |  | 		endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		return indent(".") | 
					
						
							|  |  |  |  | 	endfunction | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 	function! s:check_for_string() | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 		let pos = getpos('.') | 
					
						
							|  |  |  |  | 		try | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 			let val = s:clojure_check_for_string_worker() | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 		finally | 
					
						
							|  |  |  |  | 			call setpos('.', pos) | 
					
						
							|  |  |  |  | 		endtry | 
					
						
							|  |  |  |  | 		return val | 
					
						
							|  |  |  |  | 	endfunction | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 	function! s:strip_namespace_and_macro_chars(word) | 
					
						
							| 
									
										
										
										
											2014-03-27 22:30:07 +01:00
										 |  |  |  | 		return substitute(a:word, "\\v%(.*/|[#'`~@^,]*)(.*)", '\1', '') | 
					
						
							|  |  |  |  | 	endfunction | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 	function! s:clojure_is_method_special_case_worker(position) | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 		" Find the next enclosing form. | 
					
						
							|  |  |  |  | 		call search('\S', 'Wb') | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		" Special case: we are at a '(('. | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 		if s:current_char() == '(' | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 			return 0 | 
					
						
							|  |  |  |  | 		endif | 
					
						
							|  |  |  |  | 		call cursor(a:position) | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 		let next_paren = s:match_pairs('(', ')', 0) | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		" Special case: we are now at toplevel. | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 		if next_paren == [0, 0] | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 			return 0 | 
					
						
							|  |  |  |  | 		endif | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 		call cursor(next_paren) | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		call search('\S', 'W') | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 		let w = s:strip_namespace_and_macro_chars(s:current_word()) | 
					
						
							| 
									
										
										
										
											2021-02-13 18:14:48 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-27 22:30:07 +01:00
										 |  |  |  | 		if g:clojure_special_indent_words =~# '\V\<' . w . '\>' | 
					
						
							| 
									
										
										
										
											2021-02-13 18:14:48 +01:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 			" `letfn` is a special-special-case. | 
					
						
							|  |  |  |  | 			if w ==# 'letfn' | 
					
						
							|  |  |  |  | 				" Earlier code left the cursor at: | 
					
						
							|  |  |  |  | 				"     (letfn [...] ...) | 
					
						
							|  |  |  |  | 				"      ^ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				" Search and get coordinates of first `[` | 
					
						
							|  |  |  |  | 				"     (letfn [...] ...) | 
					
						
							|  |  |  |  | 				"            ^ | 
					
						
							|  |  |  |  | 				call search('\[', 'W') | 
					
						
							|  |  |  |  | 				let pos = getcurpos() | 
					
						
							|  |  |  |  | 				let letfn_bracket = [pos[1], pos[2]] | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				" Move cursor to start of the form this function was | 
					
						
							|  |  |  |  | 				" initially called on.  Grab the coordinates of the | 
					
						
							|  |  |  |  | 				" closest outer `[`. | 
					
						
							|  |  |  |  | 				call cursor(a:position) | 
					
						
							|  |  |  |  | 				let outer_bracket = s:match_pairs('\[', '\]', 0) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				" If the located square brackets are not the same, | 
					
						
							|  |  |  |  | 				" don't use special-case formatting. | 
					
						
							|  |  |  |  | 				if outer_bracket != letfn_bracket | 
					
						
							|  |  |  |  | 					return 0 | 
					
						
							|  |  |  |  | 				endif | 
					
						
							|  |  |  |  | 			endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 			return 1 | 
					
						
							|  |  |  |  | 		endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		return 0 | 
					
						
							|  |  |  |  | 	endfunction | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 	function! s:is_method_special_case(position) | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 		let pos = getpos('.') | 
					
						
							|  |  |  |  | 		try | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 			let val = s:clojure_is_method_special_case_worker(a:position) | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 		finally | 
					
						
							|  |  |  |  | 			call setpos('.', pos) | 
					
						
							|  |  |  |  | 		endtry | 
					
						
							|  |  |  |  | 		return val | 
					
						
							|  |  |  |  | 	endfunction | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 	" Check if form is a reader conditional, that is, it is prefixed by #? | 
					
						
							| 
									
										
										
										
											2021-11-07 20:27:04 +00:00
										 |  |  |  | 	" or #?@ | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 	function! s:is_reader_conditional_special_case(position) | 
					
						
							| 
									
										
										
										
											2021-02-13 18:14:48 +01:00
										 |  |  |  | 		return getline(a:position[0])[a:position[1] - 3 : a:position[1] - 2] == "#?" | 
					
						
							| 
									
										
										
										
											2021-11-07 20:27:04 +00:00
										 |  |  |  | 			\|| getline(a:position[0])[a:position[1] - 4 : a:position[1] - 2] == "#?@" | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 	endfunction | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	" Returns 1 for opening brackets, -1 for _anything else_. | 
					
						
							|  |  |  |  | 	function! s:bracket_type(char) | 
					
						
							|  |  |  |  | 		return stridx('([{', a:char) > -1 ? 1 : -1 | 
					
						
							|  |  |  |  | 	endfunction | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	" Returns: [opening-bracket-lnum, indent] | 
					
						
							|  |  |  |  | 	function! s:clojure_indent_pos() | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 		" Get rid of special case. | 
					
						
							|  |  |  |  | 		if line(".") == 1 | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 			return [0, 0] | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 		endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		" We have to apply some heuristics here to figure out, whether to use | 
					
						
							|  |  |  |  | 		" normal lisp indenting or not. | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 		let i = s:check_for_string() | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 		if i > -1 | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 			return [0, i + !!g:clojure_align_multiline_strings] | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 		endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		call cursor(0, 1) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		" Find the next enclosing [ or {. We can limit the second search | 
					
						
							|  |  |  |  | 		" to the line, where the [ was found. If no [ was there this is | 
					
						
							|  |  |  |  | 		" zero and we search for an enclosing {. | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 		let paren = s:match_pairs('(', ')', 0) | 
					
						
							|  |  |  |  | 		let bracket = s:match_pairs('\[', '\]', paren[0]) | 
					
						
							|  |  |  |  | 		let curly = s:match_pairs('{', '}', bracket[0]) | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		" In case the curly brace is on a line later then the [ or - in | 
					
						
							|  |  |  |  | 		" case they are on the same line - in a higher column, we take the | 
					
						
							|  |  |  |  | 		" curly indent. | 
					
						
							|  |  |  |  | 		if curly[0] > bracket[0] || curly[1] > bracket[1] | 
					
						
							|  |  |  |  | 			if curly[0] > paren[0] || curly[1] > paren[1] | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 				return curly | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 			endif | 
					
						
							|  |  |  |  | 		endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		" If the curly was not chosen, we take the bracket indent - if | 
					
						
							|  |  |  |  | 		" there was one. | 
					
						
							|  |  |  |  | 		if bracket[0] > paren[0] || bracket[1] > paren[1] | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 			return bracket | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 		endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		" There are neither { nor [ nor (, ie. we are at the toplevel. | 
					
						
							|  |  |  |  | 		if paren == [0, 0] | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 			return paren | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 		endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		" Now we have to reimplement lispindent. This is surprisingly easy, as | 
					
						
							|  |  |  |  | 		" soon as one has access to syntax items. | 
					
						
							|  |  |  |  | 		" | 
					
						
							|  |  |  |  | 		" - Check whether we are in a special position after a word in | 
					
						
							|  |  |  |  | 		"   g:clojure_special_indent_words. These are special cases. | 
					
						
							|  |  |  |  | 		" - Get the next keyword after the (. | 
					
						
							|  |  |  |  | 		" - If its first character is also a (, we have another sexp and align | 
					
						
							|  |  |  |  | 		"   one column to the right of the unmatched (. | 
					
						
							|  |  |  |  | 		" - In case it is in lispwords, we indent the next line to the column of | 
					
						
							|  |  |  |  | 		"   the ( + sw. | 
					
						
							|  |  |  |  | 		" - If not, we check whether it is last word in the line. In that case | 
					
						
							|  |  |  |  | 		"   we again use ( + sw for indent. | 
					
						
							|  |  |  |  | 		" - In any other case we use the column of the end of the word + 2. | 
					
						
							|  |  |  |  | 		call cursor(paren) | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 		if s:is_method_special_case(paren) | 
					
						
							| 
									
										
										
										
											2021-02-13 18:14:48 +01:00
										 |  |  |  | 			return [paren[0], paren[1] + &shiftwidth - 1] | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 		endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if s:is_reader_conditional_special_case(paren) | 
					
						
							|  |  |  |  | 			return paren | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 		endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		" In case we are at the last character, we use the paren position. | 
					
						
							|  |  |  |  | 		if col("$") - 1 == paren[1] | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 			return paren | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 		endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		" In case after the paren is a whitespace, we search for the next word. | 
					
						
							|  |  |  |  | 		call cursor(0, col('.') + 1) | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 		if s:current_char() == ' ' | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 			call search('\v\S', 'W') | 
					
						
							|  |  |  |  | 		endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		" If we moved to another line, there is no word after the (. We | 
					
						
							|  |  |  |  | 		" use the ( position for indent. | 
					
						
							|  |  |  |  | 		if line(".") > paren[0] | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 			return paren | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 		endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		" We still have to check, whether the keyword starts with a (, [ or {. | 
					
						
							|  |  |  |  | 		" In that case we use the ( position for indent. | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 		let w = s:current_word() | 
					
						
							|  |  |  |  | 		if s:bracket_type(w[0]) == 1 | 
					
						
							|  |  |  |  | 			return paren | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 		endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-13 18:14:48 +01:00
										 |  |  |  | 		" If the keyword begins with #, check if it is an anonymous | 
					
						
							|  |  |  |  | 		" function or set, in which case we indent by the shiftwidth | 
					
						
							|  |  |  |  | 		" (minus one if g:clojure_align_subforms = 1), or if it is | 
					
						
							|  |  |  |  | 		" ignored, in which case we use the ( position for indent. | 
					
						
							|  |  |  |  | 		if w[0] == "#" | 
					
						
							|  |  |  |  | 			" TODO: Handle #=() and other rare reader invocations? | 
					
						
							|  |  |  |  | 			if w[1] == '(' || w[1] == '{' | 
					
						
							|  |  |  |  | 				return [paren[0], paren[1] + (g:clojure_align_subforms ? 0 : &shiftwidth - 1)] | 
					
						
							|  |  |  |  | 			elseif w[1] == '_' | 
					
						
							|  |  |  |  | 				return paren | 
					
						
							|  |  |  |  | 			endif | 
					
						
							|  |  |  |  | 		endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 		" Test words without namespace qualifiers and leading reader macro | 
					
						
							|  |  |  |  | 		" metacharacters. | 
					
						
							|  |  |  |  | 		" | 
					
						
							|  |  |  |  | 		" e.g. clojure.core/defn and #'defn should both indent like defn. | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 		let ww = s:strip_namespace_and_macro_chars(w) | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-27 22:30:07 +01:00
										 |  |  |  | 		if &lispwords =~# '\V\<' . ww . '\>' | 
					
						
							| 
									
										
										
										
											2021-02-13 18:14:48 +01:00
										 |  |  |  | 			return [paren[0], paren[1] + &shiftwidth - 1] | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 		endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if g:clojure_fuzzy_indent | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 			\ && !s:match_one(g:clojure_fuzzy_indent_blacklist, ww) | 
					
						
							|  |  |  |  | 			\ && s:match_one(g:clojure_fuzzy_indent_patterns, ww) | 
					
						
							| 
									
										
										
										
											2021-02-13 18:14:48 +01:00
										 |  |  |  | 			return [paren[0], paren[1] + &shiftwidth - 1] | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 		endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		call search('\v\_s', 'cW') | 
					
						
							|  |  |  |  | 		call search('\v\S', 'W') | 
					
						
							|  |  |  |  | 		if paren[0] < line(".") | 
					
						
							| 
									
										
										
										
											2021-02-13 18:14:48 +01:00
										 |  |  |  | 			return [paren[0], paren[1] + (g:clojure_align_subforms ? 0 : &shiftwidth - 1)] | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 		endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		call search('\v\S', 'bW') | 
					
						
							| 
									
										
										
										
											2016-07-24 14:12:38 +02:00
										 |  |  |  | 		return [line('.'), col('.') + 1] | 
					
						
							|  |  |  |  | 	endfunction | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	function! GetClojureIndent() | 
					
						
							|  |  |  |  | 		let lnum = line('.') | 
					
						
							|  |  |  |  | 		let orig_lnum = lnum | 
					
						
							|  |  |  |  | 		let orig_col = col('.') | 
					
						
							|  |  |  |  | 		let [opening_lnum, indent] = s:clojure_indent_pos() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		" Account for multibyte characters | 
					
						
							|  |  |  |  | 		if opening_lnum > 0 | 
					
						
							|  |  |  |  | 			let indent -= indent - virtcol([opening_lnum, indent]) | 
					
						
							|  |  |  |  | 		endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		" Return if there are no previous lines to inherit from | 
					
						
							|  |  |  |  | 		if opening_lnum < 1 || opening_lnum >= lnum - 1 | 
					
						
							|  |  |  |  | 			call cursor(orig_lnum, orig_col) | 
					
						
							|  |  |  |  | 			return indent | 
					
						
							|  |  |  |  | 		endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		let bracket_count = 0 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		" Take the indent of the first previous non-white line that is | 
					
						
							|  |  |  |  | 		" at the same sexp level. cf. src/misc1.c:get_lisp_indent() | 
					
						
							|  |  |  |  | 		while 1 | 
					
						
							|  |  |  |  | 			let lnum = prevnonblank(lnum - 1) | 
					
						
							|  |  |  |  | 			let col = 1 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			if lnum <= opening_lnum | 
					
						
							|  |  |  |  | 				break | 
					
						
							|  |  |  |  | 			endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			call cursor(lnum, col) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			" Handle bracket counting edge case | 
					
						
							|  |  |  |  | 			if s:is_paren() | 
					
						
							|  |  |  |  | 				let bracket_count += s:bracket_type(s:current_char()) | 
					
						
							|  |  |  |  | 			endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			while 1 | 
					
						
							|  |  |  |  | 				if search('\v[(\[{}\])]', '', lnum) < 1 | 
					
						
							|  |  |  |  | 					break | 
					
						
							|  |  |  |  | 				elseif !s:ignored_region() | 
					
						
							|  |  |  |  | 					let bracket_count += s:bracket_type(s:current_char()) | 
					
						
							|  |  |  |  | 				endif | 
					
						
							|  |  |  |  | 			endwhile | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			if bracket_count == 0 | 
					
						
							|  |  |  |  | 				" Check if this is part of a multiline string | 
					
						
							|  |  |  |  | 				call cursor(lnum, 1) | 
					
						
							|  |  |  |  | 				if s:syn_id_name() !~? '\vstring|regex' | 
					
						
							|  |  |  |  | 					call cursor(orig_lnum, orig_col) | 
					
						
							|  |  |  |  | 					return indent(lnum) | 
					
						
							|  |  |  |  | 				endif | 
					
						
							|  |  |  |  | 			endif | 
					
						
							|  |  |  |  | 		endwhile | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		call cursor(orig_lnum, orig_col) | 
					
						
							|  |  |  |  | 		return indent | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 	endfunction | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	setlocal indentexpr=GetClojureIndent() | 
					
						
							| 
									
										
										
										
											2013-02-06 17:34:04 +01:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | else | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | 	" In case we have searchpairpos not available we fall back to | 
					
						
							|  |  |  |  | 	" normal lisp indenting. | 
					
						
							|  |  |  |  | 	setlocal indentexpr= | 
					
						
							|  |  |  |  | 	setlocal lisp | 
					
						
							|  |  |  |  | 	let b:undo_indent .= '| setlocal lisp<' | 
					
						
							| 
									
										
										
										
											2013-02-06 17:34:04 +01:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | endif | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | let &cpo = s:save_cpo | 
					
						
							|  |  |  |  | unlet! s:save_cpo | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-22 14:42:24 +02:00
										 |  |  |  | " vim:sts=8:sw=8:ts=8:noet |