RstFold.vim 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. " Author: Antony Lee <anntzer.lee@gmail.com>
  2. " Description: Helper functions for reStructuredText syntax folding
  3. " Last Modified: 2018-12-29
  4. function s:CacheRstFold()
  5. if !g:rst_fold_enabled
  6. return
  7. endif
  8. let closure = {'header_types': {}, 'max_level': 0, 'levels': {}}
  9. function closure.Process(match) dict
  10. let curline = getcurpos()[1]
  11. if has_key(self.levels, curline - 1)
  12. " For over+under-lined headers, the regex will match both at the
  13. " overline and at the title itself; in that case, skip the second match.
  14. return
  15. endif
  16. let lines = split(a:match, '\n')
  17. let key = repeat(lines[-1][0], len(lines))
  18. if !has_key(self.header_types, key)
  19. let self.max_level += 1
  20. let self.header_types[key] = self.max_level
  21. endif
  22. let self.levels[curline] = self.header_types[key]
  23. endfunction
  24. let save_cursor = getcurpos()
  25. let save_mark = getpos("'[")
  26. silent keeppatterns %s/\v^%(%(([=`:.'"~^_*+#-])\1+\n)?.{1,2}\n([=`:.'"~^_*+#-])\2+)|%(%(([=`:.''"~^_*+#-])\3{2,}\n)?.{3,}\n([=`:.''"~^_*+#-])\4{2,})$/\=closure.Process(submatch(0))/gn
  27. call setpos('.', save_cursor)
  28. call setpos("'[", save_mark)
  29. let b:RstFoldCache = closure.levels
  30. endfunction
  31. function RstFold#GetRstFold()
  32. if !g:rst_fold_enabled
  33. return
  34. endif
  35. if !has_key(b:, 'RstFoldCache')
  36. call s:CacheRstFold()
  37. endif
  38. if has_key(b:RstFoldCache, v:lnum)
  39. return '>' . b:RstFoldCache[v:lnum]
  40. else
  41. return '='
  42. endif
  43. endfunction
  44. function RstFold#GetRstFoldText()
  45. if !g:rst_fold_enabled
  46. return
  47. endif
  48. if !has_key(b:, 'RstFoldCache')
  49. call s:CacheRstFold()
  50. endif
  51. let indent = repeat(' ', b:RstFoldCache[v:foldstart] - 1)
  52. let thisline = getline(v:foldstart)
  53. " For over+under-lined headers, skip the overline.
  54. let text = thisline =~ '^\([=`:.''"~^_*+#-]\)\1\+$' ? getline(v:foldstart + 1) : thisline
  55. return indent . text
  56. endfunction