fix(client): VimwikiColorize accepts a range (no more E481 on selection)
Selecting text and running :VimwikiColorize {color} raised
"E481: No range allowed" — Vim prepends '<,'> to the command when invoked
from a visual selection, but the command was defined without -range.
All four colorize command defs (Vim + Neovim, Vimwiki* + Nuwiki*) are now
-range and forward the range count to the handler. A ranged (visual)
invocation wraps the '< / '> selection; a bare invocation wraps the cword.
The x-mode <Leader>wc mapping passes the visual flag explicitly.
The Vim-branch colorize() gained selection support (it was cword-only),
matching the Neovim branch, so both clients wrap a visual selection
identically. visual_selection_range() (Lua) no longer gates on
vim.fn.visualmode() — the explicit visual flag now carries that intent, and
the marks check guards unset selections.
Tests: cmd.Colorize_range_wraps_selection (nvim) and
colorize.{command_wraps_cword,visual_wraps_selection,ranged_command_no_error}
(vim). nvim 268, vim 257+18, all green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -855,10 +855,14 @@ function! nuwiki#commands#table_move_right() abort
|
|||||||
\ }]
|
\ }]
|
||||||
call s:exec('nuwiki.table.moveColumn', l:args)
|
call s:exec('nuwiki.table.moveColumn', l:args)
|
||||||
endfunction
|
endfunction
|
||||||
" `:VimwikiColorize {color}` — pure-VimL wrap as inline span tag,
|
" `:VimwikiColorize {color}` — wrap text in an inline colour span, matching
|
||||||
" matching vimwiki's `<span style="color:%c">%s</span>` template.
|
" vimwiki's `<span style="color:%c">%s</span>` template. Wraps the visual
|
||||||
|
" selection when invoked with a range (`:'<,'>VimwikiColorize` / the `x`-mode
|
||||||
|
" <Leader>wc mapping), otherwise the word under the cursor.
|
||||||
|
" a:1 = colour (empty → prompt); a:2 = range count (>0 → use the selection).
|
||||||
function! nuwiki#commands#colorize(...) abort
|
function! nuwiki#commands#colorize(...) abort
|
||||||
let l:color = a:0 >= 1 ? a:1 : ''
|
let l:color = a:0 >= 1 ? a:1 : ''
|
||||||
|
let l:visual = a:0 >= 2 && a:2 > 0
|
||||||
if l:color ==# ''
|
if l:color ==# ''
|
||||||
let l:color = input('Colour: ')
|
let l:color = input('Colour: ')
|
||||||
endif
|
endif
|
||||||
@@ -867,6 +871,28 @@ function! nuwiki#commands#colorize(...) abort
|
|||||||
endif
|
endif
|
||||||
let l:open_tag = '<span style="color:' . l:color . '">'
|
let l:open_tag = '<span style="color:' . l:color . '">'
|
||||||
let l:close_tag = '</span>'
|
let l:close_tag = '</span>'
|
||||||
|
|
||||||
|
if l:visual
|
||||||
|
let l:sp = getpos("'<")
|
||||||
|
let l:ep = getpos("'>")
|
||||||
|
if l:sp[1] > 0 && l:sp[1] == l:ep[1]
|
||||||
|
let l:line = getline(l:sp[1])
|
||||||
|
let l:sc = l:sp[2]
|
||||||
|
let l:ec = l:ep[2]
|
||||||
|
if l:ec > strlen(l:line)
|
||||||
|
let l:ec = strlen(l:line)
|
||||||
|
endif
|
||||||
|
if l:ec >= l:sc
|
||||||
|
let l:new = strpart(l:line, 0, l:sc - 1)
|
||||||
|
\ . l:open_tag . strpart(l:line, l:sc - 1, l:ec - l:sc + 1) . l:close_tag
|
||||||
|
\ . strpart(l:line, l:ec)
|
||||||
|
call setline(l:sp[1], l:new)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
" Multi-line or empty selection: fall through to the cword.
|
||||||
|
endif
|
||||||
|
|
||||||
let l:line = getline('.')
|
let l:line = getline('.')
|
||||||
let l:col = col('.')
|
let l:col = col('.')
|
||||||
" Word boundaries around cursor (1-based).
|
" Word boundaries around cursor (1-based).
|
||||||
|
|||||||
@@ -477,6 +477,44 @@ call s:record(
|
|||||||
\ 'ext=' . get(get(s:wl, 1, {}), 'ext', ''))
|
\ 'ext=' . get(get(s:wl, 1, {}), 'ext', ''))
|
||||||
unlet g:nuwiki_wikis
|
unlet g:nuwiki_wikis
|
||||||
|
|
||||||
|
" ===== Colorize (cword, visual selection, ranged command) =====
|
||||||
|
" The command is -nargs=1 -range: normal invocation wraps the cword; a visual
|
||||||
|
" range (`:'<,'>VimwikiColorize` / the x-mode <Leader>wc map) wraps the
|
||||||
|
" selection. Run these while still on the vimwiki buffer (the buffer-local
|
||||||
|
" command must be defined).
|
||||||
|
call s:set_buf(['word here'])
|
||||||
|
call cursor(1, 1)
|
||||||
|
silent VimwikiColorize red
|
||||||
|
call s:record(
|
||||||
|
\ getline(1) ==# '<span style="color:red">word</span> here' ? 1 : 0,
|
||||||
|
\ 'colorize.command_wraps_cword',
|
||||||
|
\ 'got ' . string(getline(1)))
|
||||||
|
|
||||||
|
" Visual selection → wraps the selection (visual flag passed explicitly).
|
||||||
|
call s:set_buf(['one two three'])
|
||||||
|
call cursor(1, 5)
|
||||||
|
call feedkeys("viw\<Esc>", 'tx')
|
||||||
|
call nuwiki#commands#colorize('blue', 2)
|
||||||
|
call s:record(
|
||||||
|
\ getline(1) ==# 'one <span style="color:blue">two</span> three' ? 1 : 0,
|
||||||
|
\ 'colorize.visual_wraps_selection',
|
||||||
|
\ 'got ' . string(getline(1)))
|
||||||
|
|
||||||
|
" Ranged command must not raise E481 and wraps the selection.
|
||||||
|
call s:set_buf(['alpha beta gamma'])
|
||||||
|
call cursor(1, 8)
|
||||||
|
call feedkeys("viw\<Esc>", 'tx')
|
||||||
|
let s:cz_err = ''
|
||||||
|
try
|
||||||
|
silent '<,'>VimwikiColorize green
|
||||||
|
catch
|
||||||
|
let s:cz_err = v:exception
|
||||||
|
endtry
|
||||||
|
call s:record(
|
||||||
|
\ s:cz_err ==# '' && getline(1) ==# 'alpha <span style="color:green">beta</span> gamma' ? 1 : 0,
|
||||||
|
\ 'colorize.ranged_command_no_error',
|
||||||
|
\ 'err=' . s:cz_err . ' got ' . string(getline(1)))
|
||||||
|
|
||||||
" ===== Follow-link resolves + opens in the current window (regression) =====
|
" ===== Follow-link resolves + opens in the current window (regression) =====
|
||||||
" follow_link_or_create() must resolve the definition itself and `:edit` the
|
" follow_link_or_create() must resolve the definition itself and `:edit` the
|
||||||
" target in the CURRENT window — including a page that does not exist yet
|
" target in the CURRENT window — including a page that does not exist yet
|
||||||
|
|||||||
@@ -761,6 +761,18 @@ vim.defer_fn(function()
|
|||||||
error('visual colorize did not wrap selection: ' .. got)
|
error('visual colorize did not wrap selection: ' .. got)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
-- Invoking the command with a range (`:'<,'>VimwikiColorize`, as Vim builds
|
||||||
|
-- it when you select then type the command) must not error (-range) and
|
||||||
|
-- wraps the selection.
|
||||||
|
tobj_case('cmd.Colorize_range_wraps_selection', function()
|
||||||
|
set_buf({ 'pick this word' })
|
||||||
|
vim.cmd('normal! 0wviw\27') -- select 'this'
|
||||||
|
vim.cmd("'<,'>VimwikiColorize orange")
|
||||||
|
local got = vim.api.nvim_get_current_line()
|
||||||
|
if got ~= 'pick <span style="color:orange">this</span> word' then
|
||||||
|
error('ranged command did not wrap selection: ' .. got)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
-- ===== Wiki picker (config-driven, no LSP) =====
|
-- ===== Wiki picker (config-driven, no LSP) =====
|
||||||
-- The picker must build its list from config so it works from any buffer
|
-- The picker must build its list from config so it works from any buffer
|
||||||
|
|||||||
@@ -129,11 +129,17 @@ fix site.
|
|||||||
bug: `colorize()` inferred visual-vs-normal from `vim.fn.visualmode()`, which
|
bug: `colorize()` inferred visual-vs-normal from `vim.fn.visualmode()`, which
|
||||||
returns the *last* session visual mode with stale `'<`/`'>` marks — so the
|
returns the *last* session visual mode with stale `'<`/`'>` marks — so the
|
||||||
normal-mode command wrapped a leftover selection instead of the cword.
|
normal-mode command wrapped a leftover selection instead of the cword.
|
||||||
`colorize(color, visual)` now takes an explicit `visual` flag passed only by
|
`colorize(color, visual)` now takes an explicit `visual` flag; the command and
|
||||||
the `x`-mode `<Leader>wc` mapping (`lua/nuwiki/keymaps.lua`); the command and
|
normal mapping always wrap the cword. Third bug: the commands were not
|
||||||
normal mapping always wrap the cword. Covered by `cmd.VimwikiColorize_uses_arg`,
|
`-range`, so selecting text and running `:VimwikiColorize` (which Vim turns
|
||||||
`cmd.Colorize_ignores_stale_visual_selection`, and
|
into `:'<,'>VimwikiColorize`) raised `E481: No range allowed`. All four
|
||||||
`colorize.visual_wraps_selection` in `development/tests/test-keymaps.lua`.
|
command defs are now `-range` and pass the range to the handler — a ranged
|
||||||
|
(visual) invocation wraps the `'<`/`'>` selection on both clients; the
|
||||||
|
`x`-mode `<Leader>wc` mapping passes the visual flag directly. Covered by
|
||||||
|
`cmd.VimwikiColorize_uses_arg`, `cmd.Colorize_ignores_stale_visual_selection`,
|
||||||
|
`colorize.visual_wraps_selection`, `cmd.Colorize_range_wraps_selection` in
|
||||||
|
`test-keymaps.lua` and `colorize.{command_wraps_cword,visual_wraps_selection,
|
||||||
|
ranged_command_no_error}` in `test-keymaps-vim.vim`.
|
||||||
- [ ] **`VimwikiTableMoveColumn{Left,Right}` dispatch to different backing names
|
- [ ] **`VimwikiTableMoveColumn{Left,Right}` dispatch to different backing names
|
||||||
per client** — Vim branch → `table_move_left/right`; Neovim branch →
|
per client** — Vim branch → `table_move_left/right`; Neovim branch →
|
||||||
`table_move_column_left/right`. Harmless today (each name exists in its own
|
`table_move_column_left/right`. Harmless today (each name exists in its own
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ if !has('nvim')
|
|||||||
command! -buffer -nargs=1 VimwikiTable call nuwiki#commands#table_insert()
|
command! -buffer -nargs=1 VimwikiTable call nuwiki#commands#table_insert()
|
||||||
command! -buffer VimwikiTableMoveColumnLeft call nuwiki#commands#table_move_left()
|
command! -buffer VimwikiTableMoveColumnLeft call nuwiki#commands#table_move_left()
|
||||||
command! -buffer VimwikiTableMoveColumnRight call nuwiki#commands#table_move_right()
|
command! -buffer VimwikiTableMoveColumnRight call nuwiki#commands#table_move_right()
|
||||||
command! -buffer -nargs=1 VimwikiColorize call nuwiki#commands#colorize(<q-args>)
|
command! -buffer -nargs=1 -range VimwikiColorize call nuwiki#commands#colorize(<q-args>, <range>)
|
||||||
command! -buffer VimwikiPasteLink call nuwiki#commands#paste_link()
|
command! -buffer VimwikiPasteLink call nuwiki#commands#paste_link()
|
||||||
command! -buffer VimwikiPasteUrl call nuwiki#commands#paste_url()
|
command! -buffer VimwikiPasteUrl call nuwiki#commands#paste_url()
|
||||||
command! -buffer VimwikiCatUrl call nuwiki#commands#cat_url()
|
command! -buffer VimwikiCatUrl call nuwiki#commands#cat_url()
|
||||||
@@ -174,7 +174,7 @@ if !has('nvim')
|
|||||||
command! -buffer -nargs=1 NuwikiTable call nuwiki#commands#table_insert()
|
command! -buffer -nargs=1 NuwikiTable call nuwiki#commands#table_insert()
|
||||||
command! -buffer NuwikiTableMoveColumnLeft call nuwiki#commands#table_move_left()
|
command! -buffer NuwikiTableMoveColumnLeft call nuwiki#commands#table_move_left()
|
||||||
command! -buffer NuwikiTableMoveColumnRight call nuwiki#commands#table_move_right()
|
command! -buffer NuwikiTableMoveColumnRight call nuwiki#commands#table_move_right()
|
||||||
command! -buffer -nargs=1 NuwikiColorize call nuwiki#commands#colorize(<q-args>)
|
command! -buffer -nargs=1 -range NuwikiColorize call nuwiki#commands#colorize(<q-args>, <range>)
|
||||||
command! -buffer NuwikiPasteLink call nuwiki#commands#paste_link()
|
command! -buffer NuwikiPasteLink call nuwiki#commands#paste_link()
|
||||||
command! -buffer NuwikiPasteUrl call nuwiki#commands#paste_url()
|
command! -buffer NuwikiPasteUrl call nuwiki#commands#paste_url()
|
||||||
command! -buffer NuwikiCatUrl call nuwiki#commands#cat_url()
|
command! -buffer NuwikiCatUrl call nuwiki#commands#cat_url()
|
||||||
@@ -216,7 +216,7 @@ if !has('nvim')
|
|||||||
nnoremap <silent><buffer> <Leader>wd :call nuwiki#commands#delete_file()<CR>
|
nnoremap <silent><buffer> <Leader>wd :call nuwiki#commands#delete_file()<CR>
|
||||||
nnoremap <silent><buffer> <Leader>wr :call nuwiki#commands#rename_file()<CR>
|
nnoremap <silent><buffer> <Leader>wr :call nuwiki#commands#rename_file()<CR>
|
||||||
nnoremap <silent><buffer> <Leader>wc :call nuwiki#commands#colorize('')<CR>
|
nnoremap <silent><buffer> <Leader>wc :call nuwiki#commands#colorize('')<CR>
|
||||||
xnoremap <silent><buffer> <Leader>wc :<C-u>call nuwiki#commands#colorize('')<CR>
|
xnoremap <silent><buffer> <Leader>wc :<C-u>call nuwiki#commands#colorize('', 2)<CR>
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" Diary nav
|
" Diary nav
|
||||||
@@ -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 -nargs=1 VimwikiTable lua require('nuwiki.commands').table_insert()
|
||||||
command! -buffer VimwikiTableMoveColumnLeft lua require('nuwiki.commands').table_move_column_left()
|
command! -buffer VimwikiTableMoveColumnLeft lua require('nuwiki.commands').table_move_column_left()
|
||||||
command! -buffer VimwikiTableMoveColumnRight lua require('nuwiki.commands').table_move_column_right()
|
command! -buffer VimwikiTableMoveColumnRight lua require('nuwiki.commands').table_move_column_right()
|
||||||
command! -buffer -nargs=1 VimwikiColorize lua require('nuwiki.commands').colorize(<q-args>)
|
command! -buffer -nargs=1 -range VimwikiColorize lua require('nuwiki.commands').colorize(<q-args>, <range> > 0)
|
||||||
command! -buffer VimwikiPasteLink lua require('nuwiki.commands').paste_link()
|
command! -buffer VimwikiPasteLink lua require('nuwiki.commands').paste_link()
|
||||||
command! -buffer VimwikiPasteUrl lua require('nuwiki.commands').paste_url()
|
command! -buffer VimwikiPasteUrl lua require('nuwiki.commands').paste_url()
|
||||||
command! -buffer VimwikiCatUrl lua require('nuwiki.commands').cat_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 -nargs=1 NuwikiTable lua require('nuwiki.commands').table_insert()
|
||||||
command! -buffer NuwikiTableMoveColumnLeft lua require('nuwiki.commands').table_move_column_left()
|
command! -buffer NuwikiTableMoveColumnLeft lua require('nuwiki.commands').table_move_column_left()
|
||||||
command! -buffer NuwikiTableMoveColumnRight lua require('nuwiki.commands').table_move_column_right()
|
command! -buffer NuwikiTableMoveColumnRight lua require('nuwiki.commands').table_move_column_right()
|
||||||
command! -buffer -nargs=1 NuwikiColorize lua require('nuwiki.commands').colorize(<q-args>)
|
command! -buffer -nargs=1 -range NuwikiColorize lua require('nuwiki.commands').colorize(<q-args>, <range> > 0)
|
||||||
command! -buffer NuwikiPasteLink lua require('nuwiki.commands').paste_link()
|
command! -buffer NuwikiPasteLink lua require('nuwiki.commands').paste_link()
|
||||||
command! -buffer NuwikiPasteUrl lua require('nuwiki.commands').paste_url()
|
command! -buffer NuwikiPasteUrl lua require('nuwiki.commands').paste_url()
|
||||||
command! -buffer NuwikiCatUrl lua require('nuwiki.commands').cat_url()
|
command! -buffer NuwikiCatUrl lua require('nuwiki.commands').cat_url()
|
||||||
|
|||||||
@@ -951,9 +951,11 @@ end
|
|||||||
--- the template is `<span style="color:%c">%s</span>` with `%c`
|
--- the template is `<span style="color:%c">%s</span>` with `%c`
|
||||||
--- replaced by the user-supplied colour and `%s` by the wrapped text.
|
--- replaced by the user-supplied colour and `%s` by the wrapped text.
|
||||||
--- Pure-Lua; no server roundtrip needed.
|
--- Pure-Lua; no server roundtrip needed.
|
||||||
|
-- Read the last visual selection from the `'<`/`'>` marks. Only meaningful
|
||||||
|
-- when the caller knows it's acting on a selection (colorize's `visual` flag);
|
||||||
|
-- we deliberately don't gate on vim.fn.visualmode() here since that reflects
|
||||||
|
-- session state, not whether the marks are the selection we want right now.
|
||||||
local function visual_selection_range()
|
local function visual_selection_range()
|
||||||
local mode = vim.fn.visualmode()
|
|
||||||
if mode == '' then return nil end
|
|
||||||
local s = vim.api.nvim_buf_get_mark(0, '<')
|
local s = vim.api.nvim_buf_get_mark(0, '<')
|
||||||
local e = vim.api.nvim_buf_get_mark(0, '>')
|
local e = vim.api.nvim_buf_get_mark(0, '>')
|
||||||
if s[1] == 0 or e[1] == 0 then return nil end
|
if s[1] == 0 or e[1] == 0 then return nil end
|
||||||
|
|||||||
Reference in New Issue
Block a user