fix(client): VimwikiColorize passes its {color} arg on Neovim + visual fix
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:
@@ -716,6 +716,52 @@ vim.defer_fn(function()
|
||||
-- a populated diary, but at least confirm the maps fire without
|
||||
-- error.
|
||||
|
||||
-- ===== Colorize commands pass their {color} arg (regression) =====
|
||||
-- :VimwikiColorize / :NuwikiColorize are -nargs=1; the Neovim defs used to
|
||||
-- call colorize() without <q-args>, silently dropping the colour and
|
||||
-- prompting instead. Run the real commands and assert the colour lands.
|
||||
tobj_case('cmd.VimwikiColorize_uses_arg', function()
|
||||
set_buf({ 'word here' })
|
||||
vim.api.nvim_win_set_cursor(0, { 1, 0 })
|
||||
vim.cmd('VimwikiColorize red')
|
||||
local got = vim.api.nvim_get_current_line()
|
||||
if got ~= '<span style="color:red">word</span> here' then
|
||||
error('VimwikiColorize dropped its arg: ' .. got)
|
||||
end
|
||||
end)
|
||||
tobj_case('cmd.NuwikiColorize_uses_arg', function()
|
||||
set_buf({ 'second word' })
|
||||
vim.api.nvim_win_set_cursor(0, { 1, 0 })
|
||||
vim.cmd('NuwikiColorize #00ff00')
|
||||
local got = vim.api.nvim_get_current_line()
|
||||
if got ~= '<span style="color:#00ff00">second</span> word' then
|
||||
error('NuwikiColorize dropped its arg: ' .. got)
|
||||
end
|
||||
end)
|
||||
-- Establish a stale visual selection, then confirm the normal-mode command
|
||||
-- still wraps the cword (not the leftover selection) — the visualmode()
|
||||
-- heuristic regression.
|
||||
tobj_case('cmd.Colorize_ignores_stale_visual_selection', function()
|
||||
set_buf({ 'alpha beta gamma' })
|
||||
vim.cmd('normal! 0vee\27') -- select 'alpha beta', leave marks behind
|
||||
vim.api.nvim_win_set_cursor(0, { 1, 11 }) -- on 'gamma'
|
||||
vim.cmd('VimwikiColorize blue')
|
||||
local got = vim.api.nvim_get_current_line()
|
||||
if got ~= 'alpha beta <span style="color:blue">gamma</span>' then
|
||||
error('command wrapped stale selection instead of cword: ' .. got)
|
||||
end
|
||||
end)
|
||||
-- The visual mapping path (explicit visual=true) wraps the selection.
|
||||
tobj_case('colorize.visual_wraps_selection', function()
|
||||
set_buf({ 'one two three' })
|
||||
vim.cmd('normal! 0wviw\27') -- visually select 'two', marks set on exit
|
||||
require('nuwiki.commands').colorize('red', true)
|
||||
local got = vim.api.nvim_get_current_line()
|
||||
if got ~= 'one <span style="color:red">two</span> three' then
|
||||
error('visual colorize did not wrap selection: ' .. got)
|
||||
end
|
||||
end)
|
||||
|
||||
-- ===== Wiki picker (config-driven, no LSP) =====
|
||||
-- The picker must build its list from config so it works from any buffer
|
||||
-- before the server attaches.
|
||||
|
||||
@@ -121,11 +121,19 @@ fix site.
|
||||
- [ ] `:VimwikiSearch` / `VWS` uses `lvimgrep`, not vimwiki's search engine.
|
||||
- [ ] `VimwikiIndex` family is buffer-local in nuwiki (upstream defines globally
|
||||
in `plugin/`); only `:…UISelect` is a global entry point.
|
||||
- [ ] **`VimwikiColorize` / `NuwikiColorize` drop their argument in the Neovim
|
||||
branch** — both are `-nargs=1`, but the Neovim defs call `colorize()` with no
|
||||
`<q-args>` (`ftplugin/vimwiki.vim:445,517`) while the Vim branch passes it
|
||||
(`:106,177`). The color name is silently ignored under Neovim (real bug, not
|
||||
just parity). _Fix:_ `ftplugin/vimwiki.vim` Neovim branch.
|
||||
- [x] **`VimwikiColorize` / `NuwikiColorize` drop their argument in the Neovim
|
||||
branch** — both are `-nargs=1`, but the Neovim defs called `colorize()` with no
|
||||
`<q-args>` (`ftplugin/vimwiki.vim:445,517`) while the Vim branch passes it. The
|
||||
color name was silently ignored under Neovim (real bug, not just parity).
|
||||
_Fix:_ Neovim command defs now pass `<q-args>`. While verifying, found a second
|
||||
bug: `colorize()` inferred visual-vs-normal from `vim.fn.visualmode()`, which
|
||||
returns the *last* session visual mode with stale `'<`/`'>` marks — so the
|
||||
normal-mode command wrapped a leftover selection instead of the cword.
|
||||
`colorize(color, visual)` now takes an explicit `visual` flag passed only by
|
||||
the `x`-mode `<Leader>wc` mapping (`lua/nuwiki/keymaps.lua`); the command and
|
||||
normal mapping always wrap the cword. Covered by `cmd.VimwikiColorize_uses_arg`,
|
||||
`cmd.Colorize_ignores_stale_visual_selection`, and
|
||||
`colorize.visual_wraps_selection` in `development/tests/test-keymaps.lua`.
|
||||
- [ ] **`VimwikiTableMoveColumn{Left,Right}` dispatch to different backing names
|
||||
per client** — Vim branch → `table_move_left/right`; Neovim branch →
|
||||
`table_move_column_left/right`. Harmless today (each name exists in its own
|
||||
|
||||
@@ -442,7 +442,7 @@ command! -buffer -nargs=? VimwikiGenerateTags lua require('nuwiki.commands'
|
||||
command! -buffer -nargs=1 VimwikiTable lua require('nuwiki.commands').table_insert()
|
||||
command! -buffer VimwikiTableMoveColumnLeft lua require('nuwiki.commands').table_move_column_left()
|
||||
command! -buffer VimwikiTableMoveColumnRight lua require('nuwiki.commands').table_move_column_right()
|
||||
command! -buffer -nargs=1 VimwikiColorize lua require('nuwiki.commands').colorize()
|
||||
command! -buffer -nargs=1 VimwikiColorize lua require('nuwiki.commands').colorize(<q-args>)
|
||||
command! -buffer VimwikiPasteLink lua require('nuwiki.commands').paste_link()
|
||||
command! -buffer VimwikiPasteUrl lua require('nuwiki.commands').paste_url()
|
||||
command! -buffer VimwikiCatUrl lua require('nuwiki.commands').cat_url()
|
||||
@@ -514,7 +514,7 @@ command! -buffer NuwikiTableAlign lua require('nuwiki.command
|
||||
command! -buffer -nargs=1 NuwikiTable lua require('nuwiki.commands').table_insert()
|
||||
command! -buffer NuwikiTableMoveColumnLeft lua require('nuwiki.commands').table_move_column_left()
|
||||
command! -buffer NuwikiTableMoveColumnRight lua require('nuwiki.commands').table_move_column_right()
|
||||
command! -buffer -nargs=1 NuwikiColorize lua require('nuwiki.commands').colorize()
|
||||
command! -buffer -nargs=1 NuwikiColorize lua require('nuwiki.commands').colorize(<q-args>)
|
||||
command! -buffer NuwikiPasteLink lua require('nuwiki.commands').paste_link()
|
||||
command! -buffer NuwikiPasteUrl lua require('nuwiki.commands').paste_url()
|
||||
command! -buffer NuwikiCatUrl lua require('nuwiki.commands').cat_url()
|
||||
|
||||
+17
-6
@@ -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 visual then
|
||||
local sl, sc, el, ec = visual_selection_range()
|
||||
if sl and sl == el then
|
||||
-- Single-line visual selection.
|
||||
local new_line = line:sub(1, sc)
|
||||
local sline = vim.api.nvim_buf_get_lines(0, sl - 1, sl, false)[1] or ''
|
||||
local new_line = sline:sub(1, sc)
|
||||
.. open_tag
|
||||
.. line:sub(sc + 1, ec + 1)
|
||||
.. sline:sub(sc + 1, ec + 1)
|
||||
.. close_tag
|
||||
.. line:sub(ec + 2)
|
||||
.. sline:sub(ec + 2)
|
||||
vim.api.nvim_buf_set_lines(0, sl - 1, sl, false, { new_line })
|
||||
return
|
||||
end
|
||||
-- Fall back to the cword.
|
||||
-- Multi-line or no usable selection: fall through to the cword.
|
||||
end
|
||||
-- Wrap the cword.
|
||||
local cword = vim.fn.expand('<cword>')
|
||||
if cword == '' then return end
|
||||
local col = vim.api.nvim_win_get_cursor(0)[2]
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user