aboutsummaryrefslogtreecommitdiff
path: root/plugin/insert.vim
blob: 3d27f782e23a6f07e3ffdd2ff34f629d8c226b37 (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
" Other operators for entering insert mode.

" Like 'I', but skip past the first v:count1 WORDs. Useful for when one wants
" the 'I' behavior to respect comments.
"
" If there are fewer than v:count1 WORDs in the line, then append to the end of
" the line.
"
" Have to cheese this a little bit to get the redo (.) operator to work with it.
" This is done by making a "sort-of" 0-width text object that exists where the
" change should happen.
"
" If the 'g' is present, that acts similar to gI -- it does not skip
" whitespace and starts insertion directly after the v:count1'th word.
noremap cI <cmd>call <sid>insert_comment_count(v:count1)<cr>1c<Plug><sid>(insert-comment-obj-nog)
noremap cgI <cmd>call <sid>insert_comment_count(v:count1)<cr>1c<Plug><sid>(insert-comment-obj-g)
onoremap <Plug><sid>(insert-comment-obj-nog) <cmd>call <sid>insert_comment_obj(0)<cr>
onoremap <Plug><sid>(insert-comment-obj-g) <cmd>call <sid>insert_comment_obj(1)<cr>

onoremap <plug>(insert-here-obj) <cmd>normal! "i <esc>v"

let s:motions = ['b', 'w', 'ib', 'ab']

for m in s:motions
  exec "onoremap <Plug>(mot-before-" . m . ") <cmd>call g:BeforeMot(\"" . m . "\")<cr>"
  exec "noremap dI" . m . " c<Plug>(mot-before-" . m . ")"
endfor
 
function! g:BeforeMot(mot) abort
  exec "normal! " . a:mot
  exec "normal! \<esc>i \<esc>v"
endfunction

function! s:insert_comment_count(count) abort
  let s:count = a:count
endfunction

function! s:insert_comment_obj(g, ...) abort
  if v:operator == 'c'
    let end = 0
    normal! 0
    let i = 0
    call search('^\s*\zs\S', '', line('.'))
    while i < s:count
      if col('.') == col('$') - 1
        let end = 1
        break
      endif

      if a:g
        let pattern = '\S*\zs\ze\s\+'
      else
        let pattern = '\S*\s\+\zs'
      endif

      if ! search(pattern, '', line('.'))
        let end = 1
        break
      endif

      let i += 1
    endwhile

    " Cheese because 0-width visual selections aren't a thing, I don't think, so
    " instead insert an ephemeral space and VIsual highlight that space, the c
    " command will then remove that ephemeral space, all with the user being
    " none-the-wiser.
    if end
      exec "normal! A \<esc>v"
    else
      exec "normal! i \<esc>v"
    endif
  else
  endif
endfunction