diff options
author | Evgeni Chasnovski <evgeni.chasnovski@gmail.com> | 2024-05-23 23:30:53 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-23 15:30:53 -0500 |
commit | 0a2218f965ac8cd7967d33b8c52e5b06fb284aac (patch) | |
tree | 69d79f792771da62a27c565cc1045287fd9ec40d | |
parent | c614969570ac13cfc1ff6642fcaf56ebce6d40be (diff) | |
download | rneovim-0a2218f965ac8cd7967d33b8c52e5b06fb284aac.tar.gz rneovim-0a2218f965ac8cd7967d33b8c52e5b06fb284aac.tar.bz2 rneovim-0a2218f965ac8cd7967d33b8c52e5b06fb284aac.zip |
fix(comment): fall back to using trimmed comment markers (#28938)
Problem: Currently comment detection, addition, and removal are done
by matching 'commentstring' exactly. This has the downside when users
want to add comment markers with space (like with `-- %s`
commentstring) but also be able to uncomment lines that do not contain
space (like `--aaa`).
Solution: Use the following approach:
- Line is commented if it matches 'commentstring' with trimmed parts.
- Adding comment is 100% relying on 'commentstring' parts (as is now).
- Removing comment is first trying exact 'commentstring' parts with
fallback on trying its trimmed parts.
-rw-r--r-- | runtime/doc/various.txt | 4 | ||||
-rw-r--r-- | runtime/lua/vim/_comment.lua | 19 | ||||
-rw-r--r-- | test/functional/lua/comment_spec.lua | 39 |
3 files changed, 35 insertions, 27 deletions
diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt index d41bdb5b00..662be4a7a2 100644 --- a/runtime/doc/various.txt +++ b/runtime/doc/various.txt @@ -579,6 +579,10 @@ Acting on multiple lines behaves as follows: transformed to empty comments (e.g. `/**/`). Comment markers are aligned to the least indented line. +Matching 'commentstring' does not account for whitespace in comment markers. +Removing comment markers is first attempted exactly, with fallback to using +markers trimmed from whitespace. + If the filetype of the buffer is associated with a language for which a |treesitter| parser is installed, then |vim.filetype.get_option()| is called to look up the value of 'commentstring' corresponding to the cursor position. diff --git a/runtime/lua/vim/_comment.lua b/runtime/lua/vim/_comment.lua index b6cb6c9884..044cd69716 100644 --- a/runtime/lua/vim/_comment.lua +++ b/runtime/lua/vim/_comment.lua @@ -77,14 +77,11 @@ local function make_comment_check(parts) local l_esc, r_esc = vim.pesc(parts.left), vim.pesc(parts.right) -- Commented line has the following structure: - -- <possible whitespace> <left> <anything> <right> <possible whitespace> - local nonblank_regex = '^%s-' .. l_esc .. '.*' .. r_esc .. '%s-$' - - -- Commented blank line can have any amount of whitespace around parts - local blank_regex = '^%s-' .. vim.trim(l_esc) .. '%s*' .. vim.trim(r_esc) .. '%s-$' + -- <whitespace> <trimmed left> <anything> <trimmed right> <whitespace> + local regex = '^%s-' .. vim.trim(l_esc) .. '.*' .. vim.trim(r_esc) .. '%s-$' return function(line) - return line:find(nonblank_regex) ~= nil or line:find(blank_regex) ~= nil + return line:find(regex) ~= nil end end @@ -153,14 +150,14 @@ end ---@return fun(line: string): string local function make_uncomment_function(parts) local l_esc, r_esc = vim.pesc(parts.left), vim.pesc(parts.right) - local nonblank_regex = '^(%s*)' .. l_esc .. '(.*)' .. r_esc .. '(%s-)$' - local blank_regex = '^(%s*)' .. vim.trim(l_esc) .. '(%s*)' .. vim.trim(r_esc) .. '(%s-)$' + local regex = '^(%s*)' .. l_esc .. '(.*)' .. r_esc .. '(%s-)$' + local regex_trimmed = '^(%s*)' .. vim.trim(l_esc) .. '(.*)' .. vim.trim(r_esc) .. '(%s-)$' return function(line) - -- Try both non-blank and blank regexes - local indent, new_line, trail = line:match(nonblank_regex) + -- Try regex with exact comment parts first, fall back to trimmed parts + local indent, new_line, trail = line:match(regex) if new_line == nil then - indent, new_line, trail = line:match(blank_regex) + indent, new_line, trail = line:match(regex_trimmed) end -- Return original if line is not commented diff --git a/test/functional/lua/comment_spec.lua b/test/functional/lua/comment_spec.lua index 9b1d9613cb..bbf061a2ab 100644 --- a/test/functional/lua/comment_spec.lua +++ b/test/functional/lua/comment_spec.lua @@ -301,27 +301,34 @@ describe('commenting', function() eq(get_lines(), { 'aa', '', ' ', '\t', 'aa' }) end) - it('matches comment parts strictly when detecting comment/uncomment', function() + it('correctly matches comment parts during checking and uncommenting', function() local validate = function(from, to, ref_lines) - set_lines({ '#aa', '# aa', '# aa' }) + set_lines({ '/*aa*/', '/* aa */', '/* aa */' }) toggle_lines(from, to) eq(get_lines(), ref_lines) end - set_commentstring('#%s') - validate(1, 3, { 'aa', ' aa', ' aa' }) - validate(2, 3, { '#aa', ' aa', ' aa' }) - validate(3, 3, { '#aa', '# aa', ' aa' }) - - set_commentstring('# %s') - validate(1, 3, { '# #aa', '# # aa', '# # aa' }) - validate(2, 3, { '#aa', 'aa', ' aa' }) - validate(3, 3, { '#aa', '# aa', ' aa' }) - - set_commentstring('# %s') - validate(1, 3, { '# #aa', '# # aa', '# # aa' }) - validate(2, 3, { '#aa', '# # aa', '# # aa' }) - validate(3, 3, { '#aa', '# aa', 'aa' }) + -- Should first try to match 'commentstring' parts exactly with their + -- whitespace, with fallback on trimmed parts + set_commentstring('/*%s*/') + validate(1, 3, { 'aa', ' aa ', ' aa ' }) + validate(2, 3, { '/*aa*/', ' aa ', ' aa ' }) + validate(3, 3, { '/*aa*/', '/* aa */', ' aa ' }) + + set_commentstring('/* %s */') + validate(1, 3, { 'aa', 'aa', ' aa ' }) + validate(2, 3, { '/*aa*/', 'aa', ' aa ' }) + validate(3, 3, { '/*aa*/', '/* aa */', ' aa ' }) + + set_commentstring('/* %s */') + validate(1, 3, { 'aa', ' aa ', 'aa' }) + validate(2, 3, { '/*aa*/', ' aa ', 'aa' }) + validate(3, 3, { '/*aa*/', '/* aa */', 'aa' }) + + set_commentstring(' /*%s*/ ') + validate(1, 3, { 'aa', ' aa ', ' aa ' }) + validate(2, 3, { '/*aa*/', ' aa ', ' aa ' }) + validate(3, 3, { '/*aa*/', '/* aa */', ' aa ' }) end) it('uncomments on inconsistent indent levels', function() |