diff --git a/clj/dev-resources/test-special-case-indent.in b/clj/dev-resources/test-special-case-indent.in new file mode 100644 index 0000000..badbd79 --- /dev/null +++ b/clj/dev-resources/test-special-case-indent.in @@ -0,0 +1,39 @@ +(let [x (fn [y] 1)] + (->> "ola" + (x))) + +(letfn [(x [y] 1)] + (->> "ola" + (x))) + +(->> "ola" + (x)) + +(defn foo [] + (letfn [(x [y] 1)] + (->> "ola" + (x)))) + +(letfn [(twice [x] + (* x 2)) + (six-times [y] +(* (twice y) 3))] + (println "Twice 15 =" (twice 15)) + (println "Six times 15 =" (six-times 15))) + +(letfn [(twice [x] + (* x 2))] + (->> "ola" + (x))) + +(letfn [(foo [x y] + (->> x + y + :bar)) +(twice [x] + (* x 2)) + (six-times [y] +(* (twice y) 3))] + (foo #{:foo :bar :biz} :foo)) + +;; vim:ft=clojure: diff --git a/clj/dev-resources/test-special-case-indent.out b/clj/dev-resources/test-special-case-indent.out new file mode 100644 index 0000000..b7b0c0e --- /dev/null +++ b/clj/dev-resources/test-special-case-indent.out @@ -0,0 +1,39 @@ +(let [x (fn [y] 1)] + (->> "ola" + (x))) + +(letfn [(x [y] 1)] + (->> "ola" + (x))) + +(->> "ola" + (x)) + +(defn foo [] + (letfn [(x [y] 1)] + (->> "ola" + (x)))) + +(letfn [(twice [x] + (* x 2)) + (six-times [y] + (* (twice y) 3))] + (println "Twice 15 =" (twice 15)) + (println "Six times 15 =" (six-times 15))) + +(letfn [(twice [x] + (* x 2))] + (->> "ola" + (x))) + +(letfn [(foo [x y] + (->> x + y + :bar)) + (twice [x] + (* x 2)) + (six-times [y] + (* (twice y) 3))] + (foo #{:foo :bar :biz} :foo)) + +;; vim:ft=clojure: diff --git a/clj/test/vim_clojure_static/indent_test.clj b/clj/test/vim_clojure_static/indent_test.clj index 8b09194..dd00476 100644 --- a/clj/test/vim_clojure_static/indent_test.clj +++ b/clj/test/vim_clojure_static/indent_test.clj @@ -33,3 +33,8 @@ (test-indent "dispatch macro indentation is handled correctly" :in "test-dispatch-macro-indent.in" :out "test-dispatch-macro-indent.out")) + +(deftest test-special-case-indent + (test-indent "special case indentation is handled correctly" + :in "test-special-case-indent.in" + :out "test-special-case-indent.out")) diff --git a/indent/clojure.vim b/indent/clojure.vim index ffa5820..75d82a0 100644 --- a/indent/clojure.vim +++ b/indent/clojure.vim @@ -169,7 +169,35 @@ if exists("*searchpairpos") call search('\S', 'W') let w = s:strip_namespace_and_macro_chars(s:current_word()) + if g:clojure_special_indent_words =~# '\V\<' . w . '\>' + + " `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 + return 1 endif