Skip to content

Commit bdbc281

Browse files
committedMay 1, 2023
Reader indent algorithm perf has surpassed the prev syntax highlight one
The performance of the new reader-like indentation algorithm has now surpassed the performance of my previous syntax highlighting approach with better accuracy and no hacky code required.
1 parent ee2acc2 commit bdbc281

File tree

1 file changed

+26
-17
lines changed

1 file changed

+26
-17
lines changed
 

‎indent/clojure.vim

+26-17
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ setlocal noautoindent nosmartindent nolisp
2121
setlocal softtabstop=2 shiftwidth=2 expandtab
2222
setlocal indentkeys=!,o,O
2323

24+
" NOTE: To debug this code, make sure to "set debug+=msg" otherwise errors
25+
" will occur silently.
26+
2427
" TODO: After all optimisations create Vim9script variant of the core algorithm.
2528

2629
" Returns "1" if position "i_char" in "line_str" is preceded by an odd number
@@ -65,8 +68,9 @@ endfunction
6568

6669
let s:pairs = {'(': ')', '[': ']', '{': '}'}
6770

68-
" TODO: refactor this procedure and optimise.
69-
" This procedure is essentially a lightweight Clojure reader.
71+
" This procedure is kind of like a really lightweight Clojure reader. It
72+
" looks at the lines above the current line, tokenises them (from right to
73+
" left), and performs reductions to find the parent form and where it is.
7074
function! s:InsideForm(lnum)
7175
" Reset cursor to first column of the line we wish to indent.
7276
call cursor(a:lnum, 1)
@@ -80,25 +84,29 @@ function! s:InsideForm(lnum)
8084
while lnum > 0
8185
" Reduce tokens from line "lnum" into "tokens".
8286
for tk in s:TokeniseLine(lnum)
83-
" Keep track of the first string delimiter we see, as
84-
" we'll need it later for multi-line strings/regexps.
85-
if first_string_pos == [] && tk[0] ==# '"'
86-
let first_string_pos = tk[1]
87-
endif
87+
if tk[0] ==# '"'
88+
" Keep track of the first string delimiter we
89+
" see, as we'll need it later for multi-line
90+
" strings/regexps.
91+
if first_string_pos == []
92+
let first_string_pos = tk[1]
93+
endif
94+
95+
if ! empty(tokens) && tokens[-1][0] ==# '"'
96+
let in_string = 0
97+
call remove(tokens, -1)
98+
else
99+
let in_string = 1
100+
call add(tokens, tk)
101+
endif
88102

89-
" When in string ignore other tokens.
90-
if in_string && tk[0] !=# '"'
91103
continue
92-
else
93-
let in_string = 0
94104
endif
95105

96-
" TODO: early termination?
97-
if empty(tokens)
98-
call add(tokens, tk)
99-
elseif tk[0] ==# '"' && tokens[-1][0] ==# '"'
100-
call remove(tokens, -1)
101-
elseif get(s:pairs, tk[0], '') ==# tokens[-1][0]
106+
" When in string ignore other tokens.
107+
if in_string | continue | endif
108+
109+
if ! empty(tokens) && get(s:pairs, tk[0], '') ==# tokens[-1][0]
102110
" Matching pair: drop the last item in tokens.
103111
call remove(tokens, -1)
104112
else
@@ -184,6 +192,7 @@ function! s:ClojureIndent()
184192
endfunction
185193

186194
" TODO: set lispoptions if exists.
195+
" https://github.com/vim/vim/commit/49846fb1a31de99f49d6a7e70efe685197423c84
187196
setlocal indentexpr=s:ClojureIndent()
188197

189198
let &cpoptions = s:save_cpo

0 commit comments

Comments
 (0)
Please sign in to comment.