" 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 call insert_comment_count(v:count1)1c(insert-comment-obj-nog) noremap cgI call insert_comment_count(v:count1)1c(insert-comment-obj-g) onoremap (insert-comment-obj-nog) call insert_comment_obj(0) onoremap (insert-comment-obj-g) call insert_comment_obj(1) onoremap (insert-here-obj) normal! "i v" let s:motions = ['b', 'w', 'ib', 'ab'] for m in s:motions exec "onoremap (mot-before-" . m . ") call g:BeforeMot(\"" . m . "\")" exec "noremap dI" . m . " c(mot-before-" . m . ")" endfor function! g:BeforeMot(mot) abort exec "normal! " . a:mot exec "normal! \i \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 \v" else exec "normal! i \v" endif else endif endfunction