fix(client): VimwikiColorize passes its {color} arg on Neovim + visual fix
CI / cargo fmt --check (push) Successful in 18s
CI / cargo clippy (push) Successful in 27s
CI / cargo test (push) Successful in 29s
CI / editor keymaps (push) Successful in 1m23s

The Neovim command defs for :VimwikiColorize / :NuwikiColorize were
-nargs=1 but called colorize() without <q-args>, so the colour name was
silently dropped and the user was prompted instead (the Vim branch passed
it correctly). Pass <q-args>.

While verifying, found a second bug in the Lua colorize(): it inferred
visual-vs-normal from vim.fn.visualmode(), which returns the *last* visual
mode used in the session along with stale '< / '> marks. So running
:VimwikiColorize in normal mode after any earlier visual selection wrapped
that leftover selection instead of the word under the cursor (produced an
empty, misplaced span). colorize(color, visual) now takes an explicit
visual flag, passed only by the x-mode <Leader>wc mapping; the command and
the normal-mode mapping always wrap the cword.

Tests: cmd.VimwikiColorize_uses_arg, cmd.NuwikiColorize_uses_arg,
cmd.Colorize_ignores_stale_visual_selection, colorize.visual_wraps_selection
in test-keymaps.lua. nvim suite 267, vim suite 254+18, all green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-31 15:18:31 +00:00
parent 39692ba99f
commit 66bfd61a63
5 changed files with 85 additions and 20 deletions
+23 -12
View File
@@ -960,27 +960,38 @@ local function visual_selection_range()
return s[1], s[2], e[1], e[2]
end
function M.colorize(color)
-- colorize(color, visual): wrap text in an inline colour span.
--
-- `visual` MUST be passed only by the visual-mode mapping — it means "act on
-- the `'<`/`'>` selection". We can't infer it from `vim.fn.visualmode()`,
-- which returns the *last* visual mode used in the session (with stale marks),
-- so the normal-mode command / mapping would otherwise wrap whatever was last
-- selected instead of the word under the cursor.
function M.colorize(color, visual)
if not color or color == '' then
color = vim.fn.input('Colour: ')
if color == '' then return end
end
local sl, sc, el, ec = visual_selection_range()
local row = vim.api.nvim_win_get_cursor(0)[1]
local line = vim.api.nvim_get_current_line()
local open_tag = string.format('<span style="color:%s">', color)
local close_tag = '</span>'
if sl and sl == el then
-- Single-line visual selection.
local new_line = line:sub(1, sc)
.. open_tag
.. line:sub(sc + 1, ec + 1)
.. close_tag
.. line:sub(ec + 2)
vim.api.nvim_buf_set_lines(0, sl - 1, sl, false, { new_line })
return
if visual then
local sl, sc, el, ec = visual_selection_range()
if sl and sl == el then
-- Single-line visual selection.
local sline = vim.api.nvim_buf_get_lines(0, sl - 1, sl, false)[1] or ''
local new_line = sline:sub(1, sc)
.. open_tag
.. sline:sub(sc + 1, ec + 1)
.. close_tag
.. sline:sub(ec + 2)
vim.api.nvim_buf_set_lines(0, sl - 1, sl, false, { new_line })
return
end
-- Multi-line or no usable selection: fall through to the cword.
end
-- Fall back to the cword.
-- Wrap the cword.
local cword = vim.fn.expand('<cword>')
if cword == '' then return end
local col = vim.api.nvim_win_get_cursor(0)[2]
+1 -1
View File
@@ -176,7 +176,7 @@ function M.attach(bufnr, mappings)
map('n', '<Leader>wr', cmd.rename_file, { desc = 'nuwiki: rename page' }, bufnr)
map('n', '<Leader>wc', function() cmd.colorize() end,
{ desc = 'nuwiki: wrap word in colour span' }, bufnr)
map('x', '<Leader>wc', function() cmd.colorize() end,
map('x', '<Leader>wc', function() cmd.colorize(nil, true) end,
{ desc = 'nuwiki: wrap selection in colour span' }, bufnr)
end