folding.vim 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  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 Shortcuts {{{
  30. " Space as a Folding toggle in normal mode.
  31. nnoremap <silent> <space> @=(foldlevel('.')?'za':"\<space>")<CR>
  32. " Code folding options (spf13-vim)
  33. nmap <leader>f0 :set foldlevel=0<CR>
  34. nmap <leader>f1 :set foldlevel=1<CR>
  35. nmap <leader>f2 :set foldlevel=2<CR>
  36. nmap <leader>f3 :set foldlevel=3<CR>
  37. nmap <leader>f4 :set foldlevel=4<CR>
  38. nmap <leader>f5 :set foldlevel=5<CR>
  39. nmap <leader>f6 :set foldlevel=6<CR>
  40. nmap <leader>f7 :set foldlevel=7<CR>
  41. nmap <leader>f8 :set foldlevel=8<CR>
  42. nmap <leader>f9 :set foldlevel=9<CR>
  43. " }}}
  44. " Fold Highlighting {{{
  45. " Red fold text! (Pretty good with solarized-dark)
  46. highlight Folded term=none cterm=none ctermfg=darkred ctermbg=none guifg=darkred guibg=none
  47. " }}}
  48. " Fold Text {{{
  49. set foldtext=CustomFoldText()
  50. function! CustomFoldText()
  51. " At least vim 7.3. {{{
  52. " - Requirement for strdisplaywidth.
  53. if v:version < 703
  54. return foldtext()
  55. endif
  56. " }}}
  57. " Force dot fillchar. {{{
  58. " - The complicated line is to ensure we replace the fold fillchar only.
  59. let &l:fillchars = substitute(&l:fillchars,',\?fold:.','','gi')
  60. setlocal fillchars+=fold:.
  61. " }}}
  62. " Prepare script variables. {{{
  63. let foldChar = matchstr(&fillchars, 'fold:\zs.')
  64. let currWinWidth = winwidth(0)
  65. " }}}
  66. " Prepare fold indent. {{{
  67. " - Indent taken from first line in fold.
  68. let indentLevel = indent(v:foldstart)
  69. let indent = repeat(' ', indentLevel)
  70. " }}}
  71. " Prepare fold description. {{{
  72. " - Truncated to 1/3 of the current window width.
  73. let allFoldMarkers = split(&foldmarker, ',')
  74. let frontFoldMarker = allFoldMarkers[0]
  75. let lineRaw = substitute(getline(v:foldstart), '^\s*"\?\s*\|\s*"\?\s*'.frontFoldMarker.'\d*\s*', '', 'g')
  76. let line = '+ '.lineRaw.' '
  77. let foldDesc = strpart(line, 0, currWinWidth / 3)
  78. " }}}
  79. " Prepare the stat box. {{{
  80. " - Fixed stat box width at 18 characters.
  81. " - Count width by display cells instead of bytes if at least vim 7.4
  82. let lineCount = v:foldend - v:foldstart + 1
  83. if v:version >= 704
  84. let formatForm = 'S'
  85. else
  86. let formatForm = 's'
  87. endif
  88. let statBox = '| ' . printf('%18'.formatForm, lineCount.' lines, lvl '.v:foldlevel) . ' |'
  89. " }}}
  90. " Prepare filler lines. {{{
  91. " - endFiller is the fill after the stat box. Fixed at 5 characters.
  92. " - midFiller is the fill between the description and stat box.
  93. " - midFiller compensates for column widths generated by foldcolumn, number
  94. " and relativenumber.
  95. " - strdisplaywidth() seems to work. If multi-byte characters start to give
  96. " trouble, consider checking the more primitive solution in strlen() help.
  97. let endFiller = repeat(foldChar, 5)
  98. let midFillerLength = winwidth(0) - strdisplaywidth(indent.foldDesc.statBox.endFiller) - &foldcolumn
  99. if (&number || &relativenumber)
  100. let midFillerLength -= &numberwidth
  101. endif
  102. let midFiller = repeat(foldChar, midFillerLength)
  103. " }}}
  104. " Output the combined fold text. {{{
  105. return indent.foldDesc.midFiller.statBox.endFiller
  106. " }}}
  107. endfunction
  108. " }}}
  109. endif