diff --git a/README.markdown b/README.markdown index b72d888..975c9d6 100644 --- a/README.markdown +++ b/README.markdown @@ -1,12 +1,13 @@ textobj-comment =============== -This Vim plugin provides text objects for comments. +This Vim plugin provides text objects for comments, available in Visual and +Operator-pending mode. -`ac` selects a comment including the comment delimiters and `ic` selects -just the comment content. (There's also a third text object, `aC`, which -selects a comment including trailing or leading whitespace.) These -mappings are available in Visual and Operator-pending mode. +* `ac` selects a comment including the comment delimiters +* `ic` selects just the comment content +* `iC` selects a comment including trailing or leading whitespace. +* `aC` selects a comment including adjacent ones only separated by an empty or whitespace-only line. This plugin uses the `'comments'` and `'commentstring'` settings to determine what a comment looks like for a given filetype. It works with diff --git a/autoload/textobj/comment.vim b/autoload/textobj/comment.vim index 4e45457..4758174 100644 --- a/autoload/textobj/comment.vim +++ b/autoload/textobj/comment.vim @@ -9,7 +9,7 @@ " First we look for a full-line comment with simple leader or with paired " leader under the cursor, then for inline and end-of-line comments at the " cursor position, and finally for the nearest full-line comment above. -function! s:Select(inside, whitespace) abort +function! s:Select(inside, whitespace, pass_empty_lines) abort let [simple_leaders, paired_leaders] = s:GetLeaders() if empty(simple_leaders + paired_leaders) return 0 @@ -19,7 +19,7 @@ function! s:Select(inside, whitespace) abort " Search for simple leader first to avoid being caught up in strange paired " leaders - let comment = s:FindSimpleLineComment(pos, simple_leaders, 0) + let comment = s:FindSimpleLineComment(pos, simple_leaders, 0, a:pass_empty_lines) if !empty(comment) return s:AdjustLineEnds(comment, a:whitespace, a:inside) endif @@ -33,7 +33,7 @@ function! s:Select(inside, whitespace) abort return s:AdjustInlineEnds(comment, a:whitespace, a:inside) endif - let scomment = s:FindSimpleLineComment(pos, simple_leaders, 1) + let scomment = s:FindSimpleLineComment(pos, simple_leaders, 1, a:pass_empty_lines) let pcomment = s:FindPairedLineComment(pos, paired_leaders, 1) if !empty(scomment) || !empty(pcomment) if empty(scomment) @@ -98,7 +98,7 @@ endfunction " the end is on the last byte position in the line). Empty when no match. " s:FindSimpleLineComment() {{{2 -function! s:FindSimpleLineComment(pos, simple_leaders, upwards) abort +function! s:FindSimpleLineComment(pos, simple_leaders, upwards, pass_empty_lines) abort let cursor_line = a:pos[0] if a:upwards && !empty(a:simple_leaders) @@ -113,6 +113,13 @@ function! s:FindSimpleLineComment(pos, simple_leaders, upwards) abort for simple in a:simple_leaders let simplere = '\V\^\s\*' . s:escape(simple) + + " if we allow to cross over empty (whitespace-only) lines, we append + " an 'or empty' to the regular expression + if a:pass_empty_lines + let simplere = simplere . '\|\^\s\*\$' + endif + if getline(cursor_line) =~# simplere let startline = cursor_line let ln = cursor_line - 1 @@ -531,13 +538,17 @@ endfunction " Public interface {{{1 function! textobj#comment#select_a() abort - return s:Select(0, 0) + return s:Select(0, 0, 0) endfunction function! textobj#comment#select_i() abort - return s:Select(1, 0) + return s:Select(1, 0, 0) +endfunction + +function! textobj#comment#select_big_i() abort + return s:Select(0, 1, 0) endfunction function! textobj#comment#select_big_a() abort - return s:Select(0, 1) + return s:Select(0, 0, 1) endfunction diff --git a/plugin/textobj/comment.vim b/plugin/textobj/comment.vim index 6e835b7..6c42ba0 100644 --- a/plugin/textobj/comment.vim +++ b/plugin/textobj/comment.vim @@ -21,6 +21,8 @@ call textobj#user#plugin('comment', { \ 'select-i': 'ic', \ }, \ 'big': { + \ 'select-i-function': 'textobj#comment#select_big_i', + \ 'select-i': 'iC', \ 'select-a-function': 'textobj#comment#select_big_a', \ 'select-a': 'aC', \ } diff --git a/t/inline.vim b/t/inline.vim index 5d13a74..5a3e00b 100644 --- a/t/inline.vim +++ b/t/inline.vim @@ -78,7 +78,7 @@ describe '(textobj-comment-i)' end -describe '(textobj-comment-big-a)' +describe '(textobj-comment-big-i)' before silent tabedit t/fixtures/Inline.java @@ -88,40 +88,40 @@ describe '(textobj-comment-big-a)' bwipeout! end - it 'selects a big comment with trailing whitespace' + it 'selects inner big comment with trailing whitespace' 3 normal! ww - Expect SelectABigComment() to_have_cols 8, 28 + Expect SelectIBigComment() to_have_cols 8, 28 7 exe "normal! A \ \b" - Expect SelectABigComment() to_have_cols 23, 58 + Expect SelectIBigComment() to_have_cols 23, 58 24 normal! ww - Expect SelectABigComment() to_have_cols 7, 39 + Expect SelectIBigComment() to_have_cols 7, 39 end it 'selects a big comment with leading whitespace' 5 normal! WWhr_h - Expect SelectABigComment() to_have_cols 7, 17 + Expect SelectIBigComment() to_have_cols 7, 17 5 normal! $ - Expect SelectABigComment() to_have_cols 46, 68 + Expect SelectIBigComment() to_have_cols 46, 68 7 - Expect SelectABigComment() to_have_cols 22, 54 + Expect SelectIBigComment() to_have_cols 22, 54 end it 'selects a big comment without whitespace' 15 normal! ww - Expect SelectABigComment() to_have_cols 20, 47 + Expect SelectIBigComment() to_have_cols 20, 47 18 - Expect SelectABigComment() to_have_cols 17, 45 + Expect SelectIBigComment() to_have_cols 17, 45 end it 'selects characterwise' 18 - call SelectABigComment() + call SelectIBigComment() Expect visualmode() ==# 'v' end @@ -139,8 +139,8 @@ describe 'inline leader search' it 'proceeds towards the right' 20 - Expect SelectABigComment() to_have_cols 14, 27 - Expect SelectABigComment() to_have_cols 27, 33 + Expect SelectIBigComment() to_have_cols 14, 27 + Expect SelectIBigComment() to_have_cols 27, 33 normal! w Expect SelectInnerComment() to_have_cols 42, 50 Expect SelectInnerComment() to_have_cols 47, 73 diff --git a/t/paired.vim b/t/paired.vim index 0c0e9b0..0d39230 100644 --- a/t/paired.vim +++ b/t/paired.vim @@ -88,7 +88,7 @@ describe '(textobj-comment-i)' end -describe '(textobj-comment-big-a)' +describe '(textobj-comment-big-i)' before silent tabedit t/fixtures/paired.c @@ -98,41 +98,41 @@ describe '(textobj-comment-big-a)' bwipeout! end - it 'selects a big comment with trailing whitespace' + it 'selects inner big comment with trailing whitespace' 26 - Expect SelectABigComment() to_have_lnums 26, 27 + Expect SelectIBigComment() to_have_lnums 26, 27 call append(5, ["", "\t", ""]) 5 - Expect SelectABigComment() to_have_lnums 3, 8 + Expect SelectIBigComment() to_have_lnums 3, 8 end it 'selects a big comment with leading whitespace' 4 - Expect SelectABigComment() to_have_lnums 2, 5 + Expect SelectIBigComment() to_have_lnums 2, 5 call append(7, "\t\t") 9 - Expect SelectABigComment() to_have_lnums 8, 9 + Expect SelectIBigComment() to_have_lnums 8, 9 end it 'selects a big comment without whitespace' 19 - Expect SelectABigComment() to_have_lnums 19, 19 + Expect SelectIBigComment() to_have_lnums 19, 19 2delete - Expect SelectABigComment() to_have_lnums 2, 4 + Expect SelectIBigComment() to_have_lnums 2, 4 end it 'selects linewise' 4 - call SelectABigComment() + call SelectIBigComment() Expect visualmode() ==# 'V' end it 'sets proper start and end column' - let command = "v\(textobj-comment-big-a)v\" + let command = "v\(textobj-comment-big-i)v\" 3 - Expect SelectABigComment(command) to_have_pos [2, 1], [5, 21] + Expect SelectIBigComment(command) to_have_pos [2, 1], [5, 21] 8 - Expect SelectABigComment(command) to_have_cols 5, 23 + Expect SelectIBigComment(command) to_have_cols 5, 23 end end @@ -149,9 +149,9 @@ describe 'paired leader search' it 'proceeds upwards' 9 - Expect SelectABigComment() to_have_lnums 8, 8 + Expect SelectIBigComment() to_have_lnums 8, 8 10 - Expect SelectABigComment() not to_have_lnums 8, 8 + Expect SelectIBigComment() not to_have_lnums 8, 8 end end diff --git a/t/plugin.vim b/t/plugin.vim index 498ffd9..77146b8 100644 --- a/t/plugin.vim +++ b/t/plugin.vim @@ -2,7 +2,7 @@ runtime! plugin/textobj/comment.vim let g:maps = { 'ac': '(textobj-comment-a)', \ 'ic': '(textobj-comment-i)', - \ 'aC': '(textobj-comment-big-a)' } + \ 'iC': '(textobj-comment-big-i)' } describe 'plugin' diff --git a/t/simple.vim b/t/simple.vim index ffbea7d..03c9594 100644 --- a/t/simple.vim +++ b/t/simple.vim @@ -84,7 +84,7 @@ describe '(textobj-comment-i)' end -describe '(textobj-comment-big-a)' +describe '(textobj-comment-big-i)' before silent tabedit t/fixtures/simple.py @@ -96,31 +96,31 @@ describe '(textobj-comment-big-a)' it 'selects a big comment with trailing whitespace' 5 - Expect SelectABigComment() to_have_lnums 5, 6 + Expect SelectIBigComment() to_have_lnums 5, 6 11 - Expect SelectABigComment() to_have_lnums 11, 12 + Expect SelectIBigComment() to_have_lnums 11, 12 end it 'selects a big comment with leading whitespace' 26d normal! k - Expect SelectABigComment() to_have_lnums 24, 25 + Expect SelectIBigComment() to_have_lnums 24, 25 16 - Expect SelectABigComment() to_have_lnums 14, 17 + Expect SelectIBigComment() to_have_lnums 14, 17 end it 'selects linewise' 5 - call SelectABigComment() + call SelectIBigComment() Expect visualmode() ==# 'V' end it 'sets proper start and end column' - let command = "v\(textobj-comment-big-a)v\" + let command = "v\(textobj-comment-big-i)v\" 11 - Expect SelectABigComment(command) to_have_cols 5, 1 + Expect SelectIBigComment(command) to_have_cols 5, 1 17 - Expect SelectABigComment(command) to_have_cols 1, 25 + Expect SelectIBigComment(command) to_have_cols 1, 25 end end diff --git a/t/util/helpers.vim b/t/util/helpers.vim index 5623417..efa78e0 100644 --- a/t/util/helpers.vim +++ b/t/util/helpers.vim @@ -15,8 +15,8 @@ function! SelectInnerComment(...) return DoSelect(a:0 ? a:1 : "v\(textobj-comment-i)\") endfunction -function! SelectABigComment(...) - return DoSelect(a:0 ? a:1 : "v\(textobj-comment-big-a)\") +function! SelectIBigComment(...) + return DoSelect(a:0 ? a:1 : "v\(textobj-comment-big-i)\") endfunction " Custom matchers