|
|
@@ -1,11 +1,11 @@
|
|
|
" Folding - Modeline and Notes {{{
|
|
|
-" vim: set sw=2 ts=2 sts=2 et tw=78 foldmarker={{{,}}} foldlevel=0 foldmethod=marker spell:
|
|
|
+" vim: set sw=2 ts=2 sts=2 et tw=78 foldmarker={{{,}}} foldlevel=0 foldmethod=marker:
|
|
|
"
|
|
|
" cinaeco/dotfiles Folding Settings
|
|
|
"
|
|
|
" These are settings to make folding easier to use and look at:
|
|
|
" - Indented Folds to match their first line.
|
|
|
-" - Stat box to right displays line count and fold level.
|
|
|
+" - Statbox to right displays line count and fold level.
|
|
|
" - Coloured distinctly red!
|
|
|
" (sounds harsh, but actually works well with solarized-dark!)
|
|
|
" - Fillchar is forced to '.' rather than '-'.
|
|
|
@@ -13,7 +13,7 @@
|
|
|
" - SpaceBar toggles folds, if any.
|
|
|
" (much more convenient than the 'z' commands)
|
|
|
" - SPF13-VIM provides quick foldlevel setting map: <Leader>f[0-9]
|
|
|
-" (useful with stat box lvl)
|
|
|
+" (useful with statbox lvl)
|
|
|
"
|
|
|
" Note that custom foldtext will only work for vim 7.3+. For earlier
|
|
|
" versions of vim, only the colouring and spacebar mapping will take effect.
|
|
|
@@ -46,79 +46,200 @@ if has('folding')
|
|
|
" }}}
|
|
|
|
|
|
" Fold Highlighting {{{
|
|
|
- " Red fold text! (Pretty good with solarized-dark)
|
|
|
- highlight Folded term=none cterm=none ctermfg=darkred ctermbg=none guifg=darkred guibg=none
|
|
|
+ highlight Folded term=none cterm=none ctermfg=darkgrey ctermbg=none guifg=darkgrey guibg=none
|
|
|
" }}}
|
|
|
|
|
|
" Fold Text {{{
|
|
|
set foldtext=CustomFoldText()
|
|
|
|
|
|
- function! CustomFoldText()
|
|
|
+ function! CustomFoldText(...)
|
|
|
|
|
|
- " At least vim 7.3. {{{
|
|
|
- " - Requirement for strdisplaywidth.
|
|
|
+ " At least vim 7.3 {{{
|
|
|
+ " - Requirement for strdisplaywidth().
|
|
|
+ " - strdisplaywidth() seems to work. If multi-byte characters start to give
|
|
|
+ " trouble, consider checking the more primitive solution in strlen() help.
|
|
|
if v:version < 703
|
|
|
return foldtext()
|
|
|
endif
|
|
|
" }}}
|
|
|
|
|
|
- " Force dot fillchar. {{{
|
|
|
- " - The complicated line is to ensure we replace the fold fillchar only.
|
|
|
+ " Common variables for all foldmethods {{{
|
|
|
+ let lineCount = v:foldend - v:foldstart + 1
|
|
|
+ let displayWidth = winwidth(0) - &foldcolumn
|
|
|
+ if (&number || &relativenumber)
|
|
|
+ let displayWidth -= &numberwidth
|
|
|
+ endif
|
|
|
+ let foldChar = '┄'
|
|
|
+ " }}}
|
|
|
+
|
|
|
+ " Set fold fillchar {{{
|
|
|
+ " - This complicated line is to ensure we replace the fold fillchar only.
|
|
|
let &l:fillchars = substitute(&l:fillchars,',\?fold:.','','gi')
|
|
|
- setlocal fillchars+=fold:.
|
|
|
+ exec 'setlocal fillchars+=fold:' . foldChar
|
|
|
" }}}
|
|
|
|
|
|
- " Prepare script variables. {{{
|
|
|
- let foldChar = matchstr(&fillchars, 'fold:\zs.')
|
|
|
- let currWinWidth = winwidth(0)
|
|
|
+ " Handle diff foldmethod {{{
|
|
|
+ " - Display a centre-aligned statbox with the number of lines.
|
|
|
+ if &foldmethod == 'diff'
|
|
|
+
|
|
|
+ " Prepare the statbox {{{
|
|
|
+ let statBox = printf('[ %s matching lines ]', lineCount)
|
|
|
+ " }}}
|
|
|
+
|
|
|
+ " Prepare filler lines {{{
|
|
|
+ let filler = repeat(foldChar, (displayWidth - strchars(statBox)) / 2)
|
|
|
+ " }}}
|
|
|
+
|
|
|
+ " Output the combined fold text {{{
|
|
|
+ return filler.statBox
|
|
|
+ " }}}
|
|
|
+
|
|
|
+ endif
|
|
|
" }}}
|
|
|
|
|
|
- " Prepare fold indent. {{{
|
|
|
- " - Indent taken from first line in fold.
|
|
|
- let indentLevel = indent(v:foldstart)
|
|
|
- let indent = repeat(' ', indentLevel)
|
|
|
+ " Handle all other foldmethods {{{
|
|
|
+
|
|
|
+ " Prepare fold indent and indicator {{{
|
|
|
+ " - If indent allows, build the indicator into it.
|
|
|
+ let foldIndicator = '▸ '
|
|
|
+ let indLen = strdisplaywidth(foldIndicator)
|
|
|
+ if indent(v:foldstart) >= indLen
|
|
|
+ let indent = repeat(' ', indent(v:foldstart) - indLen) . foldIndicator
|
|
|
+ else
|
|
|
+ let indent = repeat(' ', indent(v:foldstart))
|
|
|
+ endif
|
|
|
+ " }}}
|
|
|
+
|
|
|
+ " Prepare the statbox {{{
|
|
|
+ " - Fixed statbox width at 18 characters.
|
|
|
+ " - Count width by display cells instead of bytes if at least vim 7.4
|
|
|
+ if v:version >= 704
|
|
|
+ let countType = 'S'
|
|
|
+ else
|
|
|
+ let countType = 's'
|
|
|
+ endif
|
|
|
+ let statBox = '[ ' . printf('%14'.countType, lineCount.' lns, lv '.v:foldlevel) . ' ]'
|
|
|
+ " }}}
|
|
|
+
|
|
|
+ " Prepare fold description {{{
|
|
|
+ " - Remove fold markers and comment markers.
|
|
|
+ " - Truncate to 1/3 of the current window width.
|
|
|
+
|
|
|
+ " Use function argument as line text if provided {{{
|
|
|
+ let line = a:0 > 0 ? a:1 : getline(v:foldstart)
|
|
|
+ " }}}
|
|
|
+
|
|
|
+ " Remove fold markers {{{
|
|
|
+ let foldmarkers = split(&foldmarker, ',')
|
|
|
+ let line = substitute(line, '\V' . foldmarkers[0] . '\%(\d\+\)\?\s\*', '', '')
|
|
|
+ " }}}
|
|
|
+
|
|
|
+ " Remove surrounding whitespace {{{
|
|
|
+ let line = substitute(line, '^\s*\(.\{-}\)\s*$', '\1', '')
|
|
|
+ " }}}
|
|
|
+
|
|
|
+ " Add an extra space at the end {{{
|
|
|
+ let foldDesc = line.' '
|
|
|
+ " }}}
|
|
|
+
|
|
|
+ " }}}
|
|
|
+
|
|
|
+ " Prepare filler lines {{{
|
|
|
+ " - midFiller is the fill between the description and statbox.
|
|
|
+ " - midFiller compensates for column widths generated by foldcolumn, number
|
|
|
+ " and relativenumber.
|
|
|
+ let endFiller = repeat(foldChar, 1)
|
|
|
+ let midFillerLength = displayWidth - strdisplaywidth(indent.foldDesc.statBox.endFiller)
|
|
|
+ let midFiller = repeat(foldChar, midFillerLength)
|
|
|
+ " }}}
|
|
|
+
|
|
|
+ " Output the combined fold text {{{
|
|
|
+ return indent.foldDesc.midFiller.statBox.endFiller
|
|
|
+ " }}}
|
|
|
+
|
|
|
" }}}
|
|
|
|
|
|
- " Prepare fold description. {{{
|
|
|
- " - Truncated to 1/3 of the current window width.
|
|
|
- let allFoldMarkers = split(&foldmarker, ',')
|
|
|
- let frontFoldMarker = allFoldMarkers[0]
|
|
|
- let lineRaw = substitute(getline(v:foldstart), '^\s*"\?\s*\|\s*"\?\s*'.frontFoldMarker.'\d*\s*', '', 'g')
|
|
|
- let line = '+ '.lineRaw.' '
|
|
|
- let foldDesc = strpart(line, 0, currWinWidth / 3)
|
|
|
+ endfunction
|
|
|
+ " }}}
|
|
|
+
|
|
|
+ " Lokaltog's Fold Text for learning more stuff about fold description preparation {{{
|
|
|
+ function! FoldText(...)
|
|
|
+ " This function uses code from doy's vim-foldtext: https://github.com/doy/vim-foldtext
|
|
|
+ " Prepare fold variables {{{
|
|
|
+ " Use function argument as line text if provided
|
|
|
+ let l:line = a:0 > 0 ? a:1 : getline(v:foldstart)
|
|
|
+
|
|
|
+ let l:line_count = v:foldend - v:foldstart + 1
|
|
|
+ let l:indent = repeat(' ', indent(v:foldstart))
|
|
|
+
|
|
|
+ let l:w_win = winwidth(0)
|
|
|
+ let l:w_num = getwinvar(0, '&number') * getwinvar(0, '&numberwidth')
|
|
|
+ let l:w_fold = getwinvar(0, '&foldcolumn')
|
|
|
" }}}
|
|
|
+ " Handle diff foldmethod {{{
|
|
|
+ if &fdm == 'diff'
|
|
|
+ let l:text = printf('┤ %s matching lines ├', l:line_count)
|
|
|
|
|
|
- " Prepare the stat box. {{{
|
|
|
- " - Fixed stat box width at 18 characters.
|
|
|
- " - Count width by display cells instead of bytes if at least vim 7.4
|
|
|
- let lineCount = v:foldend - v:foldstart + 1
|
|
|
- if v:version >= 704
|
|
|
- let formatForm = 'S'
|
|
|
- else
|
|
|
- let formatForm = 's'
|
|
|
+ " Center-align the foldtext
|
|
|
+ return repeat('┄', (l:w_win - strchars(l:text) - l:w_num - l:w_fold) / 2) . l:text
|
|
|
endif
|
|
|
- let statBox = '| ' . printf('%18'.formatForm, lineCount.' lines, lvl '.v:foldlevel) . ' |'
|
|
|
" }}}
|
|
|
+ " Handle other foldmethods {{{
|
|
|
+ let l:text = l:line
|
|
|
+ " Remove foldmarkers {{{
|
|
|
+ let l:foldmarkers = split(&foldmarker, ',')
|
|
|
+ let l:text = substitute(l:text, '\V' . l:foldmarkers[0] . '\%(\d\+\)\?\s\*', '', '')
|
|
|
+ " }}}
|
|
|
+ " Remove comments {{{
|
|
|
+ let l:comment = split(&commentstring, '%s')
|
|
|
|
|
|
- " Prepare filler lines. {{{
|
|
|
- " - endFiller is the fill after the stat box. Fixed at 5 characters.
|
|
|
- " - midFiller is the fill between the description and stat box.
|
|
|
- " - midFiller compensates for column widths generated by foldcolumn, number
|
|
|
- " and relativenumber.
|
|
|
- " - strdisplaywidth() seems to work. If multi-byte characters start to give
|
|
|
- " trouble, consider checking the more primitive solution in strlen() help.
|
|
|
- let endFiller = repeat(foldChar, 5)
|
|
|
- let midFillerLength = winwidth(0) - strdisplaywidth(indent.foldDesc.statBox.endFiller) - &foldcolumn
|
|
|
- if (&number || &relativenumber)
|
|
|
- let midFillerLength -= &numberwidth
|
|
|
+ if l:comment[0] != ''
|
|
|
+ let l:comment_begin = l:comment[0]
|
|
|
+ let l:comment_end = ''
|
|
|
+
|
|
|
+ if len(l:comment) > 1
|
|
|
+ let l:comment_end = l:comment[1]
|
|
|
+ endif
|
|
|
+
|
|
|
+ let l:pattern = '\V' . l:comment_begin . '\s\*' . l:comment_end . '\s\*\$'
|
|
|
+
|
|
|
+ if l:text =~ l:pattern
|
|
|
+ let l:text = substitute(l:text, l:pattern, ' ', '')
|
|
|
+ else
|
|
|
+ let l:text = substitute(l:text, '.*\V' . l:comment_begin, ' ', '')
|
|
|
+
|
|
|
+ if l:comment_end != ''
|
|
|
+ let l:text = substitute(l:text, '\V' . l:comment_end, ' ', '')
|
|
|
+ endif
|
|
|
+ endif
|
|
|
endif
|
|
|
- let midFiller = repeat(foldChar, midFillerLength)
|
|
|
" }}}
|
|
|
-
|
|
|
- " Output the combined fold text. {{{
|
|
|
- return indent.foldDesc.midFiller.statBox.endFiller
|
|
|
+ " Remove preceding non-word characters {{{
|
|
|
+ let l:text = substitute(l:text, '^\W*', '', '')
|
|
|
+ " }}}
|
|
|
+ " Remove surrounding whitespace {{{
|
|
|
+ let l:text = substitute(l:text, '^\s*\(.\{-}\)\s*$', '\1', '')
|
|
|
+ " }}}
|
|
|
+ " Make unmatched block delimiters prettier {{{
|
|
|
+ let l:text = substitute(l:text, '([^)]*$', '⟯ ⋯ ⟮', '')
|
|
|
+ let l:text = substitute(l:text, '{[^}]*$', '⟯ ⋯ ⟮', '')
|
|
|
+ let l:text = substitute(l:text, '\[[^\]]*$', '⟯ ⋯ ⟮', '')
|
|
|
" }}}
|
|
|
+ " Add arrows when indent level > 2 spaces {{{
|
|
|
+ if indent(v:foldstart) > 2
|
|
|
+ let l:cline = substitute(l:line, '^\s*\(.\{-}\)\s*$', '\1', '')
|
|
|
+ let l:clen = strlen(matchstr(l:cline, '^\W*'))
|
|
|
|
|
|
+ let l:indent = repeat(' ', indent(v:foldstart) - 2)
|
|
|
+ let l:text = '▸ ' . l:text
|
|
|
+ endif
|
|
|
+ " }}}
|
|
|
+ " Prepare fold text {{{
|
|
|
+ let l:fnum = printf('┤ %s ⭡ ', printf('%4s', l:line_count))
|
|
|
+ let l:ftext = printf('%s%s ', l:indent, l:text)
|
|
|
+ " }}}
|
|
|
+ return l:ftext . repeat('┄', l:w_win - strchars(l:fnum) - strchars(l:ftext) - l:w_num - l:w_fold) . l:fnum
|
|
|
+ " }}}
|
|
|
endfunction
|
|
|
" }}}
|
|
|
|