User reported the editor-keymaps CI job hung for 30 minutes before
"Has been cancelled" — twice in a row. Two changes to keep that from
happening again:
1. Wrap both harness invocations with `timeout` (60s Neovim, 30s
Vim). A misbehaving LSP attach, a stuck `vim.defer_fn`, or
ex-mode hung on stdin can no longer hold the runner indefinitely;
`timeout` kills the process and the wrapper exits non-zero so CI
shows the real failure shape.
2. `</dev/null` on `vim -e -s` so ex-mode doesn't sit waiting for
input on CI's non-TTY stdin (the local zsh run inherits the
user's tty, masking this).
3. CI: the keymaps job now has `needs: test` and
`timeout-minutes: 10`. `needs: test` serialises behind the cargo
jobs so we don't fight for the single Gitea runner, and the
workflow-level timeout is a belt to the script-level `timeout`'s
braces — if for some reason both fail the same way, the runner
reclaims itself in 10 minutes instead of 30.
Local timing: `test-keymaps.sh` 10.4s, `test-keymaps-vim.sh` 0.1s.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
User asked about the Vim path of the keymap suite. Building it
surfaced a real bug: 25 of our autoload functions were written as
`function! foo() abort | call bar() | endfunction` one-liners, which
isn't valid Vim syntax — `function!` requires a multi-line body, and
Vim parses the `|` after `abort` as an unexpected trailing character
(E488). Most invocations of the buggy autoload functions errored
out the moment Vim tried to parse them, which is why the user saw
broken keymaps and confusing diagnostics.
Rewrote all 25 one-liners (`autoload/nuwiki/commands.vim`) into the
standard three-line form. Affected groups: `diary_*`, `toggle_list_item`,
`cycle_list_item`, `reject_list_item`, `heading_add`, `heading_remove`,
`toc_generate`, `links_generate`, `export_current` / `_all` /
`_all_force` / `_rss`, and the §13.1 deferred stubs (`list_change_lvl`,
`list_remove_done`, `table_*`, `colorize`, `paste_link`, `paste_url`).
Added `scripts/test-keymaps-vim.{sh,vim}` — a Vim-side counterpart of
the Neovim harness covering the pure-VimL bindings (header nav,
link nav, `o`/`O` bullet continuation, `<CR>` wrap step). The
LSP-roundtrip bindings (`<C-Space>`, `=`, `-`, …) stay on the Neovim
side because vim-lsp's async layer uses timers that don't fire
inside `vim -e -s` headless mode — their server-side codepath is
already exercised by the Neovim harness and the cargo test suite.
Vim harness covers 12 cases: filetype + 2 command-presence smoke
tests, 4 header-nav (`]]`/`[[`/`]=`/`]u`), `<Tab>` link-nav, `<CR>`
wrap-on-first-press, and 3 bullet-continuation flows.
CI: extended the existing `keymaps` job to install both nvim + vim
and run both harnesses. Verified locally:
Neovim harness: 19 passed, 0 failed
Vim harness: 12 passed, 0 failed
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>