folding.vim 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. " Folding - Modeline and Notes {{{
  2. " vim: set sw=2 ts=2 sts=2 et tw=78 foldmarker={{{,}}} foldlevel=0 foldmethod=marker spell:
  3. "
  4. " cinaeco/dotfiles Folding Settings
  5. "
  6. " These are settings to make folding easier to use and look at:
  7. " - Indented Folds to match their first line.
  8. " - Stat box to right displays line count and fold level.
  9. " - Coloured distinctly red!
  10. " (sounds harsh, but actually works well with solarized-dark!)
  11. " - Fillchar is forced to '.' rather than '-'.
  12. " (easier on eyes)
  13. " - SpaceBar toggles folds, if any.
  14. " (much more convenient than the 'z' commands)
  15. " - SPF13-VIM provides quick foldlevel setting map: <Leader>f[0-9]
  16. " (useful with stat box lvl)
  17. "
  18. " Note that custom foldtext will only work for vim 7.3+. For earlier
  19. " versions of vim, only the colouring and spacebar mapping will take effect.
  20. "
  21. " TODO:
  22. " - Fold description is just the first line found. Haven't really
  23. " understood the regex, but could perhaps make it better.
  24. " - Fold description current truncation rule is 1/3 of the window width.
  25. " Perhaps this could be some less arbitrary rule?
  26. "
  27. " }}}
  28. if has('folding')
  29. " Keyboard Shortcut {{{
  30. " Space as a Folding toggle in normal mode.
  31. nnoremap <silent> <space> @=(foldlevel('.')?'za':"\<space>")<CR>
  32. " }}}
  33. " Fold Highlighting {{{
  34. " Red fold text! (Pretty good with solarized-dark)
  35. highlight Folded term=none cterm=none ctermfg=darkred ctermbg=none guifg=darkred guibg=none
  36. " }}}
  37. " Fold Text {{{
  38. set foldtext=CustomFoldText()
  39. function! CustomFoldText()
  40. " At least vim 7.3. {{{
  41. " - Requirement for strdisplaywidth.
  42. if v:version < 703
  43. return foldtext()
  44. endif
  45. " }}}
  46. " Force dot fillchar. {{{
  47. " - The complicated line is to ensure we replace the fold fillchar only.
  48. let &l:fillchars = substitute(&l:fillchars,',\?fold:.','','gi')
  49. setlocal fillchars+=fold:.
  50. " }}}
  51. " Prepare script variables. {{{
  52. let foldChar = matchstr(&fillchars, 'fold:\zs.')
  53. let currWinWidth = winwidth(0)
  54. " }}}
  55. " Prepare fold indent. {{{
  56. " - Indent taken from first line in fold.
  57. let indentLevel = indent(v:foldstart)
  58. let indent = repeat(' ', indentLevel)
  59. " }}}
  60. " Prepare fold description. {{{
  61. " - Truncated to 1/3 of the current window width.
  62. let allFoldMarkers = split(&foldmarker, ',')
  63. let frontFoldMarker = allFoldMarkers[0]
  64. let lineRaw = substitute(getline(v:foldstart), '^\s*"\?\s*\|\s*"\?\s*'.frontFoldMarker.'\d*\s*', '', 'g')
  65. let line = '+ '.lineRaw.' '
  66. let foldDesc = strpart(line, 0, currWinWidth / 3)
  67. " }}}
  68. " Prepare the stat box. {{{
  69. " - Fixed stat box width at 18 characters.
  70. " - Count width by display cells instead of bytes if at least vim 7.4
  71. let lineCount = v:foldend - v:foldstart + 1
  72. if v:version >= 704
  73. let formatForm = 'S'
  74. else
  75. let formatForm = 's'
  76. endif
  77. let statBox = '| ' . printf('%18'.formatForm, lineCount.' lines, lvl '.v:foldlevel) . ' |'
  78. " }}}
  79. " Prepare filler lines. {{{
  80. " - endFiller is the fill after the stat box. Fixed at 5 characters.
  81. " - midFiller is the fill between the description and stat box.
  82. " - midFiller compensates for column widths generated by foldcolumn, number
  83. " and relativenumber.
  84. " - strdisplaywidth() seems to work. If multi-byte characters start to give
  85. " trouble, consider checking the more primitive solution in strlen() help.
  86. let endFiller = repeat(foldChar, 5)
  87. let midFillerLength = winwidth(0) - strdisplaywidth(indent.foldDesc.statBox.endFiller) - &foldcolumn
  88. if (&number || &relativenumber)
  89. let midFillerLength -= &numberwidth
  90. endif
  91. let midFiller = repeat(foldChar, midFillerLength)
  92. " }}}
  93. " Output the combined fold text. {{{
  94. return indent.foldDesc.midFiller.statBox.endFiller
  95. " }}}
  96. endfunction
  97. " }}}
  98. endif