vim/ftplugin/clojure/folding.vim @ 4e0ee24c82a7
More
author |
Steve Losh <steve@stevelosh.com> |
date |
Thu, 01 Feb 2024 08:33:56 -0500 |
parents |
68b8d179f0d4 |
children |
(none) |
if exists('loaded_clojurefolding') || &cp
finish
endif
let loaded_clojurefolding=1
if !exists('g:clojure_fold_extra')
let g:clojure_fold_extra = []
endif
let s:folded_forms = [
\ 'def',
\ 'defn',
\ 'defn-',
\ 'defprotocol',
\ 'defmacro',
\ 'defmethod',
\ 'defmulti',
\ 'defonce',
\ 'defspec',
\ 'defrecord',
\ 'defpartial',
\ 'extend-type',
\ 'extend-protocol',
\ 'deftest',
\ 'ns'
\ ] + g:clojure_fold_extra
let s:form_re = '\v^\((' . join(s:folded_forms, '|') . ')\s'
let s:form_re_bare = '\v^\((' . join(s:folded_forms, '|') . ')$'
function! s:NextNonBlankLineContents(start)
let lnum = a:start
let max = line("$")
while 1
let lnum += 1
" If we've run off the end of the file, return a blank string as
" a sentinel.
if lnum > max
return ""
endif
" Otherwise, get the contents.
let contents = getline(lnum)
" If they're non-blank, return it. Otherwise we'll loop to the next
" line.
if contents =~ '\v\S'
return contents
endif
endwhile
endfunction
function! GetClojureFold()
let line = getline(v:lnum)
if line =~ s:form_re || line =~ s:form_re_bare
" We're on one of the forms we want to fold.
let nextline = s:NextNonBlankLineContents(v:lnum)
" If we've run off the end of the file, this means we're on a top-level
" form with no later nonblank lines in the file. This has to be a one
" liner, because there's no content left that could be closing parens!
if nextline == ""
return 0
elseif nextline =~ '\v^\s+'
" If it's indented, this almost certainly isn't a one-liner. Fold
" away!
return ">1"
else
" Otherwise, the next non-blank line after this one is not
" indented. This means we're on a one-liner, so we don't want to
" fold.
return 0
endif
elseif line =~ '^\s*$'
" We need to look at the next non-blank line to determine how to fold
" blank lines.
let nextline = s:NextNonBlankLineContents(v:lnum)
" If we've run off the end of the file, this means we're on one of
" a series of blank lines ending the file. They shouldn't be folded
" with anything.
if nextline == ""
return 0
elseif nextline =~ '\v^\s+'
" If it's indented, we're in the middle of an existing form.
" Just fold with that.
return "="
else
" Otherwise, the next non-blank line after this one is not
" indented. That means we need to close any existing folds
" here.
return "<1"
endif
elseif line =~ '\v^\s+\S'
" Indented content, fold it into any existing folds.
return "="
else
" We are sitting on a non-blank, non-indented line, but it's not one of
" our special top-level forms, so we'll just leave it alone.
return 0
endif
endfunction
function! TurnOnClojureFolding()
setlocal foldexpr=GetClojureFold()
setlocal foldmethod=expr
endfunction