aboutsummaryrefslogtreecommitdiff
path: root/plugin/commenter.vim
blob: 351e2dcbb2e14ea3ca87f6ff613d13c03ac2c284 (plain) (blame)
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
" Function for commenting out blocks of text.

noremap cd <cmd>set operatorfunc=<sid>comment<cr>g@
noremap cdd <cmd>set operatorfunc=<sid>comment<cr>g@_

noremap cD <cmd>set operatorfunc=<sid>uncomment<cr>g@
noremap cDD <cmd>set operatorfunc=<sid>uncomment<cr>g@_

      "  filetype, linecomment, block start, block continue, blockend, blockpad,
      "  inline_support
let s:comment_style = {
      \ 'java': ['//', '/*', ' *', '*/', 1, 1],
      \ 'c':    ['//', '/*', ' *', '*/', 1, 1],
      \ 'cpp':  ['//', '/*', ' *', '*/', 1, 1],
      \ 'vim':  ['"',  '"',  '"',  '"',  0, 0]
      \ }

function! s:modifyreg(arg, cb) abort
  let save_a = getreg('a')
  let save_a_type = getregtype('a')

  if a:arg == 'line'
    let vis = "'[V']"
  elseif a:arg == 'block'
    let vis = "`[\<C-v>`]"
  else
    let vis = "`[v`]"
  endif
  silent! exec printf("norm! %s\"ay", vis)

  let ls = getreg('a', 1, 1)
  let regtype = getregtype('a')

  let ls = a:cb.operate(ls)

  call setreg('a', ls, regtype)
  silent! exec "norm! gv\"ap"
  call setreg('a', save_a, save_a_type)
endfunction

function! s:uncomment(arg, ...) abort

  let [line_com, bstart, bcont, bend, bpad, inl] = get(s:comment_style, &ft, ['#', '#', '#', '#', 0, 0])
  let l1 = line("'[")
  let l2 = line("']")

  if inl
    silent exec printf('silent! %s,%s s/\V\zs%s\s\?\ze//', l1, l2, escape(bstart, '/'))
    silent exec printf('silent! %s,%s s/\V\zs\s\?%s\ze//', l1, l2, escape(bend, '/'))
  endif

  silent exec printf('silent! %s,%s s/\V\^\s\*\zs%s\s\?\ze//', l1, l2, escape(line_com, '/'))
  silent exec printf('silent! %s,%s s/\V\^\s\*\zs%s\s\?\ze//', l1, l2, escape(bcont, '/'))
endfunction

function! s:comment(arg, ...) abort
  let cb = { 'arg': a:arg }

  function! cb.operate(ls) dict abort
    let [line_com, bstart, bcont, bend, bpad, inl] = get(s:comment_style, &ft, ['#', '#', '#', '#', 0, 0])
    let smallest = 100
    let ls = a:ls

    if self.arg != 'line' && !inl
      throw "Inline comments not allowed"
    endif

    if self.arg == 'line' || len(ls) > 1
      for l in ls
        if ! (l =~ '^\s*$')
          let sz = match(l, '^\(\s\+\)\zs\S\ze') + 1
          if sz <= 0
            let sz = 1
          endif

          if sz < smallest && sz > 0
            let smallest = sz
          endif
        endif
      endfor

      if self.arg == 'line'
        let i = 0
        while i < len(ls)
          let ls[i] = substitute(ls[i], printf('\%%%dc', smallest), line_com . ' ', '')
          let i += 1
        endwhile
      else
        let ls[0] = substitute(ls[0], '^', bstart . ' ', '')
        let ls[-1] = substitute(ls[-1], '$', ' ' . bend, '')
      endif

    else
      let i = 0
      while i < len(ls)
        let ls[i] = printf("%s %s %s", bstart, ls[i], bend)
        let i += 1
      endwhile
    endif

    return ls
  endfunction

  call s:modifyreg(a:arg, cb)
endfunction