fold.vim 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. function! gitgutter#fold#enable()
  2. call s:save_fold_state()
  3. call s:set_fold_levels()
  4. setlocal foldexpr=gitgutter#fold#level(v:lnum)
  5. setlocal foldmethod=expr
  6. setlocal foldlevel=0
  7. setlocal foldenable
  8. call gitgutter#utility#setbufvar(bufnr(''), 'folded', 1)
  9. endfunction
  10. function! gitgutter#fold#disable()
  11. call s:restore_fold_state()
  12. call gitgutter#utility#setbufvar(bufnr(''), 'folded', 0)
  13. endfunction
  14. function! gitgutter#fold#toggle()
  15. if s:folded()
  16. call gitgutter#fold#disable()
  17. else
  18. call gitgutter#fold#enable()
  19. endif
  20. endfunction
  21. function! gitgutter#fold#level(lnum)
  22. return gitgutter#utility#getbufvar(bufnr(''), 'fold_levels')[a:lnum]
  23. endfunction
  24. function! gitgutter#fold#foldtext()
  25. if !gitgutter#fold#is_changed()
  26. return foldtext()
  27. endif
  28. return substitute(foldtext(), ':', ' (*):', '')
  29. endfunction
  30. " Returns 1 if any of the folded lines have been changed
  31. " (added, removed, or modified), 0 otherwise.
  32. function! gitgutter#fold#is_changed()
  33. for hunk in gitgutter#hunk#hunks(bufnr(''))
  34. let hunk_begin = hunk[2]
  35. let hunk_end = hunk[2] + (hunk[3] == 0 ? 1 : hunk[3])
  36. if hunk_end < v:foldstart
  37. continue
  38. endif
  39. if hunk_begin > v:foldend
  40. break
  41. endif
  42. return 1
  43. endfor
  44. return 0
  45. endfunction
  46. " A line in a hunk has a fold level of 0.
  47. " A line within 3 lines of a hunk has a fold level of 1.
  48. " All other lines have a fold level of 2.
  49. function! s:set_fold_levels()
  50. let fold_levels = ['']
  51. for lnum in range(1, line('$'))
  52. let in_hunk = gitgutter#hunk#in_hunk(lnum)
  53. call add(fold_levels, (in_hunk ? 0 : 2))
  54. endfor
  55. let lines_of_context = 3
  56. for lnum in range(1, line('$'))
  57. if fold_levels[lnum] == 2
  58. let pre = lnum >= 3 ? lnum - lines_of_context : 0
  59. let post = lnum + lines_of_context
  60. if index(fold_levels[pre:post], 0) != -1
  61. let fold_levels[lnum] = 1
  62. endif
  63. endif
  64. endfor
  65. call gitgutter#utility#setbufvar(bufnr(''), 'fold_levels', fold_levels)
  66. endfunction
  67. function! s:save_fold_state()
  68. let bufnr = bufnr('')
  69. call gitgutter#utility#setbufvar(bufnr, 'foldlevel', &foldlevel)
  70. call gitgutter#utility#setbufvar(bufnr, 'foldmethod', &foldmethod)
  71. if &foldmethod ==# 'manual'
  72. mkview
  73. endif
  74. endfunction
  75. function! s:restore_fold_state()
  76. let bufnr = bufnr('')
  77. let &foldlevel = gitgutter#utility#getbufvar(bufnr, 'foldlevel')
  78. let &foldmethod = gitgutter#utility#getbufvar(bufnr, 'foldmethod')
  79. if &foldmethod ==# 'manual'
  80. loadview
  81. else
  82. normal! zx
  83. endif
  84. endfunction
  85. function! s:folded()
  86. return gitgutter#utility#getbufvar(bufnr(''), 'folded')
  87. endfunction