@@ -15,15 +15,13 @@ let b:did_indent = 1
1515let s: save_cpo = &cpoptions
1616set cpoptions &vim
1717
18- let b: undo_indent = ' setlocal autoindent< smartindent< expandtab< softtabstop< shiftwidth< indentexpr< indentkeys<'
18+ let b: undo_indent = ' setlocal autoindent< smartindent< expandtab< softtabstop< shiftwidth< indentexpr< indentkeys< lisp< '
1919
20- setlocal noautoindent nosmartindent
20+ setlocal noautoindent nosmartindent nolisp
2121setlocal softtabstop = 2 shiftwidth = 2 expandtab
2222setlocal indentkeys = ! ,o ,O
2323
24- " TODO: ignore 'lisp' and 'lispwords' options (actually, turn them off?)
25- " TODO: Optional Vim9script implementations of hotspot/bottleneck functions?
26- " FIXME: fallback case when syntax highlighting is disabled.
24+ " TODO: Write an optional Vim9 script version for better performance?
2725
2826function ! s: GetSynIdName (line , col )
2927 return synIDattr (synID (a: line , a: col , 0 ), ' name' )
@@ -37,11 +35,11 @@ function! s:IgnoredRegion()
3735 return s: SyntaxMatch (' \(string\|regex\|comment\|character\)' , line (' .' ), col (' .' ))
3836endfunction
3937
40- function ! s: NotAStringDelimiter ()
38+ function ! s: NotStringDelimiter ()
4139 return ! s: SyntaxMatch (' stringdelimiter' , line (' .' ), col (' .' ))
4240endfunction
4341
44- function ! s: NotARegexpDelimiter ()
42+ function ! s: NotRegexpDelimiter ()
4543 return ! s: SyntaxMatch (' regexpdelimiter' , line (' .' ), col (' .' ))
4644endfunction
4745
@@ -54,53 +52,53 @@ function! s:ShouldAlignMultiLineStrings()
5452endfunction
5553
5654" Wrapper around "searchpairpos" that will automatically set "s:best_match" to
57- " the closest pair match and continuously optimise the "stopline" value for
58- " later searches. This results in a significant performance gain by reducing
59- " the number of syntax lookups that need to take place.
60- function ! s: CheckPair (name, start , end , skipfn )
55+ " the closest pair match and optimises the "stopline" value for later
56+ " searches. This results in a significant performance gain by reducing the
57+ " number of syntax lookups that need to take place.
58+ function ! s: CheckPair (name, start , end , SkipFn )
6159 let prevln = s: best_match [1 ][0 ]
62- let pos = searchpairpos (a: start , ' ' , a: end , ' bznW' , a: skipfn , prevln)
60+ let pos = searchpairpos (a: start , ' ' , a: end , ' bznW' , a: SkipFn , prevln)
6361 if prevln < pos[0 ] || (prevln == pos[0 ] && s: best_match [1 ][1 ] < pos[1 ])
6462 let s: best_match = [a: name , pos]
6563 endif
6664endfunction
6765
6866function ! s: GetClojureIndent ()
69- let lnum = v: lnum
70-
7167 " Move cursor to the first column of the line we want to indent.
72- cursor (lnum, 0 )
68+ call cursor (v: lnum , 0 )
7369
7470 let s: best_match = [' top' , [0 , 0 ]]
7571
76- call s: CheckPair (' lst' , ' (' , ' )' , function (' <SID>IgnoredRegion' ))
77- call s: CheckPair (' map' , ' {' , ' }' , function (' <SID>IgnoredRegion' ))
78- call s: CheckPair (' vec' , ' \[' , ' \]' , function (' <SID>IgnoredRegion' ))
72+ let IgnoredRegionFn = function (' <SID>IgnoredRegion' )
73+
74+ call s: CheckPair (' lst' , ' (' , ' )' , IgnoredRegionFn)
75+ call s: CheckPair (' map' , ' {' , ' }' , IgnoredRegionFn)
76+ call s: CheckPair (' vec' , ' \[' , ' \]' , IgnoredRegionFn)
7977
80- let synname = s: GetSynIdName (lnum, col (' .' ))
78+ let synname = s: GetSynIdName (v: lnum , col (' .' ))
8179 if synname = ~? ' string'
82- call s: CheckPair (' str' , ' "' , ' "' , function (' <SID>NotAStringDelimiter ' ))
80+ call s: CheckPair (' str' , ' "' , ' "' , function (' <SID>NotStringDelimiter ' ))
8381 elseif synname = ~? ' regex'
84- call s: CheckPair (' reg' , ' #\zs"' , ' "' , function (' <SID>NotARegexpDelimiter ' ))
82+ call s: CheckPair (' reg' , ' #\zs"' , ' "' , function (' <SID>NotRegexpDelimiter ' ))
8583 endif
8684
8785 " Find closest matching higher form.
8886 let [formtype, coord] = s: best_match
89- " echom 'Match' formtype coord
9087
9188 if formtype == ' top'
9289 " At the top level, no indent.
9390 return 0
9491 elseif formtype == ' lst'
9592 " Inside a list.
9693 " TODO Begin analysis and apply rules!
97- " echom getline(coord[0], lnum - 1)
94+ " echom getline(coord[0], v: lnum - 1)
9895 return coord[1 ] + 1
9996 elseif formtype == ' vec' || formtype == ' map'
10097 " Inside a vector, map or set.
10198 return coord[1 ]
10299 elseif formtype == ' str'
103100 " Inside a string.
101+ " TODO: maintain string and regex indentation when `=` is pressed.
104102 return coord[1 ] - (s: ShouldAlignMultiLineStrings () ? 0 : 1 )
105103 elseif formtype == ' reg'
106104 " Inside a regex.
@@ -110,16 +108,13 @@ function! s:GetClojureIndent()
110108 return 2
111109endfunction
112110
113-
114- setlocal indentexpr = s: GetClojureIndent ()
115-
116-
117- " TODO: if exists("*searchpairpos")
118- " In case we have searchpairpos not available we fall back to normal lisp
119- " indenting.
120- " setlocal indentexpr=
121- " setlocal lisp
122- " let b:undo_indent .= '| setlocal lisp<'
111+ if exists (" *searchpairpos" )
112+ setlocal indentexpr = s: GetClojureIndent ()
113+ else
114+ " If searchpairpos is not available, fallback to normal lisp
115+ " indenting.
116+ setlocal lisp indentexpr =
117+ endif
123118
124119let &cpoptions = s: save_cpo
125120unlet ! s: save_cpo
0 commit comments