patch 9.1.1229: the comment plugin can be improved Commit: https://github.com/vim/vim/commit/9712a2534f3fabead9fa1c88a11179ded96b43ee Author: Maxim Kim <haba...@gmail.com> Date: Fri Mar 21 18:02:56 2025 +0100
patch 9.1.1229: the comment plugin can be improved Problem: the comment plugin can be improved Solution: add comment text objects "ic" and "ac" (Maxim Kim) closes: #16938 Signed-off-by: Maxim Kim <haba...@gmail.com> Signed-off-by: Christian Brabandt <c...@256bit.org> diff --git a/runtime/pack/dist/opt/comment/autoload/comment.vim b/runtime/pack/dist/opt/comment/autoload/comment.vim index 086d5bff0..34f0d680a 100644 --- a/runtime/pack/dist/opt/comment/autoload/comment.vim +++ b/runtime/pack/dist/opt/comment/autoload/comment.vim @@ -1,7 +1,7 @@ vim9script # Maintainer: Maxim Kim <haba...@gmail.com> -# Last Update: 2024 Oct 05 +# Last Update: 2025 Mar 21 # # Toggle comments # Usage: @@ -76,3 +76,88 @@ export def Toggle(...args: list<string>): string noautocmd keepjumps setline(lnum1, lines) return '' enddef + + +# Comment text object +# Usage: +# import autoload 'dist/comment.vim' +# onoremap <silent>ic <scriptcmd>comment.ObjComment(v:true)<CR> +# onoremap <silent>ac <scriptcmd>comment.ObjComment(v:false)<CR> +# xnoremap <silent>ic <esc><scriptcmd>comment.ObjComment(v:true)<CR> +# xnoremap <silent>ac <esc><scriptcmd>comment.ObjComment(v:false)<CR> +export def ObjComment(inner: bool) + def IsComment(): bool + var stx = map(synstack(line('.'), col('.')), 'synIDattr(v:val, "name")')->join() + return stx =~? 'Comment' + enddef + + # requires syntax support + if !exists("g:syntax_on") + return + endif + + var pos_init = getcurpos() + + # If not in comment, search next one, + if !IsComment() + if search(' \k+', 'W', line(".") + 100, 100, () => !IsComment()) <= 0 + return + endif + endif + + # Search for the beginning of the comment block + if IsComment() + if search(' %(\S+)|$', 'bW', 0, 200, IsComment) > 0 + search(' %(\S)|$', 'W', 0, 200, () => !IsComment()) + else + cursor(1, 1) + search(' \S+', 'cW', 0, 200) + endif + endif + + var pos_start = getcurpos() + + if !inner + var col = pos_start[2] + var prefix = getline(pos_start[1])[ : col - 2] + while col > 0 && prefix[col - 2] =~ '\s' + col -= 1 + endwhile + pos_start[2] = col + endif + + # Search for the comment end. + if pos_init[1] > pos_start[1] + cursor(pos_init[1], pos_init[2]) + endif + if search(' %(\S+)|$', 'W', 0, 200, IsComment) > 0 + search('\S', 'beW', 0, 200, () => !IsComment()) + else + if search('\%$', 'W', 0, 200) > 0 + search('\ze\S', 'beW', 0, 200, () => !IsComment()) + endif + endif + + var pos_end = getcurpos() + + if !inner + var spaces = matchstr(getline(pos_end[1]), '\%>.c\s*') + pos_end[2] += spaces->len() + if getline(pos_end[1])[pos_end[2] : ] =~ '^\s*$' + && (pos_start[2] == 1 || getline(pos_start[1])[ : pos_start[2]] =~ '^\s*$') + if search(' \s*\_$(\s* )+', 'eW', 0, 200) > 0 + pos_end = getcurpos() + endif + endif + endif + + if (pos_end[2] == (getline(pos_end[1])->len() ?? 1)) && pos_start[2] == 1 + cursor(pos_end[1], 1) + normal! V + cursor(pos_start[1], 1) + else + cursor(pos_end[1], pos_end[2]) + normal! v + cursor(pos_start[1], pos_start[2]) + endif +enddef diff --git a/runtime/pack/dist/opt/comment/doc/comment.txt b/runtime/pack/dist/opt/comment/doc/comment.txt index 7aa66fbd6..be8cb84e6 100644 --- a/runtime/pack/dist/opt/comment/doc/comment.txt +++ b/runtime/pack/dist/opt/comment/doc/comment.txt @@ -1,4 +1,4 @@ -*comment.txt* For Vim version 9.1. Last change: 2024 Oct 01 +*comment.txt* For Vim version 9.1. Last change: 2025 Mar 21 VIM REFERENCE MANUAL @@ -32,11 +32,20 @@ back to `gcc` otherwise, add the following mapping to your vimrc: > Note: using `gC` may not always result in valid comment markers depending on the language used. +Additionally, the plugin defines a comment text-object which requires syntax +highlighting to be enabled. + *v_ac* *ac* +ac "a comment", select current or next comment. + Leading and trailing white space is included. + Trailing newlines are included too. + *v_ic* *ic* +ic "inner comment", select current or next comment. + This plugin uses the buffer-local 'commentstring' option value to add or remove comment markers to the selected lines. Whether it will comment or un-comment -depends on the first line of the range of lines to act upon. When it matches -a comment marker, the line will be un-commented, if it doesn't, the line will -be commented out. Blank and empty lines are ignored. +depends on the range of lines to act upon. When all of the lines in range +have comment markers, all lines will be un-commented, if it doesn't, the lines +will be commented out. Blank and empty lines are ignored. The value of 'commentstring' is the same for the entire buffer and determined by its filetype (|filetypes|). To adapt it within the buffer for embedded diff --git a/runtime/pack/dist/opt/comment/doc/tags b/runtime/pack/dist/opt/comment/doc/tags index ffe4177cc..62c4afd6d 100644 --- a/runtime/pack/dist/opt/comment/doc/tags +++ b/runtime/pack/dist/opt/comment/doc/tags @@ -1,6 +1,10 @@ +ac comment.txt /*ac* b:comment_first_col comment.txt /*b:comment_first_col* comment.txt comment.txt /*comment.txt* g:comment_first_col comment.txt /*g:comment_first_col* gcc comment.txt /*gcc* +ic comment.txt /*ic* o_gc comment.txt /*o_gc* +v_ac comment.txt /*v_ac* v_gc comment.txt /*v_gc* +v_ic comment.txt /*v_ic* diff --git a/runtime/pack/dist/opt/comment/plugin/comment.vim b/runtime/pack/dist/opt/comment/plugin/comment.vim index 94ac0670b..67b431de6 100644 --- a/runtime/pack/dist/opt/comment/plugin/comment.vim +++ b/runtime/pack/dist/opt/comment/plugin/comment.vim @@ -1,9 +1,15 @@ vim9script # Maintainer: Maxim Kim <haba...@gmail.com> -# Last Update: 2024-04-26 +# Last Update: 2025 Mar 21 import autoload 'comment.vim' + nnoremap <silent> <expr> gc comment.Toggle() xnoremap <silent> <expr> gc comment.Toggle() nnoremap <silent> <expr> gcc comment.Toggle() .. '_' + +onoremap <silent>ic <scriptcmd>comment.ObjComment(v:true)<CR> +onoremap <silent>ac <scriptcmd>comment.ObjComment(v:false)<CR> +xnoremap <silent>ic <esc><scriptcmd>comment.ObjComment(v:true)<CR> +xnoremap <silent>ac <esc><scriptcmd>comment.ObjComment(v:false)<CR> diff --git a/src/testdir/test_plugin_comment.vim b/src/testdir/test_plugin_comment.vim index 8e877acdb..a0425d58d 100644 --- a/src/testdir/test_plugin_comment.vim +++ b/src/testdir/test_plugin_comment.vim @@ -29,7 +29,6 @@ func Test_basic_comment() call assert_equal(["# vim9script", "", "# def Hello()", '# echo "Hello"', "# enddef"], result) endfunc - func Test_basic_uncomment() CheckScreendump let lines =<< trim END @@ -55,7 +54,7 @@ func Test_basic_uncomment() let result = readfile(output_file) - call assert_equal(["# vim9script", "", "def Hello()", ' echo "Hello"', "enddef"], result) + call assert_equal(["# vim9script", "", "def Hello()", ' echo "Hello"', "enddef"], result) endfunc func Test_bothends_comment() @@ -177,3 +176,341 @@ func Test_mixed_indent_comment() call assert_equal(["/* int main() { */", " /* if 1 { */", " /* return 0; */", " /* } */", " /* return 1; */", "/* } */"], result) endfunc + +func Test_textobj_icomment() + CheckScreendump + let lines =<< trim END + for x in range(10): + print(x) # printing stuff + # print(x*x) + #print(x*x*x) + print(x*x*x*x) # printing stuff + print(x*x*x*x*x) # printing stuff + # print(x*x) + #print(x*x*x) + + print(x*x*x*x*x) + END + + let input_file = "test_textobj_icomment_input.py" + call writefile(lines, input_file, "D") + + let buf = RunVimInTerminal('-c "packadd comment" ' .. input_file, {}) + + call term_sendkeys(buf, "dic..") + let output_file = "comment_textobj_icomment.py" + call term_sendkeys(buf, $":w {output_file}\<CR>") + defer delete(output_file) + + call StopVimInTerminal(buf) + + let result = readfile(output_file) + + call assert_equal(["for x in range(10):", " print(x) ", " print(x*x*x*x) ", " print(x*x*x*x*x) ", "", " print(x*x*x*x*x)"], result) +endfunc + +func Test_textobj_icomment2() + CheckScreendump + let lines =<< trim END + #include <stdio.h> + + int main() { + printf("hello"); /* hello world */ printf(" world "); + /* if 1 { + return 1; + }*/ + + return 0; + } + END + + let input_file = "test_textobj_icomment2_input.c" + call writefile(lines, input_file, "D") + + let buf = RunVimInTerminal('-c "packadd comment" ' .. input_file, {}) + + call term_sendkeys(buf, "dic..") + let output_file = "comment_textobj_icomment2.c" + call term_sendkeys(buf, $":w {output_file}\<CR>") + defer delete(output_file) + + call StopVimInTerminal(buf) + + let result = readfile(output_file) + + call assert_equal(["#include <stdio.h>", "", "int main() {", " printf(\"hello\"); printf(\" world\n\");", " ", "", " return 0;", "}"], result) +endfunc + +func Test_textobj_icomment3() + CheckScreendump + let lines =<< trim END + #include <stdio.h> + + int main() { + printf("hello");/*hello world*/printf(" world "); + return 0; + } + END + + let input_file = "test_textobj_icomment3_input.c" + call writefile(lines, input_file, "D") + + let buf = RunVimInTerminal('-c "packadd comment" ' .. input_file, {}) + + call term_sendkeys(buf, "jjjdic") + let output_file = "comment_textobj_icomment3.c" + call term_sendkeys(buf, $":w {output_file}\<CR>") + defer delete(output_file) + + call StopVimInTerminal(buf) + + let result = readfile(output_file) + + call assert_equal(["#include <stdio.h>", "", "int main() {", " printf(\"hello\");printf(\" world\n\");", " return 0;", "}"], result) +endfunc + +func Test_textobj_acomment() + CheckScreendump + let lines =<< trim END + for x in range(10): + print(x) # printing stuff + # print(x*x) + #print(x*x*x) + print(x*x*x*x) # printing stuff + print(x*x*x*x*x) # printing stuff + # print(x*x) + #print(x*x*x) + + print(x*x*x*x*x) + END + + let input_file = "test_textobj_acomment_input.py" + call writefile(lines, input_file, "D") + + let buf = RunVimInTerminal('-c "packadd comment" ' .. input_file, {}) + + call term_sendkeys(buf, "dac..") + let output_file = "comment_textobj_acomment.py" + call term_sendkeys(buf, $":w {output_file}\<CR>") + defer delete(output_file) + + call StopVimInTerminal(buf) + + let result = readfile(output_file) + + call assert_equal(["for x in range(10):", " print(x)", " print(x*x*x*x)", " print(x*x*x*x*x)", "", " print(x*x*x*x*x)"], result) +endfunc + +func Test_textobj_acomment2() + CheckScreendump + let lines =<< trim END + #include <stdio.h> + + int main() { + printf("hello"); /* hello world */ printf(" world "); + /* if 1 { + return 1; + }*/ + + return 0; + } + END + + let input_file = "test_textobj_acomment2_input.c" + call writefile(lines, input_file, "D") + + let buf = RunVimInTerminal('-c "packadd comment" ' .. input_file, {}) + + call term_sendkeys(buf, "dac.") + let output_file = "comment_textobj_acomment2.c" + call term_sendkeys(buf, $":w {output_file}\<CR>") + defer delete(output_file) + + call StopVimInTerminal(buf) + + let result = readfile(output_file) + + call assert_equal(["#include <stdio.h>", "", "int main() {", " printf(\"hello\");printf(\" world\n\");", " return 0;", "}"], result) +endfunc + +func Test_textobj_acomment3() + CheckScreendump + let lines =<< trim END + #include <stdio.h> + + int main() { + printf("hello");/*hello world*/printf(" world "); + return 0; + } + END + + let input_file = "test_textobj_acomment3_input.c" + call writefile(lines, input_file, "D") + + let buf = RunVimInTerminal('-c "packadd comment" ' .. input_file, {}) + + call term_sendkeys(buf, "jjjdac") + let output_file = "comment_textobj_acomment3.c" + call term_sendkeys(buf, $":w {output_file}\<CR>") + defer delete(output_file) + + call StopVimInTerminal(buf) + + let result = readfile(output_file) + + call assert_equal(["#include <stdio.h>", "", "int main() {", " printf(\"hello\");printf(\" world\n\");", " return 0;", "}"], result) +endfunc + +func Test_textobj_firstline_comment() + CheckScreendump + let lines =<< trim END + /*#include <stdio.h>*/ + + int main() {} + END + + let input_file = "test_textobj_firstlinecomment_input.c" + call writefile(lines, input_file, "D") + + let buf = RunVimInTerminal('-c "packadd comment" ' .. input_file, {}) + + call term_sendkeys(buf, "dac") + let output_file = "comment_textobj_firstline_comment.c" + call term_sendkeys(buf, $":w {output_file}\<CR>") + defer delete(output_file) + + call StopVimInTerminal(buf) + + let result = readfile(output_file) + + call assert_equal(["int main() {}"], result) +endfunc + +func Test_textobj_noleading_space_comment() + CheckScreendump + let lines =<< trim END + int main() {// main start + }/* main end */ + END + + let input_file = "test_textobj_noleading_space_input.c" + call writefile(lines, input_file, "D") + + let buf = RunVimInTerminal('-c "packadd comment" ' .. input_file, {}) + + call term_sendkeys(buf, "dacdic") + let output_file = "comment_textobj_noleading_space_comment.c" + call term_sendkeys(buf, $":w {output_file}\<CR>") + defer delete(output_file) + + call StopVimInTerminal(buf) + + let result = readfile(output_file) + + call assert_equal(["int main() {", "}"], result) +endfunc + +func Test_textobj_noleading_space_comment2() + CheckScreendump + let lines =<< trim END + int main() {// main start + } /* main end */ + END + + let input_file = "test_textobj_noleading_space_input2.c" + call writefile(lines, input_file, "D") + + let buf = RunVimInTerminal('-c "packadd comment" ' .. input_file, {}) + + call term_sendkeys(buf, "dac.") + let output_file = "comment_textobj_noleading_space_comment2.c" + call term_sendkeys(buf, $":w {output_file}\<CR>") + defer delete(output_file) + + call StopVimInTerminal(buf) + + let result = readfile(output_file) + + call assert_equal(["int main() {", "}"], result) +endfunc + +func Test_textobj_cursor_on_leading_space_comment() + CheckScreendump + let lines =<< trim END + int main() { + // multilple comments + // cursor is between them + } + END + + let input_file = "test_textobj_cursor_on_leading_space_comment_input.c" + call writefile(lines, input_file, "D") + + let buf = RunVimInTerminal('-c "packadd comment" ' .. input_file, {}) + + call term_sendkeys(buf, "jjdac") + let output_file = "comment_textobj_cursor_on_leading_space_comment.c" + call term_sendkeys(buf, $":w {output_file}\<CR>") + defer delete(output_file) + + call StopVimInTerminal(buf) + + let result = readfile(output_file) + + call assert_equal(["int main() {", "", "}"], result) +endfunc + +func Test_textobj_conseq_comment() + CheckScreendump + let lines =<< trim END + int main() { + printf("hello"); // hello + // world + printf("world"); + } + END + + let input_file = "test_textobj_conseq_comment_input.c" + call writefile(lines, input_file, "D") + + let buf = RunVimInTerminal('-c "packadd comment" ' .. input_file, {}) + + call term_sendkeys(buf, "dac") + let output_file = "comment_textobj_conseq_comment.c" + call term_sendkeys(buf, $":w {output_file}\<CR>") + defer delete(output_file) + + call StopVimInTerminal(buf) + + let result = readfile(output_file) + + call assert_equal(["int main() {", " printf(\"hello\");", " printf(\"world\");", "}"], result) +endfunc + +func Test_textobj_conseq_comment2() + CheckScreendump + let lines =<< trim END + int main() { + printf("hello"); // hello + + // world + printf("world"); + } + END + + let input_file = "test_textobj_conseq_comment_input2.c" + call writefile(lines, input_file, "D") + + let buf = RunVimInTerminal('-c "packadd comment" ' .. input_file, {}) + + call term_sendkeys(buf, "dac") + let output_file = "comment_textobj_conseq_comment2.c" + call term_sendkeys(buf, $":w {output_file}\<CR>") + defer delete(output_file) + + call StopVimInTerminal(buf) + + let result = readfile(output_file) + + call assert_equal(["int main() {", " printf(\"hello\");", "", " // world", " printf(\"world\");", "}"], result) +endfunc diff --git a/src/version.c b/src/version.c index 18bf939a0..7debc1ab7 100644 --- a/src/version.c +++ b/src/version.c @@ -704,6 +704,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1229, /**/ 1228, /**/ -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to vim_dev+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/vim_dev/E1tvfxX-0072RU-63%40256bit.org.