Skip to content

Commit a4a4486

Browse files
committed
Import indent file from Vimclojure hg master
1 parent 278d553 commit a4a4486

1 file changed

Lines changed: 269 additions & 0 deletions

File tree

indent/clojure.vim

Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
" Vim indent file
2+
" Language: Clojure
3+
" Maintainer: Meikel Brandmeyer <mb@kotka.de>
4+
" URL: http://kotka.de/projects/clojure/vimclojure.html
5+
6+
" Only load this indent file when no other was loaded.
7+
if exists("b:did_indent")
8+
finish
9+
endif
10+
let b:did_indent = 1
11+
12+
let s:save_cpo = &cpo
13+
set cpo&vim
14+
15+
let b:undo_indent = "setlocal ai< si< lw< et< sts< sw< inde< indk<"
16+
17+
setlocal noautoindent expandtab nosmartindent
18+
19+
setlocal softtabstop=2
20+
setlocal shiftwidth=2
21+
22+
setlocal indentkeys=!,o,O
23+
24+
if exists("*searchpairpos")
25+
26+
function! s:MatchPairs(open, close, stopat)
27+
" Stop only on vector and map [ resp. {. Ignore the ones in strings and
28+
" comments.
29+
if a:stopat == 0
30+
let stopat = max([line(".") - g:vimclojure#SearchThreshold, 0])
31+
else
32+
let stopat = a:stopat
33+
endif
34+
35+
let pos = searchpairpos(a:open, '', a:close, 'bWn',
36+
\ 'vimclojure#util#SynIdName() !~ "clojureParen\\d"',
37+
\ stopat)
38+
return [ pos[0], virtcol(pos) ]
39+
endfunction
40+
41+
function! ClojureCheckForStringWorker() dict
42+
" Check whether there is the last character of the previous line is
43+
" highlighted as a string. If so, we check whether it's a ". In this
44+
" case we have to check also the previous character. The " might be the
45+
" closing one. In case the we are still in the string, we search for the
46+
" opening ". If this is not found we take the indent of the line.
47+
let nb = prevnonblank(v:lnum - 1)
48+
49+
if nb == 0
50+
return -1
51+
endif
52+
53+
call cursor(nb, 0)
54+
call cursor(0, col("$") - 1)
55+
if vimclojure#util#SynIdName() != "clojureString"
56+
return -1
57+
endif
58+
59+
" This will not work for a " in the first column...
60+
if vimclojure#util#Yank('l', 'normal! "lyl') == '"'
61+
call cursor(0, col("$") - 2)
62+
if vimclojure#util#SynIdName() != "clojureString"
63+
return -1
64+
endif
65+
if vimclojure#util#Yank('l', 'normal! "lyl') != '\\'
66+
return -1
67+
endif
68+
call cursor(0, col("$") - 1)
69+
endif
70+
71+
let p = searchpos('\(^\|[^\\]\)\zs"', 'bW')
72+
73+
if p != [0, 0]
74+
return p[1] - 1
75+
endif
76+
77+
return indent(".")
78+
endfunction
79+
80+
function! s:CheckForString()
81+
return vimclojure#util#WithSavedPosition({
82+
\ 'f' : function("ClojureCheckForStringWorker")
83+
\ })
84+
endfunction
85+
86+
function! ClojureIsMethodSpecialCaseWorker() dict
87+
" Find the next enclosing form.
88+
call vimclojure#util#MoveBackward()
89+
90+
" Special case: we are at a '(('.
91+
if vimclojure#util#Yank('l', 'normal! "lyl') == '('
92+
return 0
93+
endif
94+
call cursor(self.pos)
95+
96+
let nextParen = s:MatchPairs('(', ')', 0)
97+
98+
" Special case: we are now at toplevel.
99+
if nextParen == [0, 0]
100+
return 0
101+
endif
102+
call cursor(nextParen)
103+
104+
call vimclojure#util#MoveForward()
105+
let keyword = vimclojure#util#Yank('l', 'normal! "lye')
106+
if index([ 'deftype', 'defrecord', 'reify', 'proxy',
107+
\ 'extend-type', 'extend-protocol',
108+
\ 'letfn' ], keyword) >= 0
109+
return 1
110+
endif
111+
112+
return 0
113+
endfunction
114+
115+
function! s:IsMethodSpecialCase(position)
116+
let closure = {
117+
\ 'pos': a:position,
118+
\ 'f' : function("ClojureIsMethodSpecialCaseWorker")
119+
\ }
120+
121+
return vimclojure#util#WithSavedPosition(closure)
122+
endfunction
123+
124+
function! GetClojureIndent()
125+
" Get rid of special case.
126+
if line(".") == 1
127+
return 0
128+
endif
129+
130+
" We have to apply some heuristics here to figure out, whether to use
131+
" normal lisp indenting or not.
132+
let i = s:CheckForString()
133+
if i > -1
134+
return i
135+
endif
136+
137+
call cursor(0, 1)
138+
139+
" Find the next enclosing [ or {. We can limit the second search
140+
" to the line, where the [ was found. If no [ was there this is
141+
" zero and we search for an enclosing {.
142+
let paren = s:MatchPairs('(', ')', 0)
143+
let bracket = s:MatchPairs('\[', '\]', paren[0])
144+
let curly = s:MatchPairs('{', '}', bracket[0])
145+
146+
" In case the curly brace is on a line later then the [ or - in
147+
" case they are on the same line - in a higher column, we take the
148+
" curly indent.
149+
if curly[0] > bracket[0] || curly[1] > bracket[1]
150+
if curly[0] > paren[0] || curly[1] > paren[1]
151+
return curly[1]
152+
endif
153+
endif
154+
155+
" If the curly was not chosen, we take the bracket indent - if
156+
" there was one.
157+
if bracket[0] > paren[0] || bracket[1] > paren[1]
158+
return bracket[1]
159+
endif
160+
161+
" There are neither { nor [ nor (, ie. we are at the toplevel.
162+
if paren == [0, 0]
163+
return 0
164+
endif
165+
166+
" Now we have to reimplement lispindent. This is surprisingly easy, as
167+
" soon as one has access to syntax items.
168+
"
169+
" - Check whether we are in a special position after deftype, defrecord,
170+
" reify, proxy or letfn. These are special cases.
171+
" - Get the next keyword after the (.
172+
" - If its first character is also a (, we have another sexp and align
173+
" one column to the right of the unmatched (.
174+
" - In case it is in lispwords, we indent the next line to the column of
175+
" the ( + sw.
176+
" - If not, we check whether it is last word in the line. In that case
177+
" we again use ( + sw for indent.
178+
" - In any other case we use the column of the end of the word + 2.
179+
call cursor(paren)
180+
181+
if s:IsMethodSpecialCase(paren)
182+
return paren[1] + &shiftwidth - 1
183+
endif
184+
185+
" In case we are at the last character, we use the paren position.
186+
if col("$") - 1 == paren[1]
187+
return paren[1]
188+
endif
189+
190+
" In case after the paren is a whitespace, we search for the next word.
191+
normal! l
192+
if vimclojure#util#Yank('l', 'normal! "lyl') == ' '
193+
normal! w
194+
endif
195+
196+
" If we moved to another line, there is no word after the (. We
197+
" use the ( position for indent.
198+
if line(".") > paren[0]
199+
return paren[1]
200+
endif
201+
202+
" We still have to check, whether the keyword starts with a (, [ or {.
203+
" In that case we use the ( position for indent.
204+
let w = vimclojure#util#Yank('l', 'normal! "lye')
205+
if stridx('([{', w[0]) > 0
206+
return paren[1]
207+
endif
208+
209+
if &lispwords =~ '\<' . w . '\>'
210+
return paren[1] + &shiftwidth - 1
211+
endif
212+
213+
" XXX: Slight glitch here with special cases. However it's only
214+
" a heureustic. Offline we can't do more.
215+
if g:vimclojure#FuzzyIndent
216+
\ && w != 'with-meta'
217+
\ && w != 'clojure.core/with-meta'
218+
for pat in split(g:vimclojure#FuzzyIndentPatterns, ",")
219+
if w =~ '\(^\|/\)' . pat . '$'
220+
\ && w !~ '\(^\|/\)' . pat . '\*$'
221+
\ && w !~ '\(^\|/\)' . pat . '-fn$'
222+
return paren[1] + &shiftwidth - 1
223+
endif
224+
endfor
225+
endif
226+
227+
normal! w
228+
if paren[0] < line(".")
229+
return paren[1] + &shiftwidth - 1
230+
endif
231+
232+
normal! ge
233+
return virtcol(".") + 1
234+
endfunction
235+
236+
setlocal indentexpr=GetClojureIndent()
237+
238+
else
239+
240+
" In case we have searchpairpos not available we fall back to
241+
" normal lisp indenting.
242+
setlocal indentexpr=
243+
setlocal lisp
244+
let b:undo_indent .= " lisp<"
245+
246+
endif
247+
248+
" Defintions:
249+
setlocal lispwords=def,def-,defn,defn-,defmacro,defmacro-,defmethod,defmulti
250+
setlocal lispwords+=defonce,defvar,defvar-,defunbound,let,fn,letfn,binding,proxy
251+
setlocal lispwords+=defnk,definterface,defprotocol,deftype,defrecord,reify
252+
setlocal lispwords+=extend,extend-protocol,extend-type,bound-fn
253+
254+
" Conditionals and Loops:
255+
setlocal lispwords+=if,if-not,if-let,when,when-not,when-let,when-first
256+
setlocal lispwords+=condp,case,loop,dotimes,for,while
257+
258+
" Blocks:
259+
setlocal lispwords+=do,doto,try,catch,locking,with-in-str,with-out-str,with-open
260+
setlocal lispwords+=dosync,with-local-vars,doseq,dorun,doall,->,->>,future
261+
setlocal lispwords+=with-bindings
262+
263+
" Namespaces:
264+
setlocal lispwords+=ns,clojure.core/ns
265+
266+
" Java Classes:
267+
setlocal lispwords+=gen-class,gen-interface
268+
269+
let &cpo = s:save_cpo

0 commit comments

Comments
 (0)