diff --git a/development/tests/test-keymaps.lua b/development/tests/test-keymaps.lua index e5a8162..af3fbce 100644 --- a/development/tests/test-keymaps.lua +++ b/development/tests/test-keymaps.lua @@ -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 , 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 ~= 'word 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 ~= 'second 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 gamma' 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 two 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. diff --git a/development/vimwiki-gap.md b/development/vimwiki-gap.md index 12f55c9..76245d5 100644 --- a/development/vimwiki-gap.md +++ b/development/vimwiki-gap.md @@ -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 - `` (`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 + `` (`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 ``. 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 `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 diff --git a/ftplugin/vimwiki.vim b/ftplugin/vimwiki.vim index c77e6cb..f483a19 100644 --- a/ftplugin/vimwiki.vim +++ b/ftplugin/vimwiki.vim @@ -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() 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() 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() diff --git a/lua/nuwiki/commands.lua b/lua/nuwiki/commands.lua index 607ca66..1a159c4 100644 --- a/lua/nuwiki/commands.lua +++ b/lua/nuwiki/commands.lua @@ -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('', color) local close_tag = '' - 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('') if cword == '' then return end local col = vim.api.nvim_win_get_cursor(0)[2] diff --git a/lua/nuwiki/keymaps.lua b/lua/nuwiki/keymaps.lua index 2649b41..20eda56 100644 --- a/lua/nuwiki/keymaps.lua +++ b/lua/nuwiki/keymaps.lua @@ -176,7 +176,7 @@ function M.attach(bufnr, mappings) map('n', 'wr', cmd.rename_file, { desc = 'nuwiki: rename page' }, bufnr) map('n', 'wc', function() cmd.colorize() end, { desc = 'nuwiki: wrap word in colour span' }, bufnr) - map('x', 'wc', function() cmd.colorize() end, + map('x', 'wc', function() cmd.colorize(nil, true) end, { desc = 'nuwiki: wrap selection in colour span' }, bufnr) end