diff options
author | Josh Rahm <rahm@google.com> | 2022-09-16 20:00:12 +0000 |
---|---|---|
committer | Josh Rahm <rahm@google.com> | 2022-09-16 20:00:12 +0000 |
commit | 8c82106848a9bd37d8be9e2c5cdb7c545c0af196 (patch) | |
tree | 77a0964015d8893a195558cc6daedf54e2ae9418 | |
parent | b7542bfb27673a2cd1c3c1836739f1b18f450b13 (diff) | |
download | fieldmarshal.vim-8c82106848a9bd37d8be9e2c5cdb7c545c0af196.tar.gz fieldmarshal.vim-8c82106848a9bd37d8be9e2c5cdb7c545c0af196.tar.bz2 fieldmarshal.vim-8c82106848a9bd37d8be9e2c5cdb7c545c0af196.zip |
commenter.vim: add acp and icp text objects.
Just like ip and ap, except it excludes commment blocks.
-rw-r--r-- | plugin/commenter.vim | 81 |
1 files changed, 76 insertions, 5 deletions
diff --git a/plugin/commenter.vim b/plugin/commenter.vim index 1855828..f903fce 100644 --- a/plugin/commenter.vim +++ b/plugin/commenter.vim @@ -13,18 +13,84 @@ vnoremap i/ <cmd>call <sid>comment_obj('', 'i')<cr> onoremap a/ <cmd>call <sid>comment_obj(v:operator, 'a')<cr> vnoremap a/ <cmd>call <sid>comment_obj('', 'a')<cr> +" Objects for paragraphs excluding any comment blocks immediately preceeding or +" Succeeding +onoremap acp <cmd>call <sid>uncommented_paragraph('a')<cr> +onoremap icp <cmd>call <sid>uncommented_paragraph('i')<cr> + noremap czd <cmd>set operatorfunc=<sid>uncomment<cr>g@ nnoremap czdd <cmd>set operatorfunc=<sid>uncomment<cr>g@_ function! s:single_character_style(c) return { - \ 'block_start_regex': '\(^\s*\(\(\S\)\(' . a:c . '\)\@<!.*\|\S\n\)\_s\+\|\%^\)${as}' . a:c . '\s*${is}\S${ie}', - \ 'block_end_regex': a:c . '.*${is}.${ie}\(\n\s*\)*${as}\n\_s*\S' . a:c . '\@<!', + \ 'block_start_regex': '\(^\s*\(\(\S\)\(' . a:c . '\)\@<!.*\|\n\)\_s\+\|\%^\)${as}' . a:c . '\s*${is}\S${ie}', + \ 'block_end_regex': a:c . '.*${is}\(\n\s*\)*${as}\n\_s*\S' . a:c . '\@<!', \ 'line': a:c \ } endfunction let s:default_style = s:single_character_style('#') +" Save the motion postions, for use with g@. +function s:save_object(t) abort + let s:object = { + \ "type": a:t, + \ "start": getpos("'["), + \ "end": getpos("']") + \ } +endfunction + +function! s:maxpos(cur, oth) + let [a, l1, c1, b] = a:cur + let [_, l2, c2, _] = a:oth + + if l1 > l2 + return a:cur + elseif l2 > l1 + return a:oth + elseif c2 > c1 + return a:oth + else + return a:cur + endif + +endfunction + +function! s:minpos(cur, oth) + let [a, l1, c1, b] = a:cur + let [_, l2, c2, _] = a:oth + + if l1 < l2 + return a:cur + elseif l2 < l1 + return a:oth + elseif c2 < c1 + return a:oth + else + return a:cur + endif + +endfunction + +function! s:uncommented_paragraph(t) abort + let savepos = getpos('.') + set operatorfunc=s:save_object + exec "normal! g@". a:t . "pv\<esc>" + call setpos('.', savepos) + + let [start_regex, end_regex] = g:GetCommentRegex('a') + + call search(end_regex . '\|\%^', 'cb') + exec "normal! j" + call setpos('.', s:maxpos(getpos('.'), s:object.start)) + normal! m< + call setpos('.', savepos) + + call search(start_regex . '\|\%$', 'c') + call setpos('.', s:minpos(getpos('.'), s:object.end)) + exec "normal! k" + + normal! m>gvV +endfunction function! s:regex_combine(s1, s2) abort if a:s1 == "" @@ -38,7 +104,7 @@ function! s:regex_combine(s1, s2) abort return printf('\(%s\)\|\(%s\)', a:s1, a:s2) endfunction -function! s:comment_obj(op, iOrA) +function! g:GetCommentRegex(ia) abort let style = get(s:comment_style, &ft, s:default_style) let start_regex = s:regex_combine( @@ -48,7 +114,7 @@ function! s:comment_obj(op, iOrA) \ get(style, 'multi_end_regex', ''), \ get(style, 'block_end_regex', '')) \ - if a:iOrA == 'i' + if a:ia == 'i' let start_regex = \ substitute( \ substitute(start_regex, '\V${i\(\[se]\)}', '\\z\1', 'g'), @@ -67,6 +133,11 @@ function! s:comment_obj(op, iOrA) \ substitute(end_regex, '\V${a\(\[se]\)}', '\\z\1', 'g'), \ '\V${i\(\[se]\)}', '', 'g') endif + return [start_regex, end_regex] +endfunction + +function! s:comment_obj(op, ia) + let [start_regex, end_regex] = g:GetCommentRegex(a:ia) call search(end_regex, 'c') exec "normal! v\<esc>m>" @@ -76,7 +147,7 @@ function! s:comment_obj(op, iOrA) let [_, sl, sc, _] = getpos("'<") let [_, el, ec, _] = getpos("'>") - if getline(sl)[:sc - 2] =~ '^\s*$' && a:iOrA == 'a' && ec >= len(getline(el)) + if getline(sl)[:sc - 2] =~ '^\s*$' && a:ia == 'a' && ec >= len(getline(el)) exec "normal V" endif endfunction |