diff options
author | Josh Rahm <rahm@google.com> | 2022-09-13 14:08:31 -0600 |
---|---|---|
committer | Josh Rahm <rahm@google.com> | 2022-09-13 14:08:31 -0600 |
commit | 79b37fdd282f616714876b97e484d8dcc8a488ab (patch) | |
tree | 27805240cf5f7d97f7e6e682d4dfd69364b36e03 | |
parent | a3caef03c883cd9711ac60996227e13e1199e4db (diff) | |
download | fieldmarshal.vim-79b37fdd282f616714876b97e484d8dcc8a488ab.tar.gz fieldmarshal.vim-79b37fdd282f616714876b97e484d8dcc8a488ab.tar.bz2 fieldmarshal.vim-79b37fdd282f616714876b97e484d8dcc8a488ab.zip |
commenter.vim: much better comment handling with fancier regexes.
-rw-r--r-- | plugin/commenter.vim | 162 | ||||
-rw-r--r-- | plugin/move.vim | 2 |
2 files changed, 102 insertions, 62 deletions
diff --git a/plugin/commenter.vim b/plugin/commenter.vim index 982f7c2..c7f30b7 100644 --- a/plugin/commenter.vim +++ b/plugin/commenter.vim @@ -5,57 +5,86 @@ nnoremap cdd <cmd>set operatorfunc=<sid>comment<cr>g@_ nnoremap cD <cmd>set operatorfunc=<sid>comment<cr>g@$ " Comment out the rest of the line and put the cursor into insert mode -noremap cdC c<Plug><SID>(comment-change-object-i) +nnoremap cdC c<Plug><SID>(comment-change-object-i) " Comment out the line and go into insert mode before the first non-blank " character. -noremap cdcc c<Plug><SID>(comment-change-object-I) +nnoremap cdcc c<Plug><SID>(comment-change-object-I) onoremap <Plug><SID>(comment-change-object-i) <cmd>call <sid>change_comment_obj('i')<cr> onoremap <Plug><SID>(comment-change-object-I) <cmd>call <sid>change_comment_obj('I')<cr> -onoremap i/ <cmd>call <sid>inner_comment(v:operator)<cr> -vnoremap i/ <cmd>call <sid>inner_comment('')<cr> +onoremap i/ <cmd>call <sid>comment_obj(v:operator, 'i')<cr> +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> noremap czd <cmd>set operatorfunc=<sid>uncomment<cr>g@ nnoremap czdd <cmd>set operatorfunc=<sid>uncomment<cr>g@_ -function! s:inner_comment(op) - let [line_com, bstart, bcont, bend, bpad, inl] = - \ get(s:comment_style, &ft, ['#', '#', '#', '#', 0, 0]) - let lc = escape(line_com, '/') - - if getline('.') =~ printf('\V\^\s\*%s', lc) - call search(printf('\V\^\s\*\S\(%s\)\@<!', lc), 'W') - exec "normal! k$m>" - let l = search(printf('\V\^\s\*\S\(%s\)\@<!', lc), 'bW') - if l == 0 - normal! 0m< - else - exec "normal! j0m<" - endif +let s:default_style = { + \ 'block_start_regex': '\(^\s*\(\(\S\)\(#\)\@<!.*\|\S\n\)\_s\+\|\%^\)#\+\s*\zs\S\ze', + \ 'block_end_regex': '#.*\zs.\ze\n\_s*\S#\@<!', + \ 'line': '#' + \ } - normal! gvoh - if a:op == 'c' - exec printf("normal! \<esc>i%s gv%dll", line_com, len(line_com)) - endif +function! s:regex_combine(s1, s2) abort + if a:s1 == "" + return a:s2 + endif + + if a:s2 == "" + return a:s1 + endif + + return printf('\(%s\)\|\(%s\)', a:s1, a:s2) +endfunction + +function! s:comment_obj(op, iOrA) + let style = get(s:comment_style, &ft, s:default_style) + + let start_regex = s:regex_combine( + \ get(style, 'multi_start_regex', ''), + \ get(style, 'block_start_regex', '')) + let end_regex = s:regex_combine( + \ get(style, 'multi_end_regex', ''), + \ get(style, 'block_end_regex', '')) + \ + if a:iOrA == 'i' + let start_regex = + \ substitute( + \ substitute(start_regex, '\V${i\(\[se]\)}', '\\z\1', 'g'), + \ '\V${a\(\[se]\)}', '', 'g') + let end_regex = + \ substitute( + \ substitute(end_regex, '\V${i\(\[se]\)}', '\\z\1', 'g'), + \ '\V${a\(\[se]\)}', '', 'g') else - let cs = escape(bstart, '/') - let ce = escape(bend, '/') + let start_regex = + \ substitute( + \ substitute(start_regex, '\V${a\(\[se]\)}', '\\z\1', 'g'), + \ '\V${i\(\[se]\)}', '', 'g') + let end_regex = + \ substitute( + \ substitute(end_regex, '\V${a\(\[se]\)}', '\\z\1', 'g'), + \ '\V${i\(\[se]\)}', '', 'g') + endif - normal! k - let l2 = search('\V\zs\S\_s\*' . ce, 'Wc') - exec "normal! m>" - let l1 = search('\V' . cs . '\S\*\_s\?\zs', 'bW') - exec "normal! m<gvo" + call search(end_regex, 'c') + exec "normal! v\<esc>m>" + call search(start_regex, 'bW') + exec "normal! m<gv" - if l1 != l2 && len(v:operator) > 0 - exec printf("normal! \<esc>i%s gv%dll", bcont, len(bcont)) - else - " exec printf("normal! \<esc>i%s gv%dllo%dll", bcont, len(bcont), len(bcont)) - endif + let [_, sl, sc, _] = getpos("'<") + let [_, el, ec, _] = getpos("'>") + + if getline(sl)[:sc - 2] =~ '^\s*$' && a:iOrA == 'a' && ec >= len(getline(el)) + " Select line-wise if the comments on on lines. + exec "normal V" endif + + endfunction function! s:change_comment_obj(mv) abort @@ -63,39 +92,52 @@ function! s:change_comment_obj(mv) abort " This is a cheese to allow the cdcc and cdC commands to be repeated with " the dot operator. When in insert mode <left><right><up><down> stop " recording into the redobuff. This is a way to get around that. - " - " exec "normal! i \<esc>v" - let [line_com, bstart, bcont, bend, bpad, inl] = - \ get(s:comment_style, &ft, ['#', '#', '#', '#', 0, 0]) - exec printf("normal! %s %s \<esc>%dhvl", a:mv, line_com, len(line_com) + 3) + let s = get(s:comment_style, &ft, s:default_style) + exec printf("normal! %s %s \<esc>%dhvl", a:mv, s.line, len(s.line) + 3) else endif endfunction - " 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] + \ 'java,c,cpp,rust,go': { + \ 'multi_start_regex': '${as}\/\*\([*]\|\_s\)*${is}\S', + \ 'multi_end_regex': '${is}\S\_s*\*\/${as}', + \ 'block_start_regex': '\(^\s*\(\(\S\S\)\(\/\/\)\@<!.*\|\S\n\)\n*${as}\_s\+\|\%^${as}\)\/\/\+\s*${is}\S${ie}', + \ 'block_end_regex': '\/\/.*${is}.${ie}${as}\n\_s*\S\/\@<!', + \ 'line': '//', + \ 'multi_start': '/*', + \ 'multi_cont': ' *', + \ 'multi_end': ' */' + \ }, + \ 'vim': { + \ 'block_start_regex': '\(^\s*\(\(\S\)\("\)\@<!.*\|\S\n\)\_s\+\|\%^\)"\s*${is}\S${ie}', + \ 'block_end_regex': '".*${is}.${ie}\n${as}\_s*\S"\@<!', + \ 'line': '"' + \ } \ } +let s:comment_style_new = {} +for [langs, i] in items(s:comment_style) + for l in split(langs, ',') + let s:comment_style_new[l] = i + endfor +endfor +let s:comment_style = s:comment_style_new + function! s:uncomment(arg, ...) abort - let [line_com, bstart, bcont, bend, bpad, inl] = - \ get(s:comment_style, &ft, ['#', '#', '#', '#', 0, 0]) + let s = get(s:comment_style, &ft, s:default_style) let l1 = line("'[") let l2 = line("']") - if inl + if has_key(s, 'multi_start') 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, '/')) + \ 'silent! %s,%s s/\V\zs%s\s\?\ze//', l1, l2, escape(s.multi_start, '/')) + silent exec printf('silent! %s,%s s/\V\zs\s\?%s\ze//', l1, l2, escape(s.multi_end, '/')) + silent exec printf('silent! %s,%s s/\V\^\s\*\zs%s\s\?\ze//', l1, l2, escape(s.multi_cont, '/')) 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, '/')) + silent exec printf('silent! %s,%s s/\V\^\s\*\zs%s\s\?\ze//', l1, l2, escape(s.line, '/')) endfunction function! s:comment(arg, ...) abort @@ -103,7 +145,7 @@ function! s:comment(arg, ...) abort normal! m` function! cb.operate(ls, t) dict abort - let [line_com, bstart, bcont, bend, bpad, inl] = get(s:comment_style, &ft, ['#', '#', '#', '#', 0, 0]) + let s = get(s:comment_style, &ft, s:default_style) let smallest = 100 let ls = a:ls @@ -124,26 +166,26 @@ function! s:comment(arg, ...) abort if self.arg == 'line' let i = 0 while i < len(ls) - let ls[i] = substitute(ls[i], printf('\%%%dc', smallest), line_com . ' ', '') + let ls[i] = substitute(ls[i], printf('\%%%dc', smallest), s.line . ' ', '') let i += 1 endwhile else - if self.arg != 'line' && !inl + if self.arg != 'line' && !has_key(s, 'multi_start') throw "Inline comments not allowed" endif - let ls[0] = substitute(ls[0], '^', bstart . ' ', '') - let ls[-1] = substitute(ls[-1], '$', ' ' . bend, '') + let ls[0] = substitute(ls[0], '^', s.multi_start . ' ', '') + let ls[-1] = substitute(ls[-1], '$', ' ' . s.multi_end, '') endif else let l = getline('.') if l[len(l) - len(ls[0]):] ==# ls[0] - let ls[0] = printf("%s %s", line_com, ls[0]) + let ls[0] = printf("%s %s", s.line, ls[0]) else - if !inl + if !has_key(s, 'multi_start') throw "Inline comments not allowed" endif - let ls[0] = printf("%s %s %s", bstart, ls[0], bend) + let ls[0] = printf("%s %s %s", s.multi_start, ls[0], s.multi_end) endif endif diff --git a/plugin/move.vim b/plugin/move.vim index 8d11d22..0ed2e7f 100644 --- a/plugin/move.vim +++ b/plugin/move.vim @@ -3,5 +3,3 @@ onoremap <silent> i% <cmd>call search('{') <bar> normal! v%<bs>o<space><cr> vnoremap <silent> a% <esc>V/{<cr>% vnoremap <silent> i% <esc>/{<cr>v%<bs>o<space>o - -onoremap <silent> gv gv |