feat(calendar): integrate calendar-vim with wiki diary paths
Wire g:calendar_action/g:calendar_sign to nuwiki diary hooks that resolve diary paths from the wiki root config instead of calendar-vim's default ~/diary. Auto-detected on FileType vimwiki when calendar-vim is present; opt out with g:nuwiki_use_calendar=0 or g:nuwiki_no_calendar. - autoload/nuwiki/diary.vim: calendar_action/calendar_sign using wiki cfg; open diary in the previous window and close the calendar window after. - autoload/vimwiki/diary.vim: vimwiki# aliases for drop-in compatibility. - plugin/nuwiki.vim + lua/nuwiki/init.lua: auto-wire hooks, overwriting calendar-vim's defaults while respecting user-set custom hooks. - lua/nuwiki/config.lua: add use_calendar option (on by default). - development/start-*.sh + _common.sh: clone calendar-vim, fix vimrc var expansion, pass wiki root to the Vim/Neovim clients.
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
" autoload/nuwiki/diary.vim — diary-specific functions for nuwiki
|
||||
" Includes calendar-vim integration functions
|
||||
|
||||
" ===== Calendar-Vim Integration =====
|
||||
|
||||
" Function: nuwiki#diary#calendar_action(day, month, year, week, dir)
|
||||
" Called by calendar-vim when user presses Enter on a date.
|
||||
" day/month/year are numeric integers. week and dir are not used.
|
||||
" Opens or creates the diary entry for the given date.
|
||||
function! nuwiki#diary#calendar_action(day, month, year, week, dir) abort
|
||||
" Build YYYY-MM-DD from the parts passed by calendar-vim
|
||||
let l:date_str = printf('%04d-%02d-%02d', a:year, a:month, a:day)
|
||||
|
||||
" Get wiki configuration for the first wiki (index 0)
|
||||
let l:c = s:wiki_cfg(0)
|
||||
|
||||
" Construct file path: {root}/{diary_rel}/{YYYY-MM-DD}.{ext}
|
||||
let l:file_path = l:c.root . '/' . l:c.diary_rel . '/' . l:date_str . l:c.ext
|
||||
|
||||
" Remember the calendar window so we can close it once the diary opens.
|
||||
let l:cal_winid = win_getid()
|
||||
|
||||
" Open the diary file in a different window. If a previous window exists go
|
||||
" there; otherwise split / vsplit / new depending on a:dir.
|
||||
if winnr('#') > 0
|
||||
execute 'wincmd p'
|
||||
if !&hidden && &modified
|
||||
execute 'new'
|
||||
endif
|
||||
elseif a:dir ==# 'V'
|
||||
execute 'vsplit'
|
||||
else
|
||||
execute 'split'
|
||||
endif
|
||||
|
||||
execute 'edit ' . fnameescape(l:file_path)
|
||||
if !filereadable(l:file_path)
|
||||
if l:c.ext[0] ==# '.'
|
||||
execute 'setfiletype ' . l:c.ext[1:]
|
||||
else
|
||||
execute 'setfiletype ' . l:c.ext
|
||||
endif
|
||||
endif
|
||||
|
||||
" Close the calendar window now that the diary is open (keep at least one).
|
||||
if win_getid() != l:cal_winid && win_id2win(l:cal_winid) > 0 && winnr('$') > 1
|
||||
let l:diary_winid = win_getid()
|
||||
if win_gotoid(l:cal_winid)
|
||||
close
|
||||
endif
|
||||
call win_gotoid(l:diary_winid)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" Function: nuwiki#diary#calendar_sign(day, month, year)
|
||||
" Called by calendar-vim to determine which dates show markers (*)
|
||||
" day, month, year are numeric integers (1-based).
|
||||
" Returns a single-character string to use as marker (e.g. '*' or ''),
|
||||
" or 1/0 for 1-indexed calendars.
|
||||
" calendar-vim's default expects the return value to be a single character
|
||||
" to display; returning any non-empty string shows a marker.
|
||||
function! nuwiki#diary#calendar_sign(day, month, year) abort
|
||||
" Build YYYY-MM-DD from the parts passed by calendar-vim
|
||||
let l:date_str = printf('%04d-%02d-%02d', a:year, a:month, a:day)
|
||||
|
||||
" Get wiki configuration for the first wiki (index 0)
|
||||
let l:c = s:wiki_cfg(0)
|
||||
|
||||
" Construct expected file path
|
||||
let l:file_path = l:c.root . '/' . l:c.diary_rel . '/' . l:date_str . l:c.ext
|
||||
|
||||
" Return a marker if the file exists, empty string otherwise
|
||||
if filereadable(l:file_path)
|
||||
return '*'
|
||||
endif
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
" Helper: get wiki configuration for wiki n (0-based).
|
||||
" Mirrors the same logic used by nuwiki#commands#open_diary_path etc.
|
||||
function! s:wiki_cfg(n) abort
|
||||
let l:w = {}
|
||||
if exists('g:nuwiki_wikis') && len(g:nuwiki_wikis) > a:n
|
||||
let l:w = g:nuwiki_wikis[a:n]
|
||||
endif
|
||||
let l:root = expand(get(l:w, 'root',
|
||||
\ get(g:, 'nuwiki_wiki_root', '~/vimwiki')))
|
||||
let l:ext = get(l:w, 'file_extension',
|
||||
\ get(g:, 'nuwiki_file_extension', '.wiki'))
|
||||
if l:ext[0] !=# '.' | let l:ext = '.' . l:ext | endif
|
||||
let l:idx = get(l:w, 'index', 'index')
|
||||
let l:diary_rel = get(l:w, 'diary_rel_path',
|
||||
\ get(g:, 'nuwiki_diary_rel_path', 'diary'))
|
||||
let l:diary_idx = get(l:w, 'diary_index', 'diary')
|
||||
return { 'root': l:root, 'ext': l:ext, 'idx': l:idx,
|
||||
\ 'diary_rel': l:diary_rel, 'diary_idx': l:diary_idx }
|
||||
endfunction
|
||||
@@ -0,0 +1,14 @@
|
||||
" autoload/vimwiki/diary.vim — vimwiki namespace aliases for nuwiki diary functions
|
||||
" Provides drop-in compatibility for vimwiki-dependent plugins like calendar-vim
|
||||
|
||||
" vimwiki#diary#calendar_action(day, month, year, week, dir)
|
||||
" Alias to nuwiki#diary#calendar_action for calendar-vim compatibility
|
||||
function! vimwiki#diary#calendar_action(day, month, year, week, dir) abort
|
||||
return nuwiki#diary#calendar_action(a:day, a:month, a:year, a:week, a:dir)
|
||||
endfunction
|
||||
|
||||
" vimwiki#diary#calendar_sign(day, month, year)
|
||||
" Alias to nuwiki#diary#calendar_sign for calendar-vim compatibility
|
||||
function! vimwiki#diary#calendar_sign(day, month, year) abort
|
||||
return nuwiki#diary#calendar_sign(a:day, a:month, a:year)
|
||||
endfunction
|
||||
@@ -275,6 +275,20 @@ reset_dirs() {
|
||||
done
|
||||
}
|
||||
|
||||
# ensure_calendar_vim — clone calendar-vim into dev dir for testing
|
||||
ensure_calendar_vim() {
|
||||
local repo="$DEV_DIR/calendar-vim"
|
||||
if [[ -d "$repo/.git" ]]; then
|
||||
return
|
||||
fi
|
||||
if ! command -v git >/dev/null 2>&1; then
|
||||
log "git not found — skipping calendar-vim"
|
||||
return 1
|
||||
fi
|
||||
log "cloning https://github.com/mattn/calendar-vim.git → $repo"
|
||||
git clone --depth 1 https://github.com/mattn/calendar-vim.git "$repo" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
seed_wiki() {
|
||||
if [[ "${NUWIKI_DEV_NO_SEED:-0}" == "1" ]]; then
|
||||
log "NUWIKI_DEV_NO_SEED=1 — skipping wiki seed (using $WIKI_DIR as-is)"
|
||||
|
||||
@@ -54,17 +54,13 @@ vim.env.XDG_DATA_HOME = '$DATA_DIR'
|
||||
vim.env.XDG_CONFIG_HOME = '$CONFIG_DIR'
|
||||
|
||||
vim.opt.runtimepath:prepend('$REPO_ROOT')
|
||||
vim.opt.runtimepath:append('$DEV_DIR/calendar-vim')
|
||||
|
||||
vim.g.nuwiki_binary_path = '$REPO_ROOT/bin/nuwiki-ls'
|
||||
|
||||
-- Friendly defaults for an interactive smoke test.
|
||||
vim.opt.number = true
|
||||
vim.opt.signcolumn = 'yes'
|
||||
vim.opt.termguicolors = true
|
||||
vim.opt.swapfile = false
|
||||
vim.opt.writebackup = false
|
||||
vim.opt.undofile = false
|
||||
vim.g.mapleader = ' '
|
||||
vim.g.nuwiki_wiki_root = '$WIKI_DIR'
|
||||
vim.g.nuwiki_file_extension = '.wiki'
|
||||
vim.g.nuwiki_syntax = 'vimwiki'
|
||||
vim.g.nuwiki_diary_rel_path = 'diary'
|
||||
|
||||
require('nuwiki').setup({
|
||||
wiki_root = '$WIKI_DIR',
|
||||
@@ -74,13 +70,14 @@ require('nuwiki').setup({
|
||||
-- they're swallowed; with it they land in :messages.
|
||||
vim.lsp.set_log_level('info')
|
||||
|
||||
print('[nuwiki-dev] ready — wiki root: $WIKI_DIR')
|
||||
print('[nuwiki-dev] ready — wiki root: ' .. '$WIKI_DIR')
|
||||
print('[nuwiki-dev] :LspInfo to inspect, :checkhealth nuwiki for diagnostics')
|
||||
EOF
|
||||
}
|
||||
|
||||
main() {
|
||||
ensure_binary
|
||||
ensure_calendar_vim
|
||||
seed_wiki
|
||||
write_init
|
||||
reset_dirs "$STATE_DIR" "$DATA_DIR" "$CONFIG_DIR"
|
||||
|
||||
@@ -114,25 +114,27 @@ write_vimrc() {
|
||||
|
||||
" Confine state to the dev cache so we never touch the user's real Vim
|
||||
" install.
|
||||
set viminfo='100,n$VIM_STATE/viminfo
|
||||
let &directory = '$VIM_STATE/swap//'
|
||||
let &backupdir = '$VIM_STATE/backup//'
|
||||
let &undodir = '$VIM_STATE/undo//'
|
||||
set viminfo='100,n${VIM_STATE}/viminfo
|
||||
let &directory = '${VIM_STATE}/swap//'
|
||||
let &backupdir = '${VIM_STATE}/backup//'
|
||||
let &undodir = '${VIM_STATE}/undo//'
|
||||
|
||||
" Make Vim look for runtime paths in the dev cache. vim-lsp is intentionally
|
||||
" absent so nuwiki dispatches jump-to-definition through coc.
|
||||
set nocompatible
|
||||
let &runtimepath = '$REPO_ROOT' . ',' . &runtimepath
|
||||
let &runtimepath .= ',$COC_DIR'
|
||||
let &runtimepath = '${REPO_ROOT}' . ',' . &runtimepath
|
||||
let &runtimepath .= ',${COC_DIR}'
|
||||
let &runtimepath .= ',${DEV_DIR}/calendar-vim'
|
||||
|
||||
" Point coc at the generated settings + a private data dir.
|
||||
let g:coc_config_home = '$DEV_DIR'
|
||||
let g:coc_data_home = '$COC_DATA'
|
||||
let g:coc_config_home = '${DEV_DIR}'
|
||||
let g:coc_data_home = '${COC_DATA}'
|
||||
|
||||
let g:nuwiki_binary_path = '$REPO_ROOT/bin/nuwiki-ls'
|
||||
let g:nuwiki_wiki_root = '$WIKI_DIR'
|
||||
let g:nuwiki_binary_path = '${REPO_ROOT}/bin/nuwiki-ls'
|
||||
let g:nuwiki_wiki_root = '${WIKI_DIR}'
|
||||
let g:nuwiki_file_extension = '.wiki'
|
||||
let g:nuwiki_syntax = 'vimwiki'
|
||||
let g:nuwiki_diary_rel_path = 'diary'
|
||||
let g:nuwiki_log_level = 'info'
|
||||
|
||||
filetype plugin indent on
|
||||
@@ -153,11 +155,8 @@ augroup NuwikiFtdetect
|
||||
autocmd BufRead,BufNewFile *.wiki setfiletype vimwiki
|
||||
augroup END
|
||||
|
||||
" coc starts the server automatically from coc-settings.json once a vimwiki
|
||||
" buffer loads — no explicit nuwiki#lsp#start() needed.
|
||||
|
||||
echomsg '[nuwiki-dev] ready (coc.nvim) — wiki root: $WIKI_DIR'
|
||||
echomsg '[nuwiki-dev] coc.preferences.jumpCommand = $COC_JUMP'
|
||||
echo
|
||||
echomsg '[nuwiki-dev] coc.preferences.jumpCommand = ' . '\$COC_JUMP'
|
||||
echomsg '[nuwiki-dev] <CR> on a [[link]] should open in the CURRENT window'
|
||||
echomsg '[nuwiki-dev] :CocList services for status, :messages for log'
|
||||
EOF
|
||||
@@ -167,6 +166,7 @@ main() {
|
||||
ensure_node
|
||||
ensure_binary
|
||||
ensure_coc
|
||||
ensure_calendar_vim
|
||||
write_coc_settings
|
||||
seed_wiki
|
||||
write_vimrc
|
||||
|
||||
+12
-11
@@ -70,19 +70,20 @@ write_vimrc() {
|
||||
|
||||
" Confine state to the dev cache so we never touch the user's real Vim
|
||||
" install.
|
||||
set viminfo='100,n$VIM_STATE/viminfo
|
||||
let &directory = '$VIM_STATE/swap//'
|
||||
let &backupdir = '$VIM_STATE/backup//'
|
||||
let &undodir = '$VIM_STATE/undo//'
|
||||
set viminfo='100,n${VIM_STATE}/viminfo
|
||||
let &directory = '${VIM_STATE}/swap//'
|
||||
let &backupdir = '${VIM_STATE}/backup//'
|
||||
let &undodir = '${VIM_STATE}/undo//'
|
||||
|
||||
" Make Vim look for runtime paths in the dev cache.
|
||||
set nocompatible
|
||||
let &runtimepath = '$REPO_ROOT' . ',' . &runtimepath
|
||||
let &runtimepath .= ',$VIM_LSP_DIR'
|
||||
let &runtimepath .= ',$ASYNC_DIR'
|
||||
let &runtimepath = '${REPO_ROOT}' . ',' . &runtimepath
|
||||
let &runtimepath .= ',${VIM_LSP_DIR}'
|
||||
let &runtimepath .= ',${ASYNC_DIR}'
|
||||
let &runtimepath .= ',${DEV_DIR}/calendar-vim'
|
||||
|
||||
let g:nuwiki_binary_path = '$REPO_ROOT/bin/nuwiki-ls'
|
||||
let g:nuwiki_wiki_root = '$WIKI_DIR'
|
||||
let g:nuwiki_binary_path = '${REPO_ROOT}/bin/nuwiki-ls'
|
||||
let g:nuwiki_wiki_root = '${WIKI_DIR}'
|
||||
let g:nuwiki_file_extension = '.wiki'
|
||||
let g:nuwiki_syntax = 'vimwiki'
|
||||
let g:nuwiki_log_level = 'info'
|
||||
@@ -113,8 +114,7 @@ augroup NuwikiStart
|
||||
autocmd FileType vimwiki call nuwiki#lsp#start()
|
||||
augroup END
|
||||
|
||||
" Status messages go to :messages so they don't trigger "Press ENTER".
|
||||
echomsg '[nuwiki-dev] ready — wiki root: $WIKI_DIR'
|
||||
echomsg '[nuwiki-dev] ready — wiki root: ' . g:nuwiki_wiki_root
|
||||
echomsg '[nuwiki-dev] :LspStatus for diagnostics, :messages for log'
|
||||
EOF
|
||||
}
|
||||
@@ -122,6 +122,7 @@ EOF
|
||||
main() {
|
||||
ensure_binary
|
||||
ensure_vim_lsp
|
||||
ensure_calendar_vim
|
||||
seed_wiki
|
||||
write_vimrc
|
||||
reset_dirs "$VIM_STATE"
|
||||
|
||||
@@ -56,6 +56,12 @@ M.defaults = {
|
||||
diagnostic = {
|
||||
link_severity = 'warn',
|
||||
},
|
||||
|
||||
-- Calendar-vim integration. On by default — set to `false` to opt out.
|
||||
-- When on, nuwiki detects calendar-vim on the runtimepath and wires
|
||||
-- `g:calendar_action` / `g:calendar_sign` automatically.
|
||||
-- Also respects `g:nuwiki_no_calendar` set before setup() to disable.
|
||||
use_calendar = true,
|
||||
}
|
||||
|
||||
M.options = vim.deepcopy(M.defaults)
|
||||
|
||||
@@ -85,6 +85,28 @@ function M.setup(opts)
|
||||
vim.filetype.add({ extension = extensions })
|
||||
end
|
||||
|
||||
-- Auto-detect calendar-vim and wire hooks when the first vimwiki buffer loads.
|
||||
-- On by default; disable with use_calendar = false or g:nuwiki_no_calendar.
|
||||
if config.options.use_calendar ~= false and not config.options.no_calendar then
|
||||
vim.api.nvim_create_autocmd('FileType', {
|
||||
pattern = 'vimwiki',
|
||||
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
|
||||
|
||||
lsp.register()
|
||||
_setup_global_mappings()
|
||||
_setup_global_commands()
|
||||
|
||||
@@ -27,6 +27,30 @@ else
|
||||
command! -nargs=0 NuwikiInstall execute 'source' fnameescape(s:plugin_root . '/scripts/download_bin.vim')
|
||||
endif
|
||||
|
||||
" Calendar-Vim Integration — auto-detect when calendar-vim is loaded.
|
||||
augroup nuwiki_calendar_detect
|
||||
autocmd!
|
||||
autocmd FileType vimwiki call s:nuwiki_setup_calendar()
|
||||
augroup END
|
||||
function! s:nuwiki_setup_calendar() abort
|
||||
if !get(g:, 'nuwiki_use_calendar', 1) || get(g:, 'nuwiki_no_calendar', 0)
|
||||
return
|
||||
endif
|
||||
if exists('*calendar#open') || exists(':Calendar') == 2
|
||||
" Wire nuwiki's diary hooks unless the user set a custom (non-default) one.
|
||||
" calendar-vim's own default is 'calendar#diary' (writes to ~/diary); we
|
||||
" overwrite that so paths come from the wiki root config instead.
|
||||
let l:act = get(g:, 'calendar_action', '')
|
||||
if l:act ==# '' || l:act ==# 'calendar#diary'
|
||||
let g:calendar_action = 'vimwiki#diary#calendar_action'
|
||||
endif
|
||||
let l:sign = get(g:, 'calendar_sign', '')
|
||||
if l:sign ==# '' || l:sign ==# 'calendar#sign'
|
||||
let g:calendar_sign = 'vimwiki#diary#calendar_sign'
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
if has('nvim')
|
||||
" Neovim path is initialised by `require('nuwiki').setup()`. Nothing else
|
||||
" to do at vimscript boot — wait until the user runs setup.
|
||||
|
||||
Reference in New Issue
Block a user