summaryrefslogtreecommitdiff
path: root/start/signify/autoload/sy/fold.vim
blob: e3afb970f56841feb8590509abf5667082fe9121 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
" vim: et sw=2 sts=2

" Function: SignifyFoldExpr {{{1
function! SignifyFoldExpr(lnum)
  return s:levels[a:lnum]
endfunction

" Function: SignifyFoldText {{{1
function! SignifyFoldText()
  let linelen = &textwidth ? &textwidth : 80
  let marker  = &foldmarker[:stridx(&foldmarker, ',')-1]
  let range   = foldclosedend(v:foldstart) - foldclosed(v:foldstart) + 1

  let left    = substitute(getline(v:foldstart), marker, '', '')
  let leftlen = len(left)

  let right    = printf('%d [%d]', range, v:foldlevel)
  let rightlen = len(right)

  let tmp    = strpart(left, 0, linelen - rightlen)
  let tmplen = len(tmp)

  if leftlen > tmplen
    let left    = strpart(tmp, 0, tmplen - 4) . '... '
    let leftlen = tmplen
  endif

  let fill = repeat(' ', linelen - (leftlen + rightlen))

  " return left . fill . right . repeat(' ', 100)
  return left . fill . right
endfunction

" Function: #dispatch {{{1
function! sy#fold#dispatch(do_tab) abort
  if a:do_tab
    call sy#fold#enable(1)
  else
    call sy#fold#toggle()
  endif
endfunction

" Function: #enable {{{1
function! sy#fold#enable(do_tab) abort
  execute sy#util#return_if_no_changes()

  if a:do_tab
    tabedit %
  endif

  let [s:context0, s:context1] = get(g:, 'signify_fold_context', [3, 8])
  let s:levels = s:get_levels(s:get_lines())

  setlocal foldexpr=SignifyFoldExpr(v:lnum)
  setlocal foldtext=SignifyFoldText()
  setlocal foldmethod=expr
  setlocal foldlevel=0
endfunction

" Function: #disable {{{1
function! sy#fold#disable() abort
  let &l:foldmethod = b:sy_folded.method
  let &l:foldtext = b:sy_folded.text
  normal! zv
endfunction

" Function: #toggle {{{1
function! sy#fold#toggle() abort
  if exists('b:sy_folded')
    call sy#fold#disable()
    if b:sy_folded.method == 'manual'
      loadview
    endif
    unlet b:sy_folded
  else
    let b:sy_folded = { 'method': &foldmethod, 'text': &foldtext }
    if &foldmethod == 'manual'
      let old_vop = &viewoptions
      mkview
      let &viewoptions = old_vop
    endif
    call sy#fold#enable(0)
  endif

  redraw!
  call sy#start()
endfunction

" Function: s:get_lines {{{1
function! s:get_lines() abort
  let signlist = sy#util#execute('sign place buffer='. b:sy.buffer)

  let lines = []
  for line in split(signlist, '\n')[2:]
    call insert(lines, matchlist(line, '\v^\s+line\=(\d+)')[1], 0)
  endfor

  return reverse(lines)
endfunction
" }}}

" Function: s:get_levels {{{1
function! s:get_levels(lines) abort
  let levels = {}

  for line in range(1, line('$'))
    let levels[line] = 2
  endfor

  for line in a:lines
    for l in range(line - s:context1, line + s:context1)
      if (l < 1) || (l > line('$'))
        continue
      endif
      if levels[l] == 2
        let levels[l] = 1
      endif
      for ll in range(line - s:context0, line + s:context0)
        let levels[ll] = 0
      endfor
    endfor
  endfor

  return levels
endfunction