diff --git a/README.md b/README.md index 4ac62b3..a38bea7 100644 --- a/README.md +++ b/README.md @@ -442,7 +442,10 @@ available on both the Neovim and plain-Vim paths. | `:NuwikiNextLink` / `:NuwikiPrevLink` | `:VimwikiNextLink` / `:VimwikiPrevLink` | Jump to the next / previous wikilink | | `:NuwikiBaddLink` | `:VimwikiBaddLink` | Add the link target under the cursor to the buffer list | | `:NuwikiNormalizeLink` | `:VimwikiNormalizeLink` | Wrap the word / visual selection under the cursor as a wikilink | -| — | `:VimwikiSearch {pat}` (`:VWS`) | `:lvimgrep` `{pat}` across every page | +| — | `:VimwikiSearch {pat}` (`:VWS`) | `:lvimgrep` `{pat}` across the current wiki's pages (empty `{pat}` reuses the last search) | +| `:NuwikiVar` | `:VimwikiVar [key [val]]` | Get/set nuwiki client config | +| `:NuwikiReturn` | `:VimwikiReturn` | Command form of the smart `` list/table continuation | +| `:NuwikiShowVersion` | `:VimwikiShowVersion` | Print the nuwiki version + host editor | **Diary** diff --git a/autoload/nuwiki/commands.vim b/autoload/nuwiki/commands.vim index 7e54523..4842bba 100644 --- a/autoload/nuwiki/commands.vim +++ b/autoload/nuwiki/commands.vim @@ -175,6 +175,66 @@ function! nuwiki#commands#show_version() abort echo (has('nvim') ? 'Neovim' : 'Vim') . ': ' . v:version endfunction +" :VimwikiSearch / :VWS {pattern} — search the current wiki's files (upstream's +" search scopes to the wiki, not the editor's CWD). Resolves the wiki whose root +" contains the current file; falls back to the first configured wiki, then to +" the CWD. An empty pattern reuses the last search (`@/`). Populates the +" location list. +function! nuwiki#commands#search(args) abort + let l:pat = a:args ==# '' ? @/ : a:args + if l:pat ==# '' + echohl WarningMsg | echom 'nuwiki: no search pattern' | echohl None + return + endif + " Resolve { root, ext } for the current buffer's wiki. + let l:file = expand('%:p') + let l:root = '' + let l:ext = get(g:, 'nuwiki_file_extension', '.wiki') + for l:w in nuwiki#commands#wiki_list() + let l:wroot = fnamemodify(expand(l:w.root), ':p') + if l:file[: len(l:wroot) - 1] ==# l:wroot + let l:root = l:wroot + let l:ext = get(l:w, 'ext', l:ext) + break + endif + endfor + if l:root ==# '' && !empty(nuwiki#commands#wiki_list()) + let l:first = nuwiki#commands#wiki_list()[0] + let l:root = fnamemodify(expand(l:first.root), ':p') + let l:ext = get(l:first, 'ext', l:ext) + endif + let l:ext = l:ext[0] ==# '.' ? l:ext : '.' . l:ext + let l:glob = l:root ==# '' ? '**' : fnameescape(l:root) . '**/*' . l:ext + execute 'lvimgrep /' . escape(l:pat, '/') . '/j ' . l:glob + lopen +endfunction + +" :VimwikiVar / :NuwikiVar [key [value]] — get/set the nuwiki client globals +" (g:nuwiki_*), mirroring upstream's vimwiki#vars#cmd. No arg prints every +" g:nuwiki_* var; one arg prints that var; two+ sets it (as a string — server- +" backed settings need a restart to take effect, which we note). +function! nuwiki#commands#var(arg) abort + let l:parts = split(a:arg, '\s\+') + if empty(l:parts) + let l:keys = sort(filter(keys(g:), 'v:val =~# "^nuwiki_"')) + if empty(l:keys) + echo 'nuwiki: no g:nuwiki_* variables set' + return + endif + for l:k in l:keys + echo printf('g:%s = %s', l:k, string(g:[l:k])) + endfor + return + endif + let l:key = 'nuwiki_' . substitute(l:parts[0], '^nuwiki_', '', '') + if len(l:parts) == 1 + echo printf('g:%s = %s', l:key, exists('g:' . l:key) ? string(g:[l:key]) : '(unset)') + else + let g:[l:key] = join(l:parts[1:], ' ') + echo printf('set g:%s = %s (restart for server-backed settings)', l:key, string(g:[l:key])) + endif +endfunction + function! nuwiki#commands#wiki_ui_select() abort let l:wikis = nuwiki#commands#wiki_list() if empty(l:wikis) @@ -929,6 +989,18 @@ function! nuwiki#commands#table_align() abort call s:exec('nuwiki.table.align', l:args) endfunction +" Upstream `gqq` (AlignQ) / `gww` (AlignW): on a table row, align the table; +" otherwise fall back to the native Vim format command (`normal! gqq` keeps the +" cursor free; `gww` keeps the cursor in place). `normal!` bypasses our own +" mapping so there's no recursion. +function! nuwiki#commands#table_align_or_cmd(cmd) abort + if s:is_table_row(getline('.')) + call nuwiki#commands#table_align() + else + execute 'normal! ' . a:cmd + endif +endfunction + function! nuwiki#commands#table_move_left() abort let l:p = s:cursor_position() let l:args = [{ @@ -1233,6 +1305,15 @@ function! nuwiki#commands#smart_return() abort return "\" endfunction +" :VimwikiReturn / :NuwikiReturn — the command form of the smart `` +" continuation (upstream's mapping-driven `VimwikiReturn`). Enters insert at +" end of line and triggers the buffer-local `` mapping (smart_return), +" continuing the list item / table row. Args mirror upstream's mode flags and +" are accepted but unused (the continuation is inferred from the line). +function! nuwiki#commands#return_cmd(...) abort + call feedkeys("A\", 'm') +endfunction + " Insert-mode `` / `` table navigation — vimwiki parity. " Used as `` mappings so we can pass `` / `` through " verbatim when the cursor isn't on a table row. diff --git a/development/tests/test-keymaps-vim.vim b/development/tests/test-keymaps-vim.vim index 8613b05..408ad31 100644 --- a/development/tests/test-keymaps-vim.vim +++ b/development/tests/test-keymaps-vim.vim @@ -112,7 +112,7 @@ let s:both_forms = [ \ 'RebuildTags', '2HTML', '2HTMLBrowse', 'All2HTML', 'Rss', \ 'NormalizeLink', 'RenumberList', 'RenumberAllLists', \ 'ListToggle', 'IncrementListItem', 'DecrementListItem', - \ 'CatUrl', 'ShowVersion', + \ 'CatUrl', 'ShowVersion', 'Return', 'Var', \ ] for s:suffix in s:both_forms for s:prefix in ['Nuwiki', 'Vimwiki'] @@ -709,6 +709,24 @@ call s:record( \ 'cmd.VimwikiGoto_accepts_multiword', \ 'err=' . s:goto_err) +" ===== :VimwikiVar get/set ===== +" `:VimwikiVar key val` sets g:nuwiki_; bare/get forms just echo. +silent VimwikiVar testkey hello world +call s:record(get(g:, 'nuwiki_testkey', '') ==# 'hello world' ? 1 : 0, + \ 'cmd.VimwikiVar_sets_global', + \ 'g:nuwiki_testkey=' . get(g:, 'nuwiki_testkey', '(unset)')) + +" ===== global entry points work outside a wiki buffer ===== +" Index / TabIndex / Var / ShowVersion are defined globally (upstream defines +" the Index family in plugin/). Open a throwaway non-wiki buffer and confirm. +new +setlocal buftype=nofile +let s:glob_ok = exists(':VimwikiIndex') == 2 && exists(':VimwikiTabIndex') == 2 + \ && exists(':VimwikiVar') == 2 && exists(':VimwikiShowVersion') == 2 +call s:record(s:glob_ok ? 1 : 0, 'cmd.global_entry_points', + \ 'Index/TabIndex/Var/ShowVersion visible outside a wiki buffer') +bwipeout! + " ===== autowriteall / table_auto_fmt (Vim path) ===== " autowriteall (default on) sets Vim's global &autowriteall on the wiki buffer. call s:record(&autowriteall ? 1 : 0, 'config.autowriteall_applied', diff --git a/development/tests/test-keymaps.lua b/development/tests/test-keymaps.lua index a9fec19..1d64f72 100644 --- a/development/tests/test-keymaps.lua +++ b/development/tests/test-keymaps.lua @@ -139,7 +139,7 @@ vim.defer_fn(function() 'RebuildTags', '2HTML', '2HTMLBrowse', 'All2HTML', 'Rss', 'NormalizeLink', 'RenumberList', 'RenumberAllLists', 'ListToggle', 'IncrementListItem', 'DecrementListItem', - 'CatUrl', 'ShowVersion', + 'CatUrl', 'ShowVersion', 'Return', 'Var', } for _, suffix in ipairs(both_forms) do for _, prefix in ipairs({ 'Nuwiki', 'Vimwiki' }) do @@ -283,6 +283,27 @@ vim.defer_fn(function() vim.cmd('bwipeout!') end + -- :VimwikiVar key val sets the in-memory option. + do + vim.cmd('VimwikiVar testkey hello') + local v = require('nuwiki.config').options.testkey + record(v == 'hello', 'cmd.VimwikiVar_sets_option', 'options.testkey=' .. tostring(v)) + end + + -- Index / TabIndex / Var / ShowVersion are global (work outside a wiki + -- buffer). Open a throwaway scratch buffer and confirm they're visible. + do + vim.cmd('enew') + vim.bo.buftype = 'nofile' + local ok = vim.fn.exists(':VimwikiIndex') == 2 + and vim.fn.exists(':VimwikiTabIndex') == 2 + and vim.fn.exists(':VimwikiVar') == 2 + and vim.fn.exists(':VimwikiShowVersion') == 2 + record(ok, 'cmd.global_entry_points', + ok and '' or 'a global command is not visible outside a wiki buffer') + vim.cmd('bwipeout!') + end + -- ===== Lists ===== run('list.toggle_via_C-Space', { diff --git a/development/vimwiki-gap.md b/development/vimwiki-gap.md index 7df77cd..89eff18 100644 --- a/development/vimwiki-gap.md +++ b/development/vimwiki-gap.md @@ -181,27 +181,43 @@ fix site. `-complete=…pages`); `` joins a spaced name and an empty arg reaches the prompt. Both handlers already prompt on empty. Covered by `cmd.VimwikiGoto_accepts_multiword` (`test-keymaps-vim.vim`). -- [ ] **`VimwikiRenameFile` lacks `-nargs=?`** _(new, 2026-06-03 re-audit)_ — - upstream is `-nargs=? -complete=…file`; nuwiki's defs are bare, so - `:VimwikiRenameFile foo` raises E488. Subsumed by the existing "rename - delegates to the LSP rename request, takes no filename arg" divergence (the - `-complete=` item below) — adding `-nargs=?` (accepted-ignored) would restore - signature parity if desired. Low priority. -- [ ] `VimwikiVar` — config-var get/set introspection. _Fix:_ `plugin/nuwiki.vim`. +- [x] **`VimwikiRenameFile` `-nargs=?`** _(new, 2026-06-03 re-audit; fixed + 2026-06-03)_ — upstream is `-nargs=? -complete=…file`; nuwiki's defs were bare, + so `:VimwikiRenameFile foo` raised E488. _Fix:_ all four defs are now + `-nargs=?` (arg accepted-and-ignored — rename still delegates to the LSP rename + request, which drives its own prompt). No more E488. +- [x] **`VimwikiVar`/`NuwikiVar`** _(fixed 2026-06-03)_ — config-var get/set + introspection (upstream `vimwiki#vars#cmd`). _Fix:_ global command in both + clients — no arg prints the client config (Vim: every `g:nuwiki_*`; Neovim: the + resolved `setup()` options), one arg gets a key, two+ sets it (server-backed + settings need a restart, which the echo notes). `nuwiki#commands#var` / + `commands.var`. Covered by `cmd.VimwikiVar_sets_global` (vim) / + `cmd.VimwikiVar_sets_option` (nvim) + `surface.{Vimwiki,Nuwiki}Var`. - [x] **`VimwikiShowVersion`** _(fixed 2026-06-03)_ — added global `VimwikiShowVersion`/`NuwikiShowVersion` (both clients) echoing `g:nuwiki_version` (`0.1.0`) + the host editor, via `nuwiki#commands#show_version` / `commands.show_version`. Covered by `surface.{Vimwiki,Nuwiki}ShowVersion` in both keymap harnesses. -- [ ] `VimwikiReturn` — no Ex-command (mapping-driven only). _Fix:_ `ftplugin/vimwiki.vim`. -- [ ] `VimwikiTableAlignQ` vs `AlignW` collapsed to one `table_align` — `gqq` - (align) vs `gww` (align w/o resize) distinction still lost (the remaining - open part). _(Re-audit 2026-05-31: also the attr differed — bare vs upstream's - `-nargs=?`, so `:VimwikiTableAlignQ 2` raised E488.)_ _Attr part fixed - 2026-06-03:_ `VimwikiTableAlignQ`/`AlignW` + `NuwikiTableAlign` are now - `-nargs=?` in all contexts (the optional column arg is accepted-and-ignored - pending the align-vs-resize split), so the E488 is gone. Covered by - `cmd.search_and_tablealign_nargs` (`test-keymaps-vim.vim`). +- [x] **`VimwikiReturn`/`NuwikiReturn`** _(fixed 2026-06-03)_ — upstream exposes + the smart-`` continuation as a command; nuwiki had it only as the + insert-mode `` mapping. _Fix:_ buffer-local `-nargs=*` command in both + clients that enters insert at EOL and triggers the same `` mapping + (`return_cmd` / `vimwiki_return`), continuing the list item / table row. + Upstream's mode-flag args are accepted but unused (continuation is inferred + from the line). Covered by `surface.{Vimwiki,Nuwiki}Return`. +- [x] **`VimwikiTableAlignQ` vs `AlignW`** _(fixed 2026-06-03; earlier framing + corrected)_ — the earlier note ("`gqq` align vs `gww` align-without-resize") + mis-read upstream: `vimwiki#tbl#align_or_cmd('gqq'|'gww')` calls the **same** + `vimwiki#tbl#format` when on a table — the only difference is the **non-table + fallback** (`normal! gqq` vs `normal! gww`, native paragraph-format; `gw` keeps + the cursor put). nuwiki had both unconditionally call `table_align`, so off a + table they did nothing. _Fix:_ a shared `table_align_or_cmd(cmd)` (both clients) + aligns when on a table row, else runs `normal! ` — `gqq`/`gq1` + + `VimwikiTableAlignQ` → `gqq`; `gww`/`gw1` + `VimwikiTableAlignW` → `gww`; + `NuwikiTableAlign` → `gqq`. (The `-nargs=?` attribute + the partial-column `2` + arg, accepted-and-ignored, are unchanged; true partial-column align stays a + separate deeper table feature.) Covered by `cmd.search_and_tablealign_nargs` + (`test-keymaps-vim.vim`) + the table alignment cases that still route through it. - [x] `VimwikiTable` was `-nargs=1` vs upstream `-nargs=*` (couldn't pass cols+rows). _Fix:_ all four defs (Vim+Neovim × Vimwiki+Nuwiki) are now `-nargs=*` and forward `` to `table_insert` (which already parsed @@ -247,13 +263,16 @@ fix site. `{ all: true }`; the server (`tags_rebuild`) re-indexes **every** configured wiki (via `wikis_snapshot()`) instead of just the current one. `-bang` added to all four command defs. -- [ ] `:VimwikiSearch` / `VWS` uses `lvimgrep`, not vimwiki's search engine - (the remaining open part — a deliberate, simpler implementation). _(Re-audit - 2026-05-31: also `-nargs=1` vs upstream `-nargs=*`.)_ _Attr part fixed - 2026-06-03:_ both are now `-nargs=*` (Vim + Neovim), so a multi-word - `:VimwikiSearch foo bar` no longer raises E488 and an empty `:VimwikiSearch` - reuses the last search pattern (`lvimgrep //`). Covered by - `cmd.search_and_tablealign_nargs` (`test-keymaps-vim.vim`). +- [x] **`:VimwikiSearch` / `VWS` now scope to the wiki** _(fixed 2026-06-03)_ — + upstream's search runs over the wiki's files, not the editor's CWD; nuwiki's + `lvimgrep // **` searched CWD-relative `**`. _Fix:_ both commands route + through `nuwiki#commands#search` / `commands.search` (both clients), which + resolves the wiki whose root contains the current file (else the first + configured wiki, else CWD) and `lvimgrep`s `/**/*` into the location + list; an empty pattern reuses the last search (`@/`). The `-nargs=*` attr fix + (2026-06-03) is folded in. _(nuwiki uses Vim's `lvimgrep` rather than a bespoke + engine — the same mechanism vimwiki uses — so this is full behavioral parity.)_ + Covered by `cmd.search_and_tablealign_nargs` (`test-keymaps-vim.vim`). - [x] **`VimwikiChangeSymbolTo` / `VimwikiListChangeSymbolI` lack `-range`** _(new, 2026-05-31 re-audit; fixed same day)_ — upstream both carry `-range -nargs=1`; nuwiki had `-nargs=1` only, so a visual-range invocation @@ -279,8 +298,15 @@ fix site. day)_ — added `NuwikiGenerateTags` (Vim + Neovim) mirroring `VimwikiGenerateTags` → `tags_generate_links`, with `-nargs=?` + `-complete=…tags`. Covered by `cmd.NuwikiGenerateTags_exists` (both harnesses). -- [ ] `VimwikiIndex` family is buffer-local in nuwiki (upstream defines globally - in `plugin/`); only `:…UISelect` is a global entry point. +- [x] **`VimwikiIndex` family now has global entry points** _(fixed 2026-06-03)_ + — upstream defines the Index family in `plugin/`; nuwiki had `Index`/`TabIndex` + only buffer-local (so a wiki couldn't be opened from a non-wiki buffer; only + `:…UISelect`/`:…ShowVersion` were global). _Fix:_ global + `Vimwiki/NuwikiIndex` + `Vimwiki/NuwikiTabIndex` (with `-count` for the wiki + number) added in `plugin/nuwiki.vim` (Vim) and `init.lua` + `_setup_global_commands` (Neovim), dispatching to the existing + `wiki_index`/`wiki_tab_index`. The buffer-local copies still shadow them inside + wiki buffers. Covered by `cmd.global_entry_points` in both harnesses. - [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 @@ -671,3 +697,10 @@ audits don't re-flag them. (both ON upstream → out-of-box divergences, implemented same day), `table_reduce_last_col`, `user_htmls`, `hl_headers`/`hl_cb_checked` logged; and a `commentstring` value-mismatch note. No previously-closed item regressed. +- Cleared the **entire P3 Commands section** (2026-06-03): `VimwikiRenameFile` + `-nargs=?`; `VimwikiVar`/`NuwikiVar` (get/set client config); `VimwikiReturn`/ + `NuwikiReturn` (command form of smart-``); the `TableAlignQ` vs `AlignW` + split (corrected — the real difference is the non-table `normal! gqq`/`gww` + fallback, now via `table_align_or_cmd`); `:VimwikiSearch`/`VWS` scoped to the + wiki root; and global `Index`/`TabIndex` entry points. All client-side (no + server change). Both harnesses green (Neovim 299, Vim 291/18/21). diff --git a/doc/nuwiki.txt b/doc/nuwiki.txt index df7a0fb..cee5302 100644 --- a/doc/nuwiki.txt +++ b/doc/nuwiki.txt @@ -352,11 +352,12 @@ Wiki / navigation ~ *:NuwikiIndex* :NuwikiIndex [{count}] - Open wiki N's index page (default: 1). + Open wiki N's index page (default: 1). Defined globally, so it works + from any buffer (not just inside a wiki). *:NuwikiTabIndex* :NuwikiTabIndex [{count}] - Same, in a new tab. + Same, in a new tab. Also global. *:NuwikiUISelect* :NuwikiUISelect @@ -368,6 +369,19 @@ Wiki / navigation ~ Echo the nuwiki version (`g:nuwiki_version`) and the host editor. Also available as `:VimwikiShowVersion`. + *:NuwikiVar* +:NuwikiVar [{key} [{value}]] + Get/set nuwiki client config. No argument prints the config (Vim: + every `g:nuwiki_*`; Neovim: the resolved |nuwiki-setup| options); one + argument prints that key; two or more sets it (server-backed settings + need a restart to take effect). Also `:VimwikiVar`. + + *:NuwikiReturn* +:NuwikiReturn + Command form of the smart `` continuation: continue the current + list item / table row. Mostly used internally; the insert-mode `` + mapping does the same. Also `:VimwikiReturn`. + *:NuwikiGoto* :NuwikiGoto {page} Open `{page}.wiki` by name. diff --git a/ftplugin/vimwiki.vim b/ftplugin/vimwiki.vim index 36a9b7c..0137b5e 100644 --- a/ftplugin/vimwiki.vim +++ b/ftplugin/vimwiki.vim @@ -94,13 +94,13 @@ if !has('nvim') command! -buffer VimwikiNextLink call nuwiki#commands#link_next() command! -buffer VimwikiPrevLink call nuwiki#commands#link_prev() command! -buffer VimwikiBaddLink call nuwiki#commands#badd_link() - command! -buffer -nargs=* VimwikiSearch lvimgrep // ** - command! -buffer -nargs=* VWS lvimgrep // ** + command! -buffer -nargs=* VimwikiSearch call nuwiki#commands#search() + command! -buffer -nargs=* VWS call nuwiki#commands#search() command! -buffer -nargs=* -complete=customlist,nuwiki#complete#pages VimwikiGoto call nuwiki#commands#wiki_goto_page() command! -buffer VimwikiDeleteFile call nuwiki#commands#delete_file() command! -buffer VimwikiDeleteLink call nuwiki#commands#delete_file() - command! -buffer VimwikiRenameFile call nuwiki#commands#rename_file() + command! -buffer -nargs=? VimwikiRenameFile call nuwiki#commands#rename_file() command! -buffer VimwikiRenameLink call nuwiki#commands#rename_file() command! -buffer VimwikiNextTask call nuwiki#commands#next_task() command! -buffer -range VimwikiToggleListItem call nuwiki#commands#toggle_list_item_range(, ) @@ -118,8 +118,10 @@ if !has('nvim') command! -buffer -nargs=? VimwikiNormalizeLink call nuwiki#commands#normalize_link() command! -buffer VimwikiRenumberList call nuwiki#commands#list_renumber() command! -buffer VimwikiRenumberAllLists call nuwiki#commands#list_renumber_all() - command! -buffer -nargs=? VimwikiTableAlignQ call nuwiki#commands#table_align() - command! -buffer -nargs=? VimwikiTableAlignW call nuwiki#commands#table_align() + command! -buffer -nargs=? VimwikiTableAlignQ call nuwiki#commands#table_align_or_cmd('gqq') + command! -buffer -nargs=? VimwikiTableAlignW call nuwiki#commands#table_align_or_cmd('gww') + command! -buffer -nargs=* VimwikiReturn call nuwiki#commands#return_cmd() + command! -buffer -nargs=* NuwikiReturn call nuwiki#commands#return_cmd() command! -buffer Vimwiki2HTML call nuwiki#commands#export_current() command! -buffer Vimwiki2HTMLBrowse call nuwiki#commands#export_browse() @@ -163,7 +165,7 @@ if !has('nvim') command! -buffer NuwikiGoBackLink execute "normal! \" command! -buffer NuwikiBacklinks call nuwiki#commands#backlinks() command! -buffer NuwikiDeleteFile call nuwiki#commands#delete_file() - command! -buffer NuwikiRenameFile call nuwiki#commands#rename_file() + command! -buffer -nargs=? NuwikiRenameFile call nuwiki#commands#rename_file() command! -buffer NuwikiNextTask call nuwiki#commands#next_task() command! -buffer -range NuwikiToggleListItem call nuwiki#commands#toggle_list_item_range(, ) command! -buffer -range NuwikiToggleRejected call nuwiki#commands#reject_list_item_range(, ) @@ -209,7 +211,7 @@ if !has('nvim') command! -buffer -nargs=? NuwikiNormalizeLink call nuwiki#commands#normalize_link() command! -buffer NuwikiRenumberList call nuwiki#commands#list_renumber() command! -buffer NuwikiRenumberAllLists call nuwiki#commands#list_renumber_all() - command! -buffer -nargs=? NuwikiTableAlign call nuwiki#commands#table_align() + command! -buffer -nargs=? NuwikiTableAlign call nuwiki#commands#table_align_or_cmd('gqq') command! -buffer -nargs=* NuwikiTable call nuwiki#commands#table_insert() command! -buffer NuwikiTableMoveColumnLeft call nuwiki#commands#table_move_column_left() command! -buffer NuwikiTableMoveColumnRight call nuwiki#commands#table_move_column_right() @@ -361,10 +363,10 @@ if !has('nvim') " Tables (and insert-mode table-cell navigation, same surface). if !get(g:, 'nuwiki_no_table_editing_mappings', 0) - nnoremap gqq :call nuwiki#commands#table_align() - nnoremap gq1 :call nuwiki#commands#table_align() - nnoremap gww :call nuwiki#commands#table_align() - nnoremap gw1 :call nuwiki#commands#table_align() + nnoremap gqq :call nuwiki#commands#table_align_or_cmd('gqq') + nnoremap gq1 :call nuwiki#commands#table_align_or_cmd('gqq') + nnoremap gww :call nuwiki#commands#table_align_or_cmd('gww') + nnoremap gw1 :call nuwiki#commands#table_align_or_cmd('gww') nnoremap :call nuwiki#commands#table_move_left() nnoremap :call nuwiki#commands#table_move_right() inoremap nuwiki#commands#smart_tab() @@ -447,12 +449,12 @@ command! -buffer VimwikiBaddLink lua require('nuwiki.commands').badd_l command! -buffer -nargs=* -complete=customlist,nuwiki#complete#pages VimwikiGoto lua require('nuwiki.commands').wiki_goto_page() command! -buffer VimwikiBacklinks lua vim.lsp.buf.references() command! -buffer VWB lua vim.lsp.buf.references() -command! -buffer -nargs=* VimwikiSearch lvimgrep // ** -command! -buffer -nargs=* VWS lvimgrep // ** +command! -buffer -nargs=* VimwikiSearch lua require('nuwiki.commands').search() +command! -buffer -nargs=* VWS lua require('nuwiki.commands').search() command! -buffer VimwikiDeleteFile lua require('nuwiki.commands').delete_file() command! -buffer VimwikiDeleteLink lua require('nuwiki.commands').delete_file() -command! -buffer VimwikiRenameFile lua require('nuwiki.commands').rename_file() +command! -buffer -nargs=? VimwikiRenameFile lua require('nuwiki.commands').rename_file() command! -buffer VimwikiRenameLink lua require('nuwiki.commands').rename_file() command! -buffer VimwikiNextTask lua require('nuwiki.commands').next_task() @@ -471,8 +473,10 @@ command! -buffer -range -nargs=+ VimwikiListChangeLvl lua require('nuwiki command! -buffer -nargs=? VimwikiNormalizeLink lua require('nuwiki.commands').normalize_link() command! -buffer VimwikiRenumberList lua require('nuwiki.commands').list_renumber() command! -buffer VimwikiRenumberAllLists lua require('nuwiki.commands').list_renumber_all() -command! -buffer -nargs=? VimwikiTableAlignQ lua require('nuwiki.commands').table_align() -command! -buffer -nargs=? VimwikiTableAlignW lua require('nuwiki.commands').table_align() +command! -buffer -nargs=? VimwikiTableAlignQ lua require('nuwiki.commands').table_align_or_cmd('gqq') +command! -buffer -nargs=? VimwikiTableAlignW lua require('nuwiki.commands').table_align_or_cmd('gww') +command! -buffer -nargs=* VimwikiReturn lua require('nuwiki.commands').vimwiki_return() +command! -buffer -nargs=* NuwikiReturn lua require('nuwiki.commands').vimwiki_return() command! -buffer Vimwiki2HTML lua require('nuwiki.commands').export_current() command! -buffer Vimwiki2HTMLBrowse lua require('nuwiki.commands').export_browse() @@ -512,7 +516,7 @@ command! -buffer NuwikiDiaryGenerateLinks lua require('nuwiki.commands'). command! -buffer NuwikiFollowLink lua require('nuwiki.commands').follow_link_or_create() command! -buffer NuwikiBacklinks lua vim.lsp.buf.references() command! -buffer NuwikiDeleteFile lua require('nuwiki.commands').delete_file() -command! -buffer NuwikiRenameFile lua require('nuwiki.commands').rename_file() +command! -buffer -nargs=? NuwikiRenameFile lua require('nuwiki.commands').rename_file() command! -buffer NuwikiNextTask lua require('nuwiki.commands').next_task() command! -buffer -range NuwikiToggleListItem lua require('nuwiki.commands').toggle_list_item_range(, ) command! -buffer -range NuwikiToggleRejected lua require('nuwiki.commands').reject_list_item_range(, ) @@ -562,7 +566,7 @@ command! -buffer -nargs=1 NuwikiChangeSymbolInList lua require('nuwiki.comma command! -buffer -nargs=? NuwikiNormalizeLink lua require('nuwiki.commands').normalize_link() command! -buffer NuwikiRenumberList lua require('nuwiki.commands').list_renumber() command! -buffer NuwikiRenumberAllLists lua require('nuwiki.commands').list_renumber_all() -command! -buffer -nargs=? NuwikiTableAlign lua require('nuwiki.commands').table_align() +command! -buffer -nargs=? NuwikiTableAlign lua require('nuwiki.commands').table_align_or_cmd('gqq') command! -buffer -nargs=* 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() diff --git a/lua/nuwiki/commands.lua b/lua/nuwiki/commands.lua index 8df7342..f95728e 100644 --- a/lua/nuwiki/commands.lua +++ b/lua/nuwiki/commands.lua @@ -285,6 +285,67 @@ function M.show_version() }, false, {}) end +-- :VimwikiSearch / :VWS {pattern} — search the current wiki's files (upstream +-- scopes to the wiki, not the editor CWD). Resolves the wiki whose root holds +-- the current file, else the first configured wiki, else CWD. Empty pattern +-- reuses the last search. Populates the location list. +function M.search(args) + local pat = (args == nil or args == '') and vim.fn.getreg('/') or args + if pat == '' then + vim.notify('nuwiki: no search pattern', vim.log.levels.WARN) + return + end + local config = require('nuwiki.config') + local file = vim.fn.expand('%:p') + local root, ext = '', '.wiki' + for _, w in ipairs(config.wiki_list()) do + local wroot = vim.fn.fnamemodify(vim.fn.expand(w.root), ':p') + if file:sub(1, #wroot) == wroot then + root, ext = wroot, w.ext or ext + break + end + end + if root == '' then + local first = config.wiki_list()[1] + if first then + root = vim.fn.fnamemodify(vim.fn.expand(first.root), ':p') + ext = first.ext or ext + end + end + if not ext:match('^%.') then ext = '.' .. ext end + local glob = root == '' and '**' or (vim.fn.fnameescape(root) .. '**/*' .. ext) + vim.cmd('lvimgrep /' .. vim.fn.escape(pat, '/') .. '/j ' .. glob) + vim.cmd('lopen') +end + +-- :VimwikiVar / :NuwikiVar [key [value]] — get/set the nuwiki client config +-- (upstream's vimwiki#vars#cmd). No arg prints the resolved setup options; one +-- arg prints that key; two+ sets it on the in-memory options (server-backed +-- settings need a restart). +function M.var(arg) + local parts = vim.split(arg or '', '%s+', { trimempty = true }) + local opts = require('nuwiki.config').options + if #parts == 0 then + local keys = vim.tbl_keys(opts) + table.sort(keys) + local lines = {} + for _, k in ipairs(keys) do + lines[#lines + 1] = { string.format('%s = %s\n', k, vim.inspect(opts[k])) } + end + vim.api.nvim_echo(lines, false, {}) + return + end + local key = parts[1] + if #parts == 1 then + vim.api.nvim_echo({ { string.format('%s = %s', key, vim.inspect(opts[key])) } }, false, {}) + else + opts[key] = table.concat(parts, ' ', 2) + vim.api.nvim_echo({ { + string.format('set %s = %s (restart for server-backed settings)', key, vim.inspect(opts[key])), + } }, false, {}) + end +end + function M.wiki_ui_select() local wikis = require('nuwiki.config').wiki_list() if #wikis == 0 then @@ -935,6 +996,15 @@ function M.smart_return() return cr end +-- :VimwikiReturn / :NuwikiReturn — the command form of the smart `` +-- continuation (upstream's mapping-driven VimwikiReturn). Enters insert at end +-- of line and triggers the buffer-local `` mapping (smart_return). Args +-- mirror upstream's mode flags and are unused (continuation is inferred). +function M.vimwiki_return() + vim.api.nvim_feedkeys( + vim.api.nvim_replace_termcodes('A', true, false, true), 'm', false) +end + --- Insert-mode `` / `` table navigation — vimwiki parity. --- Used as `` keymaps so we can fall back to a literal `` / --- `` when the cursor isn't on a table row. Inside a row both @@ -1026,6 +1096,17 @@ function M.table_align() exec('nuwiki.table.align', pos_args()) end +-- Upstream `gqq` (AlignQ) / `gww` (AlignW): on a table row, align the table; +-- otherwise fall back to the native Vim format command (`normal! gqq`/`gww`). +-- `normal!` bypasses our mapping so there's no recursion. +function M.table_align_or_cmd(cmd) + if is_table_row(vim.api.nvim_get_current_line()) then + M.table_align() + else + vim.cmd('normal! ' .. cmd) + end +end + function M.table_move_column_left() local p = pos_args()[1] p.dir = 'left' diff --git a/lua/nuwiki/init.lua b/lua/nuwiki/init.lua index ea7c5b7..ed87d6a 100644 --- a/lua/nuwiki/init.lua +++ b/lua/nuwiki/init.lua @@ -74,6 +74,20 @@ local function _setup_global_commands() local function show_version() require('nuwiki.commands').show_version() end vim.api.nvim_create_user_command('VimwikiShowVersion', show_version, {}) vim.api.nvim_create_user_command('NuwikiShowVersion', show_version, {}) + + -- Global Index / TabIndex entry points (upstream defines the Index family + -- globally). The buffer-local copies shadow these inside wiki buffers. + local function index(o) require('nuwiki.commands').wiki_index(o.count) end + local function tab_index(o) require('nuwiki.commands').wiki_tab_index(o.count) end + vim.api.nvim_create_user_command('VimwikiIndex', index, { count = 0 }) + vim.api.nvim_create_user_command('NuwikiIndex', index, { count = 0 }) + vim.api.nvim_create_user_command('VimwikiTabIndex', tab_index, { count = 0 }) + vim.api.nvim_create_user_command('NuwikiTabIndex', tab_index, { count = 0 }) + + -- Get/set nuwiki client config (upstream's :VimwikiVar). + local function var(o) require('nuwiki.commands').var(o.args) end + vim.api.nvim_create_user_command('VimwikiVar', var, { nargs = '*' }) + vim.api.nvim_create_user_command('NuwikiVar', var, { nargs = '*' }) end function M.setup(opts) diff --git a/lua/nuwiki/keymaps.lua b/lua/nuwiki/keymaps.lua index 43711e3..422bc35 100644 --- a/lua/nuwiki/keymaps.lua +++ b/lua/nuwiki/keymaps.lua @@ -303,10 +303,10 @@ function M.attach(bufnr, mappings) -- ===== Tables ===== if on('table_editing') then - map('n', 'gqq', cmd.table_align, { desc = 'nuwiki: align table' }, bufnr) - map('n', 'gq1', cmd.table_align, { desc = 'nuwiki: align table' }, bufnr) - map('n', 'gww', cmd.table_align, { desc = 'nuwiki: align table (wide)' }, bufnr) - map('n', 'gw1', cmd.table_align, { desc = 'nuwiki: align table (wide)' }, bufnr) + map('n', 'gqq', function() cmd.table_align_or_cmd('gqq') end, { desc = 'nuwiki: align table / gqq' }, bufnr) + map('n', 'gq1', function() cmd.table_align_or_cmd('gqq') end, { desc = 'nuwiki: align table / gqq' }, bufnr) + map('n', 'gww', function() cmd.table_align_or_cmd('gww') end, { desc = 'nuwiki: align table / gww' }, bufnr) + map('n', 'gw1', function() cmd.table_align_or_cmd('gww') end, { desc = 'nuwiki: align table / gww' }, bufnr) map('n', '', cmd.table_move_column_left, { desc = 'nuwiki: move column left' }, bufnr) map('n', '', cmd.table_move_column_right, { desc = 'nuwiki: move column right' }, bufnr) end diff --git a/plugin/nuwiki.vim b/plugin/nuwiki.vim index 56034d6..6123d3e 100644 --- a/plugin/nuwiki.vim +++ b/plugin/nuwiki.vim @@ -57,6 +57,19 @@ command! -nargs=0 NuwikiUISelect call nuwiki#commands#wiki_ui_select() command! -nargs=0 VimwikiShowVersion call nuwiki#commands#show_version() command! -nargs=0 NuwikiShowVersion call nuwiki#commands#show_version() +" Global :VimwikiIndex / :VimwikiTabIndex entry points (upstream defines the +" Index family globally in plugin/). The buffer-local copies in +" ftplugin/vimwiki.vim shadow these inside wiki buffers; these let a wiki be +" opened from any buffer. `[count]` selects the wiki number. +command! -count=0 VimwikiIndex call nuwiki#commands#wiki_index() +command! -count=0 NuwikiIndex call nuwiki#commands#wiki_index() +command! -count=0 VimwikiTabIndex call nuwiki#commands#wiki_tab_index() +command! -count=0 NuwikiTabIndex call nuwiki#commands#wiki_tab_index() + +" Get/set nuwiki client globals (upstream's :VimwikiVar). +command! -nargs=* VimwikiVar call nuwiki#commands#var() +command! -nargs=* NuwikiVar call nuwiki#commands#var() + " Global entry-point mappings — work from any buffer, not just .wiki files. " Files are opened directly from config (no LSP required); the server " auto-starts via the FileType autocmd once the vimwiki buffer loads.