@@ -41,7 +41,7 @@ function! s:SyntaxMatch(pattern, line, col)
4141endfunction
4242
4343function ! s: IgnoredRegion ()
44- return s: SyntaxMatch (' \vstring |regex|comment|character' , line (' .' ), col (' .' ))
44+ return s: SyntaxMatch (' \(string\ |regex\ |comment\ |character\) ' , line (' .' ), col (' .' ))
4545endfunction
4646
4747function ! s: NotAStringDelimiter ()
@@ -80,47 +80,59 @@ function! s:ClosestMatch(match1, match2)
8080 endif
8181endfunction
8282
83+ " Wrapper around "searchpairpos" that will automatically set "s:best_match" to
84+ " the closest pair match and continuously optimise the "stopline" value for
85+ " later searches. This results in a significant performance gain by reducing
86+ " the number of syntax lookups that need to take place.
87+ function ! s: CheckPair (name, start , end , skipfn)
88+ let pos = searchpairpos (a: start , ' ' , a: end , ' bznW' , a: skipfn , s: best_match [1 ][0 ])
89+ let s: best_match = s: ClosestMatch (s: best_match , [a: name , pos])
90+ endfunction
91+
8392" Only need to search up. Never down.
8493function ! s: GetClojureIndent ()
8594 let lnum = v: lnum
8695
8796 " Move cursor to the first column of the line we want to indent.
8897 cursor (lnum, 0 )
8998
90- let matches = [
91- \ [' lst' , searchpairpos ( ' (' , ' ' , ' )' , ' bznW' , function (' <SID>IgnoredRegion' ))],
92- \ [' vec' , searchpairpos (' \[' , ' ' , ' \]' , ' bznW' , function (' <SID>IgnoredRegion' ))],
93- \ [' map' , searchpairpos ( ' {' , ' ' , ' }' , ' bznW' , function (' <SID>IgnoredRegion' ))],
94- \ [' reg' , s: IsInRegex () ? searchpairpos (' #\zs"' , ' ' , ' "' , ' bznW' , function (' <SID>NotARegexpDelimiter' )) : [0 , 0 ]],
95- \ [' str' , s: IsInString () ? searchpairpos (' "' , ' ' , ' "' , ' bznW' , function (' <SID>NotAStringDelimiter' )) : [0 , 0 ]]
96- \ ]
97- echom ' Matches' matches
99+ let s: best_match = [' top' , [0 , 0 ]]
100+
101+ call s: CheckPair (' lst' , ' (' , ' )' , function (' <SID>IgnoredRegion' ))
102+ call s: CheckPair (' vec' , ' \[' , ' \]' , function (' <SID>IgnoredRegion' ))
103+ call s: CheckPair (' map' , ' {' , ' }' , function (' <SID>IgnoredRegion' ))
104+
105+ if s: IsInString ()
106+ call s: CheckPair (' str' , ' "' , ' "' , function (' <SID>NotAStringDelimiter' ))
107+ elseif s: IsInRegex ()
108+ call s: CheckPair (' reg' , ' #\zs"' , ' "' , function (' <SID>NotARegexpDelimiter' ))
109+ endif
98110
99111 " Find closest matching higher form.
100- let [formtype, coord] = reduce (matches, function ( ' <SID>ClosestMatch ' ), [ ' top ' , [ 0 , 0 ]])
101- echom ' Match' formtype coord
112+ let [formtype, coord] = s: best_match
113+ " echom 'Match' formtype coord
102114
103115 if formtype == ' top'
104116 " At the top level, no indent.
105- echom ' At the top level!'
117+ " echom 'At the top level!'
106118 return 0
107119 elseif formtype == ' lst'
108- echom ' Special format rules!'
120+ " echom 'Special format rules!'
109121 " TODO
110122 " Grab text!
111- echom getline (coord[0 ], lnum - 1 )
123+ " echom getline(coord[0], lnum - 1)
112124 " Begin lexing!
113125 return coord[1 ] + 1
114126 elseif formtype == ' vec' || formtype == ' map'
115127 " Inside a vector, map or set.
116128 return coord[1 ]
117129 elseif formtype == ' reg'
118130 " Inside a regex.
119- echom ' Inside a regex!'
131+ " echom 'Inside a regex!'
120132 return coord[1 ] - (s: ShouldAlignMultiLineStrings () ? 0 : 2 )
121133 elseif formtype == ' str'
122134 " Inside a string.
123- echom ' Inside a string!'
135+ " echom 'Inside a string!'
124136 return coord[1 ] - (s: ShouldAlignMultiLineStrings () ? 0 : 1 )
125137 endif
126138
0 commit comments