test(calendar): add Vim + Neovim integration harnesses
Add headless harnesses covering the calendar-vim integration, wired into CI alongside the existing keymap/config suites: - test-calendar-vim.sh/.vim (+ -optout.vim): pure-VimL diary hooks (calendar_sign markers, calendar_action path resolution from wiki root, calendar window close), plugin/nuwiki.vim hook auto-wiring that overrides calendar-vim's defaults, and opt-out via g:nuwiki_use_calendar and g:nuwiki_no_calendar. Uses a stub calendar-vim on the runtimepath. - test-calendar.sh/.lua: Neovim setup() wiring + window-close under the real window API, and opt-out via use_calendar = false. Fixes surfaced by the suite: - diary.vim: new diary entries set filetype 'vimwiki' (was the raw extension, e.g. 'wiki'); the stray FileType autocmd also blocked the calendar window from closing. - init.lua: drop the redundant Neovim FileType autocmd (plugin/nuwiki.vim already wires both editors) and translate use_calendar=false into g:nuwiki_no_calendar so the opt-out actually disables wiring.
This commit is contained in:
@@ -100,3 +100,7 @@ jobs:
|
|||||||
run: ./development/tests/test-config.sh
|
run: ./development/tests/test-config.sh
|
||||||
- name: run Vim config parity harness
|
- name: run Vim config parity harness
|
||||||
run: ./development/tests/test-config-vim.sh
|
run: ./development/tests/test-config-vim.sh
|
||||||
|
- name: run Neovim calendar integration harness
|
||||||
|
run: ./development/tests/test-calendar.sh
|
||||||
|
- name: run Vim calendar integration harness
|
||||||
|
run: ./development/tests/test-calendar-vim.sh
|
||||||
|
|||||||
@@ -34,12 +34,10 @@ function! nuwiki#diary#calendar_action(day, month, year, week, dir) abort
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
execute 'edit ' . fnameescape(l:file_path)
|
execute 'edit ' . fnameescape(l:file_path)
|
||||||
if !filereadable(l:file_path)
|
" A brand-new entry has no file on disk yet, so ftdetect may not have run;
|
||||||
if l:c.ext[0] ==# '.'
|
" ensure the vimwiki filetype so syntax/maps are active immediately.
|
||||||
execute 'setfiletype ' . l:c.ext[1:]
|
if &filetype !=# 'vimwiki'
|
||||||
else
|
setfiletype vimwiki
|
||||||
execute 'setfiletype ' . l:c.ext
|
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" Close the calendar window now that the diary is open (keep at least one).
|
" Close the calendar window now that the diary is open (keep at least one).
|
||||||
|
|||||||
@@ -79,7 +79,12 @@ nuwiki/
|
|||||||
│ ├── test-keymaps.sh # Neovim keymap harness
|
│ ├── test-keymaps.sh # Neovim keymap harness
|
||||||
│ ├── test-keymaps.lua
|
│ ├── test-keymaps.lua
|
||||||
│ ├── test-keymaps-vim.sh # Vim keymap harness
|
│ ├── test-keymaps-vim.sh # Vim keymap harness
|
||||||
│ └── test-keymaps-vim.vim
|
│ ├── test-keymaps-vim.vim
|
||||||
|
│ ├── test-calendar.sh # Neovim calendar-vim integration harness
|
||||||
|
│ ├── test-calendar.lua
|
||||||
|
│ ├── test-calendar-vim.sh # Vim calendar-vim integration harness
|
||||||
|
│ ├── test-calendar-vim.vim
|
||||||
|
│ └── test-calendar-vim-optout.vim
|
||||||
│
|
│
|
||||||
└── .gitea/
|
└── .gitea/
|
||||||
└── workflows/
|
└── workflows/
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
" development/tests/test-calendar-vim-optout.vim — driven by test-calendar-vim.sh.
|
||||||
|
"
|
||||||
|
" Asserts that the calendar-vim integration stays OFF when the user opts out
|
||||||
|
" (g:nuwiki_use_calendar = 0 or g:nuwiki_no_calendar = 1). In that case the
|
||||||
|
" FileType autocmd must leave calendar-vim's own defaults untouched, so the
|
||||||
|
" hooks still point at 'calendar#diary' / 'calendar#sign' (set by the stub).
|
||||||
|
|
||||||
|
let s:results = []
|
||||||
|
let s:pass = 0
|
||||||
|
let s:fail = 0
|
||||||
|
let s:out = $NUWIKI_CALENDAR_RESULTS
|
||||||
|
|
||||||
|
function! s:record(ok, name, detail) abort
|
||||||
|
let l:line = (a:ok ? 'PASS' : 'FAIL') . ' ' . a:name
|
||||||
|
if a:detail !=# ''
|
||||||
|
let l:line .= ' — ' . a:detail
|
||||||
|
endif
|
||||||
|
call add(s:results, l:line)
|
||||||
|
if a:ok
|
||||||
|
let s:pass += 1
|
||||||
|
else
|
||||||
|
let s:fail += 1
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" The buffer is already a loaded vimwiki file (FileType has fired). nuwiki must
|
||||||
|
" NOT have rewired the hooks — they should still be calendar-vim's defaults.
|
||||||
|
call s:record(&filetype ==# 'vimwiki', 'ftplugin.attached',
|
||||||
|
\ &filetype ==# 'vimwiki' ? '' : 'filetype=' . &filetype)
|
||||||
|
call s:record(get(g:, 'calendar_action', '') !=# 'vimwiki#diary#calendar_action',
|
||||||
|
\ 'optout.action_not_wired',
|
||||||
|
\ 'g:calendar_action=' . get(g:, 'calendar_action', ''))
|
||||||
|
call s:record(get(g:, 'calendar_sign', '') !=# 'vimwiki#diary#calendar_sign',
|
||||||
|
\ 'optout.sign_not_wired',
|
||||||
|
\ 'g:calendar_sign=' . get(g:, 'calendar_sign', ''))
|
||||||
|
|
||||||
|
call add(s:results, '')
|
||||||
|
call add(s:results, printf('SUMMARY: %d passed, %d failed', s:pass, s:fail))
|
||||||
|
call writefile(s:results, s:out)
|
||||||
|
execute (s:fail == 0 ? 'qall!' : 'cquit!')
|
||||||
Executable
+121
@@ -0,0 +1,121 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# development/tests/test-calendar-vim.sh — calendar-vim integration harness (Vim).
|
||||||
|
#
|
||||||
|
# Exercises the pure-VimL diary hooks (nuwiki#diary#calendar_action /
|
||||||
|
# nuwiki#diary#calendar_sign) plus plugin/nuwiki.vim's auto-wiring of
|
||||||
|
# g:calendar_action / g:calendar_sign. A stub calendar-vim is placed on the
|
||||||
|
# runtimepath so :Calendar exists and the hooks start at calendar-vim's own
|
||||||
|
# defaults — the exact state nuwiki must detect and override.
|
||||||
|
#
|
||||||
|
# Two runs:
|
||||||
|
# 1. default → integration ON, hooks rewired, diary paths from wiki root
|
||||||
|
# 2. opt-out → g:nuwiki_use_calendar=0 / g:nuwiki_no_calendar=1 leave
|
||||||
|
# calendar-vim's defaults untouched
|
||||||
|
#
|
||||||
|
# No LSP binary is needed — the diary hooks are entirely client-side VimL.
|
||||||
|
# Exit code: 0 when all assertions pass, 1 otherwise. Skips (0) without vim.
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||||
|
TMP="$(mktemp -d -t nuwiki-calendar-vim-test-XXXXXX)"
|
||||||
|
trap 'rm -rf "$TMP"' EXIT
|
||||||
|
|
||||||
|
log() { printf '\033[1;34m[calendar-vim]\033[0m %s\n' "$*"; }
|
||||||
|
|
||||||
|
if ! command -v vim >/dev/null 2>&1; then
|
||||||
|
log 'vim not installed — skipping'
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- Scratch wiki with one seeded diary entry (2026-05-30) ----------------
|
||||||
|
WIKI="$TMP/wiki"
|
||||||
|
mkdir -p "$WIKI/diary"
|
||||||
|
echo "= index =" > "$WIKI/index.wiki"
|
||||||
|
echo "= 2026-05-30 =" > "$WIKI/diary/2026-05-30.wiki"
|
||||||
|
|
||||||
|
# --- Stub calendar-vim ----------------------------------------------------
|
||||||
|
# Mimics the real plugin closely enough for detection + the override path:
|
||||||
|
# defines :Calendar and seeds calendar-vim's default hook names.
|
||||||
|
CAL="$TMP/calendar-vim"
|
||||||
|
mkdir -p "$CAL/plugin" "$CAL/autoload"
|
||||||
|
cat > "$CAL/plugin/calendar.vim" <<'EOF'
|
||||||
|
if exists('g:loaded_calendar_stub') | finish | endif
|
||||||
|
let g:loaded_calendar_stub = 1
|
||||||
|
let g:calendar_action = get(g:, 'calendar_action', 'calendar#diary')
|
||||||
|
let g:calendar_sign = get(g:, 'calendar_sign', 'calendar#sign')
|
||||||
|
command! -nargs=* Calendar echo 'stub calendar'
|
||||||
|
EOF
|
||||||
|
cat > "$CAL/autoload/calendar.vim" <<'EOF'
|
||||||
|
function! calendar#open(...) abort
|
||||||
|
endfunction
|
||||||
|
function! calendar#diary(...) abort
|
||||||
|
endfunction
|
||||||
|
function! calendar#sign(...) abort
|
||||||
|
return 0
|
||||||
|
endfunction
|
||||||
|
EOF
|
||||||
|
|
||||||
|
run_harness() {
|
||||||
|
local label="$1" vimrc="$2" harness="$3"
|
||||||
|
local results="$TMP/results-$label.txt"
|
||||||
|
log "running $label harness…"
|
||||||
|
NUWIKI_CALENDAR_RESULTS="$results" \
|
||||||
|
NUWIKI_CALENDAR_WIKI="$WIKI" \
|
||||||
|
timeout 30 vim -e -s -u "$vimrc" -c "edit $WIKI/index.wiki" \
|
||||||
|
-c "source $harness" </dev/null >"$TMP/$label.log" 2>&1 || true
|
||||||
|
if [[ ! -f "$results" ]]; then
|
||||||
|
echo "calendar $label harness produced no output" >&2
|
||||||
|
echo "--- vim log ---" >&2
|
||||||
|
cat "$TMP/$label.log" >&2 || true
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
cat "$results"
|
||||||
|
grep -qE '^SUMMARY: [0-9]+ passed, 0 failed' "$results"
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Run 1: default (integration ON) --------------------------------------
|
||||||
|
VIMRC="$TMP/vimrc"
|
||||||
|
cat > "$VIMRC" <<EOF
|
||||||
|
set nocompatible
|
||||||
|
let &runtimepath = '$REPO_ROOT' . ',' . &runtimepath
|
||||||
|
let &runtimepath .= ',$CAL'
|
||||||
|
let g:nuwiki_wiki_root = '$WIKI'
|
||||||
|
let g:nuwiki_file_extension = '.wiki'
|
||||||
|
let g:nuwiki_diary_rel_path = 'diary'
|
||||||
|
set hidden
|
||||||
|
filetype plugin indent on
|
||||||
|
syntax enable
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# --- Run 2: opt-out via g:nuwiki_use_calendar = 0 -------------------------
|
||||||
|
VIMRC_OPTOUT="$TMP/vimrc-optout"
|
||||||
|
cat > "$VIMRC_OPTOUT" <<EOF
|
||||||
|
set nocompatible
|
||||||
|
let &runtimepath = '$REPO_ROOT' . ',' . &runtimepath
|
||||||
|
let &runtimepath .= ',$CAL'
|
||||||
|
let g:nuwiki_use_calendar = 0
|
||||||
|
let g:nuwiki_wiki_root = '$WIKI'
|
||||||
|
filetype plugin indent on
|
||||||
|
syntax enable
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# --- Run 3: opt-out via g:nuwiki_no_calendar = 1 --------------------------
|
||||||
|
VIMRC_NOCAL="$TMP/vimrc-nocal"
|
||||||
|
cat > "$VIMRC_NOCAL" <<EOF
|
||||||
|
set nocompatible
|
||||||
|
let &runtimepath = '$REPO_ROOT' . ',' . &runtimepath
|
||||||
|
let &runtimepath .= ',$CAL'
|
||||||
|
let g:nuwiki_no_calendar = 1
|
||||||
|
let g:nuwiki_wiki_root = '$WIKI'
|
||||||
|
filetype plugin indent on
|
||||||
|
syntax enable
|
||||||
|
EOF
|
||||||
|
|
||||||
|
rc=0
|
||||||
|
run_harness 'default' "$VIMRC" "$REPO_ROOT/development/tests/test-calendar-vim.vim" || rc=1
|
||||||
|
run_harness 'optout-use' "$VIMRC_OPTOUT" "$REPO_ROOT/development/tests/test-calendar-vim-optout.vim" || rc=1
|
||||||
|
run_harness 'optout-no' "$VIMRC_NOCAL" "$REPO_ROOT/development/tests/test-calendar-vim-optout.vim" || rc=1
|
||||||
|
|
||||||
|
exit $rc
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
" development/tests/test-calendar-vim.vim — driven by development/tests/test-calendar-vim.sh.
|
||||||
|
"
|
||||||
|
" Pure-VimL regression suite for the calendar-vim integration. The diary
|
||||||
|
" hooks (nuwiki#diary#calendar_action / nuwiki#diary#calendar_sign) are
|
||||||
|
" implemented entirely in VimL and shared verbatim by the Vim and Neovim
|
||||||
|
" clients, so this harness is the canonical coverage for them. The Vim
|
||||||
|
" plugin-side hook wiring (plugin/nuwiki.vim's FileType autocmd) is also
|
||||||
|
" asserted here; the Neovim setup() wiring has its own harness in
|
||||||
|
" development/tests/test-calendar.lua.
|
||||||
|
"
|
||||||
|
" A stub calendar-vim is placed on the runtimepath by the shell wrapper so
|
||||||
|
" :Calendar exists and g:calendar_action/g:calendar_sign already hold
|
||||||
|
" calendar-vim's own defaults ('calendar#diary'/'calendar#sign') — exactly
|
||||||
|
" the state nuwiki must detect and override.
|
||||||
|
|
||||||
|
let s:results = []
|
||||||
|
let s:pass = 0
|
||||||
|
let s:fail = 0
|
||||||
|
let s:out = $NUWIKI_CALENDAR_RESULTS
|
||||||
|
|
||||||
|
function! s:record(ok, name, detail) abort
|
||||||
|
let l:line = (a:ok ? 'PASS' : 'FAIL') . ' ' . a:name
|
||||||
|
if a:detail !=# ''
|
||||||
|
let l:line .= ' — ' . a:detail
|
||||||
|
endif
|
||||||
|
call add(s:results, l:line)
|
||||||
|
if a:ok
|
||||||
|
let s:pass += 1
|
||||||
|
else
|
||||||
|
let s:fail += 1
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
let s:wiki_root = $NUWIKI_CALENDAR_WIKI
|
||||||
|
|
||||||
|
" ===== Hook wiring: nuwiki overrides calendar-vim's defaults =====
|
||||||
|
" The stub set g:calendar_action='calendar#diary' / g:calendar_sign='calendar#sign'
|
||||||
|
" at load. Opening this .wiki buffer fired plugin/nuwiki.vim's FileType autocmd,
|
||||||
|
" which must have rewired both to the nuwiki delegators.
|
||||||
|
|
||||||
|
call s:record(&filetype ==# 'vimwiki', 'ftplugin.attached',
|
||||||
|
\ &filetype ==# 'vimwiki' ? '' : 'filetype=' . &filetype)
|
||||||
|
call s:record(get(g:, 'calendar_action', '') ==# 'vimwiki#diary#calendar_action',
|
||||||
|
\ 'hook.action_wired', 'g:calendar_action=' . get(g:, 'calendar_action', ''))
|
||||||
|
call s:record(get(g:, 'calendar_sign', '') ==# 'vimwiki#diary#calendar_sign',
|
||||||
|
\ 'hook.sign_wired', 'g:calendar_sign=' . get(g:, 'calendar_sign', ''))
|
||||||
|
|
||||||
|
" ===== calendar_sign: marker reflects diary-file existence =====
|
||||||
|
" The shell seeded a diary entry for 2026-05-30 and left 2026-05-31 absent.
|
||||||
|
|
||||||
|
call s:record(nuwiki#diary#calendar_sign(30, 5, 2026) ==# '*',
|
||||||
|
\ 'sign.existing_date_marked',
|
||||||
|
\ 'got ' . string(nuwiki#diary#calendar_sign(30, 5, 2026)))
|
||||||
|
call s:record(nuwiki#diary#calendar_sign(31, 5, 2026) ==# '',
|
||||||
|
\ 'sign.absent_date_unmarked',
|
||||||
|
\ 'got ' . string(nuwiki#diary#calendar_sign(31, 5, 2026)))
|
||||||
|
" The vimwiki# alias must return the identical result.
|
||||||
|
call s:record(vimwiki#diary#calendar_sign(30, 5, 2026) ==# '*',
|
||||||
|
\ 'sign.alias_matches', '')
|
||||||
|
|
||||||
|
" ===== calendar_action: opens WIKI_ROOT/diary/<date>.wiki, not ~/diary =====
|
||||||
|
" Set up two windows so the "previous window" branch runs and we can assert
|
||||||
|
" the calendar window is closed afterwards.
|
||||||
|
|
||||||
|
" Window A: the seed wiki (already current). Open a fresh window to stand in
|
||||||
|
" for the calendar, then invoke the action from it.
|
||||||
|
new
|
||||||
|
file [stub-calendar]
|
||||||
|
let s:cal_winid = win_getid()
|
||||||
|
let s:wins_before = winnr('$')
|
||||||
|
call nuwiki#diary#calendar_action(31, 5, 2026, 0, '')
|
||||||
|
|
||||||
|
let s:opened = expand('%:p')
|
||||||
|
let s:want = s:wiki_root . '/diary/2026-05-31.wiki'
|
||||||
|
call s:record(s:opened ==# s:want, 'action.opens_wiki_diary_path',
|
||||||
|
\ 'opened=' . s:opened)
|
||||||
|
call s:record(s:opened !~# '/diary/2026-05-31.wiki$' ? 0 : 1,
|
||||||
|
\ 'action.path_has_date_filename', 'opened=' . s:opened)
|
||||||
|
call s:record(s:opened !~# expand('~') . '/diary',
|
||||||
|
\ 'action.not_home_diary', 'opened=' . s:opened)
|
||||||
|
|
||||||
|
" The calendar window must be closed once the diary is open.
|
||||||
|
call s:record(win_id2win(s:cal_winid) == 0, 'action.closes_calendar_window',
|
||||||
|
\ 'cal still at win ' . win_id2win(s:cal_winid))
|
||||||
|
call s:record(winnr('$') == s:wins_before - 1, 'action.window_count_decremented',
|
||||||
|
\ 'before=' . s:wins_before . ' after=' . winnr('$'))
|
||||||
|
|
||||||
|
" ===== calendar_action sets the wiki filetype on a new entry =====
|
||||||
|
call s:record(&filetype ==# 'vimwiki', 'action.sets_filetype',
|
||||||
|
\ 'filetype=' . &filetype)
|
||||||
|
|
||||||
|
" ===== Wrap up =====
|
||||||
|
|
||||||
|
call add(s:results, '')
|
||||||
|
call add(s:results, printf('SUMMARY: %d passed, %d failed', s:pass, s:fail))
|
||||||
|
call writefile(s:results, s:out)
|
||||||
|
execute (s:fail == 0 ? 'qall!' : 'cquit!')
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
-- development/tests/test-calendar.lua — driven by development/tests/test-calendar.sh.
|
||||||
|
--
|
||||||
|
-- Headless Neovim harness for the calendar-vim integration wired through
|
||||||
|
-- `require('nuwiki').setup()`. The diary hooks themselves are pure VimL and
|
||||||
|
-- covered exhaustively by development/tests/test-calendar-vim.vim; this
|
||||||
|
-- harness focuses on the Neovim-only pieces:
|
||||||
|
-- * setup() registering the FileType autocmd that overrides calendar-vim's
|
||||||
|
-- own default hooks ('calendar#diary' / 'calendar#sign'),
|
||||||
|
-- * the window-close behaviour of calendar_action under the real (non-ex)
|
||||||
|
-- window API,
|
||||||
|
-- * disabling via use_calendar = false.
|
||||||
|
--
|
||||||
|
-- The opt-out case runs in a second nvim invocation (see the shell wrapper)
|
||||||
|
-- because setup() registers the autocmd once per process.
|
||||||
|
--
|
||||||
|
-- Results are written to $NUWIKI_CALENDAR_RESULTS so the wrapper can render
|
||||||
|
-- them without scraping nvim's output.
|
||||||
|
|
||||||
|
local OUT = vim.env.NUWIKI_CALENDAR_RESULTS or '/tmp/nuwiki-calendar-results.txt'
|
||||||
|
local WIKI = vim.env.NUWIKI_CALENDAR_WIKI
|
||||||
|
local MODE = vim.env.NUWIKI_CALENDAR_MODE or 'default'
|
||||||
|
local out_lines = {}
|
||||||
|
local pass, fail = 0, 0
|
||||||
|
|
||||||
|
local function record(ok, name, detail)
|
||||||
|
local suffix = (detail and detail ~= '') and (' — ' .. detail) or ''
|
||||||
|
table.insert(out_lines, (ok and 'PASS' or 'FAIL') .. ' ' .. name .. suffix)
|
||||||
|
if ok then pass = pass + 1 else fail = fail + 1 end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function finish()
|
||||||
|
table.insert(out_lines, '')
|
||||||
|
table.insert(out_lines, string.format('SUMMARY: %d passed, %d failed', pass, fail))
|
||||||
|
vim.fn.writefile(out_lines, OUT)
|
||||||
|
vim.cmd(fail == 0 and 'qall!' or 'cquit!')
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Open the seeded wiki index so the FileType vimwiki autocmd fires.
|
||||||
|
vim.cmd('edit ' .. vim.fn.fnameescape(WIKI .. '/index.wiki'))
|
||||||
|
|
||||||
|
if MODE == 'optout' then
|
||||||
|
-- use_calendar = false: setup() must not register the wiring autocmd, so
|
||||||
|
-- calendar-vim's own defaults (set by the stub) survive untouched.
|
||||||
|
record(vim.bo.filetype == 'vimwiki', 'optout.ftplugin_attached',
|
||||||
|
'filetype=' .. vim.bo.filetype)
|
||||||
|
record(vim.g.calendar_action ~= 'vimwiki#diary#calendar_action',
|
||||||
|
'optout.action_not_wired', 'g:calendar_action=' .. tostring(vim.g.calendar_action))
|
||||||
|
record(vim.g.calendar_sign ~= 'vimwiki#diary#calendar_sign',
|
||||||
|
'optout.sign_not_wired', 'g:calendar_sign=' .. tostring(vim.g.calendar_sign))
|
||||||
|
finish()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ===== Hook wiring overrides calendar-vim defaults =====
|
||||||
|
record(vim.bo.filetype == 'vimwiki', 'ftplugin_attached',
|
||||||
|
'filetype=' .. vim.bo.filetype)
|
||||||
|
record(vim.g.calendar_action == 'vimwiki#diary#calendar_action',
|
||||||
|
'hook.action_wired', 'g:calendar_action=' .. tostring(vim.g.calendar_action))
|
||||||
|
record(vim.g.calendar_sign == 'vimwiki#diary#calendar_sign',
|
||||||
|
'hook.sign_wired', 'g:calendar_sign=' .. tostring(vim.g.calendar_sign))
|
||||||
|
|
||||||
|
-- ===== calendar_sign reflects diary-file existence =====
|
||||||
|
record(vim.fn['nuwiki#diary#calendar_sign'](30, 5, 2026) == '*',
|
||||||
|
'sign.existing_date_marked',
|
||||||
|
'got ' .. tostring(vim.fn['nuwiki#diary#calendar_sign'](30, 5, 2026)))
|
||||||
|
record(vim.fn['nuwiki#diary#calendar_sign'](31, 5, 2026) == '',
|
||||||
|
'sign.absent_date_unmarked',
|
||||||
|
'got ' .. tostring(vim.fn['nuwiki#diary#calendar_sign'](31, 5, 2026)))
|
||||||
|
|
||||||
|
-- ===== calendar_action: path + window-close (real window API) =====
|
||||||
|
-- Open a second window to act as the calendar, invoke from it, and confirm
|
||||||
|
-- the diary lands at WIKI/diary/<date>.wiki while the calendar window closes.
|
||||||
|
vim.cmd('new')
|
||||||
|
local cal_win = vim.api.nvim_get_current_win()
|
||||||
|
local wins_before = #vim.api.nvim_list_wins()
|
||||||
|
vim.fn['nuwiki#diary#calendar_action'](31, 5, 2026, 0, '')
|
||||||
|
|
||||||
|
local opened = vim.fn.expand('%:p')
|
||||||
|
local want = WIKI .. '/diary/2026-05-31.wiki'
|
||||||
|
record(opened == want, 'action.opens_wiki_diary_path', 'opened=' .. opened)
|
||||||
|
record(not opened:match(vim.fn.expand('~') .. '/diary'),
|
||||||
|
'action.not_home_diary', 'opened=' .. opened)
|
||||||
|
record(not vim.api.nvim_win_is_valid(cal_win),
|
||||||
|
'action.closes_calendar_window',
|
||||||
|
'cal_win valid=' .. tostring(vim.api.nvim_win_is_valid(cal_win)))
|
||||||
|
record(#vim.api.nvim_list_wins() == wins_before - 1,
|
||||||
|
'action.window_count_decremented',
|
||||||
|
'before=' .. wins_before .. ' after=' .. #vim.api.nvim_list_wins())
|
||||||
|
record(vim.bo.filetype == 'vimwiki', 'action.sets_filetype',
|
||||||
|
'filetype=' .. vim.bo.filetype)
|
||||||
|
|
||||||
|
finish()
|
||||||
Executable
+106
@@ -0,0 +1,106 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# development/tests/test-calendar.sh — calendar-vim integration harness (Neovim).
|
||||||
|
#
|
||||||
|
# Drives development/tests/test-calendar.lua under headless Neovim to cover the
|
||||||
|
# pieces specific to the Lua entry point:
|
||||||
|
# * require('nuwiki').setup() wiring g:calendar_action / g:calendar_sign and
|
||||||
|
# overriding calendar-vim's own defaults,
|
||||||
|
# * calendar_action's window-close behaviour under the real window API,
|
||||||
|
# * opting out with use_calendar = false.
|
||||||
|
#
|
||||||
|
# A stub calendar-vim on the runtimepath provides :Calendar and seeds the
|
||||||
|
# default hook names. The LSP binary is built (setup() registers the client);
|
||||||
|
# the calendar paths themselves don't need the server.
|
||||||
|
#
|
||||||
|
# Exit: 0 when both runs are green, 1 otherwise. Skips (0) without nvim.
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||||
|
TMP="$(mktemp -d -t nuwiki-calendar-test-XXXXXX)"
|
||||||
|
trap 'rm -rf "$TMP"' EXIT
|
||||||
|
|
||||||
|
log() { printf '\033[1;34m[calendar]\033[0m %s\n' "$*"; }
|
||||||
|
|
||||||
|
if ! command -v nvim >/dev/null 2>&1; then
|
||||||
|
log 'nvim not installed — skipping'
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# setup() registers the LSP client, so build the binary like the other
|
||||||
|
# Neovim harnesses do (incremental, fast).
|
||||||
|
BIN="$REPO_ROOT/bin/nuwiki-ls"
|
||||||
|
log 'building nuwiki-ls (release, incremental)…'
|
||||||
|
cargo build --release -p nuwiki-ls --manifest-path "$REPO_ROOT/Cargo.toml" >/dev/null
|
||||||
|
mkdir -p "$REPO_ROOT/bin"
|
||||||
|
ln -sf "$REPO_ROOT/target/release/nuwiki-ls" "$BIN"
|
||||||
|
|
||||||
|
# --- Scratch wiki with one seeded diary entry (2026-05-30) ----------------
|
||||||
|
WIKI="$TMP/wiki"
|
||||||
|
mkdir -p "$WIKI/diary"
|
||||||
|
echo "= index =" > "$WIKI/index.wiki"
|
||||||
|
echo "= 2026-05-30 =" > "$WIKI/diary/2026-05-30.wiki"
|
||||||
|
|
||||||
|
# --- Stub calendar-vim ----------------------------------------------------
|
||||||
|
CAL="$TMP/calendar-vim"
|
||||||
|
mkdir -p "$CAL/plugin" "$CAL/autoload"
|
||||||
|
cat > "$CAL/plugin/calendar.vim" <<'EOF'
|
||||||
|
if exists('g:loaded_calendar_stub') | finish | endif
|
||||||
|
let g:loaded_calendar_stub = 1
|
||||||
|
let g:calendar_action = get(g:, 'calendar_action', 'calendar#diary')
|
||||||
|
let g:calendar_sign = get(g:, 'calendar_sign', 'calendar#sign')
|
||||||
|
command! -nargs=* Calendar echo 'stub calendar'
|
||||||
|
EOF
|
||||||
|
cat > "$CAL/autoload/calendar.vim" <<'EOF'
|
||||||
|
function! calendar#open(...) abort
|
||||||
|
endfunction
|
||||||
|
function! calendar#diary(...) abort
|
||||||
|
endfunction
|
||||||
|
function! calendar#sign(...) abort
|
||||||
|
return 0
|
||||||
|
endfunction
|
||||||
|
EOF
|
||||||
|
|
||||||
|
write_init() {
|
||||||
|
local file="$1" use_calendar="$2"
|
||||||
|
cat > "$file" <<EOF
|
||||||
|
vim.opt.runtimepath:prepend('$REPO_ROOT')
|
||||||
|
vim.opt.runtimepath:append('$CAL')
|
||||||
|
vim.g.nuwiki_binary_path = '$BIN'
|
||||||
|
vim.g.nuwiki_wiki_root = '$WIKI'
|
||||||
|
vim.g.nuwiki_file_extension = '.wiki'
|
||||||
|
vim.g.nuwiki_diary_rel_path = 'diary'
|
||||||
|
require('nuwiki').setup({ wiki_root = '$WIKI', use_calendar = $use_calendar })
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
run() {
|
||||||
|
local label="$1" init="$2" mode="$3"
|
||||||
|
local results="$TMP/results-$label.txt"
|
||||||
|
log "running $label harness…"
|
||||||
|
NUWIKI_CALENDAR_RESULTS="$results" \
|
||||||
|
NUWIKI_CALENDAR_WIKI="$WIKI" \
|
||||||
|
NUWIKI_CALENDAR_MODE="$mode" \
|
||||||
|
timeout 60 nvim --clean -u "$init" --headless \
|
||||||
|
-c "luafile $REPO_ROOT/development/tests/test-calendar.lua" \
|
||||||
|
>"$TMP/$label.log" 2>&1 || true
|
||||||
|
if [[ ! -f "$results" ]]; then
|
||||||
|
echo "calendar $label harness produced no output" >&2
|
||||||
|
echo "--- nvim log ---" >&2
|
||||||
|
cat "$TMP/$label.log" >&2 || true
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
cat "$results"
|
||||||
|
grep -qE '^SUMMARY: [0-9]+ passed, 0 failed' "$results"
|
||||||
|
}
|
||||||
|
|
||||||
|
INIT_ON="$TMP/init-on.lua"
|
||||||
|
INIT_OFF="$TMP/init-off.lua"
|
||||||
|
write_init "$INIT_ON" 'true'
|
||||||
|
write_init "$INIT_OFF" 'false'
|
||||||
|
|
||||||
|
rc=0
|
||||||
|
run 'default' "$INIT_ON" 'default' || rc=1
|
||||||
|
run 'optout' "$INIT_OFF" 'optout' || rc=1
|
||||||
|
exit $rc
|
||||||
+5
-20
@@ -85,26 +85,11 @@ function M.setup(opts)
|
|||||||
vim.filetype.add({ extension = extensions })
|
vim.filetype.add({ extension = extensions })
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Auto-detect calendar-vim and wire hooks when the first vimwiki buffer loads.
|
-- Calendar-vim wiring lives in plugin/nuwiki.vim's FileType autocmd, which
|
||||||
-- On by default; disable with use_calendar = false or g:nuwiki_no_calendar.
|
-- runs for both Vim and Neovim. Translate the Lua-side opt-out into the
|
||||||
if config.options.use_calendar ~= false and not config.options.no_calendar then
|
-- g: flag that autocmd reads so `use_calendar = false` fully disables it.
|
||||||
vim.api.nvim_create_autocmd('FileType', {
|
if config.options.use_calendar == false then
|
||||||
pattern = 'vimwiki',
|
vim.g.nuwiki_no_calendar = 1
|
||||||
callback = function()
|
|
||||||
if vim.fn.exists('*calendar#open') == 1 or vim.fn.exists(':Calendar') == 2 then
|
|
||||||
-- Overwrite calendar-vim's own defaults (which write to ~/diary)
|
|
||||||
-- but respect a user-set custom hook.
|
|
||||||
local act = vim.g.calendar_action
|
|
||||||
if not act or act == '' or act == 'calendar#diary' then
|
|
||||||
vim.g.calendar_action = 'vimwiki#diary#calendar_action'
|
|
||||||
end
|
|
||||||
local sign = vim.g.calendar_sign
|
|
||||||
if not sign or sign == '' or sign == 'calendar#sign' then
|
|
||||||
vim.g.calendar_sign = 'vimwiki#diary#calendar_sign'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
end
|
end
|
||||||
|
|
||||||
lsp.register()
|
lsp.register()
|
||||||
|
|||||||
Reference in New Issue
Block a user