aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Rahm <rahm@google.com>2022-09-16 20:00:12 +0000
committerJosh Rahm <rahm@google.com>2022-09-16 20:00:12 +0000
commit8c82106848a9bd37d8be9e2c5cdb7c545c0af196 (patch)
tree77a0964015d8893a195558cc6daedf54e2ae9418
parentb7542bfb27673a2cd1c3c1836739f1b18f450b13 (diff)
downloadfieldmarshal.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.vim81
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