diff --git a/autoload/nuwiki/commands.vim b/autoload/nuwiki/commands.vim
index f1efa8a..dc4ad85 100644
--- a/autoload/nuwiki/commands.vim
+++ b/autoload/nuwiki/commands.vim
@@ -190,6 +190,30 @@ function! nuwiki#commands#auto_chdir() abort
endif
endfunction
+" vimwiki `auto_header`: on a new wiki page, insert a level-1 header derived
+" from the filename. Skips the wiki index + diary index pages; only acts on an
+" empty new buffer. Wired from a BufNewFile autocmd.
+function! nuwiki#commands#auto_header() abort
+ if line('$') > 1 || getline(1) !=# ''
+ return
+ endif
+ let l:file = expand('%:p')
+ for l:c in nuwiki#commands#wiki_list()
+ let l:root = fnamemodify(expand(l:c.root), ':p')
+ if l:root[len(l:root) - 1:] !=# '/' | let l:root .= '/' | endif
+ if l:file[: len(l:root) - 1] ==# l:root
+ let l:index_path = l:root . l:c.idx . l:c.ext
+ let l:diary_index_path = l:root . l:c.diary_rel . '/' . l:c.diary_idx . l:c.ext
+ if l:file ==# l:index_path || l:file ==# l:diary_index_path
+ return
+ endif
+ break
+ endif
+ endfor
+ call setline(1, '= ' . expand('%:t:r') . ' =')
+ call append(1, '')
+endfunction
+
" :VimwikiShowVersion / :NuwikiShowVersion — echo the nuwiki version and the
" host editor, mirroring upstream's version banner.
function! nuwiki#commands#show_version() abort
diff --git a/crates/nuwiki-lsp/src/lib.rs b/crates/nuwiki-lsp/src/lib.rs
index 931cec9..1326b02 100644
--- a/crates/nuwiki-lsp/src/lib.rs
+++ b/crates/nuwiki-lsp/src/lib.rs
@@ -269,7 +269,29 @@ impl Backend {
}
}
let path = target.path.as_deref()?;
- return synthesise_page_uri(&source_wiki.config, path);
+ // vimwiki `dir_link`: a `[[dir/]]` link opens `
/`
+ // (e.g. `index` → `dir/index.wiki`); empty → the directory itself.
+ if target.is_directory {
+ let dl = source_wiki.config.dir_link.trim();
+ if dl.is_empty() {
+ let mut p = source_wiki.config.root.clone();
+ for seg in path.split('/').filter(|s| !s.is_empty()) {
+ p.push(seg);
+ }
+ return Url::from_file_path(p).ok();
+ }
+ let joined = format!("{}/{dl}", path.trim_end_matches('/'));
+ return synthesise_page_uri(&source_wiki.config, &joined);
+ }
+ // vimwiki `create_link`: when off, only follow to a page that
+ // already exists on disk — never synthesise a new one.
+ let uri = synthesise_page_uri(&source_wiki.config, path)?;
+ if !source_wiki.config.create_link
+ && !uri.to_file_path().map(|p| p.exists()).unwrap_or(false)
+ {
+ return None;
+ }
+ return Some(uri);
}
// No wiki registered (no `initializationOptions`, no
// workspace folder). Fall back to the source buffer's
diff --git a/development/tests/test-keymaps-vim.vim b/development/tests/test-keymaps-vim.vim
index f796b02..8d83251 100644
--- a/development/tests/test-keymaps-vim.vim
+++ b/development/tests/test-keymaps-vim.vim
@@ -728,6 +728,23 @@ endtry
call s:record(s:nm_err ==# '' ? 1 : 0,
\ 'cmd.VimwikiSearch_no_match_graceful', 'err=' . s:nm_err)
+" ===== auto_header inserts `= Stem =` on a new wiki page; skips the index =====
+let s:ah_root = fnamemodify(expand(nuwiki#commands#wiki_list()[0].root), ':p')
+if s:ah_root[len(s:ah_root)-1:] !=# '/' | let s:ah_root .= '/' | endif
+new
+execute 'file ' . fnameescape('/tmp/nuwiki-ah-plain/MyNewPage.wiki')
+call nuwiki#commands#auto_header()
+call s:record(getline(1) ==# '= MyNewPage =' ? 1 : 0,
+ \ 'cmd.auto_header_inserts', 'line1=' . getline(1))
+bwipeout!
+new
+execute 'file ' . fnameescape(s:ah_root . 'index.wiki')
+call nuwiki#commands#auto_header()
+call s:record(getline(1) ==# '' ? 1 : 0,
+ \ 'cmd.auto_header_skips_index', 'line1=' . getline(1))
+bwipeout!
+unlet s:ah_root
+
" ===== :VimwikiGoto -nargs=* =====
" Was -nargs=1, so a page name with a space raised E488 (and the empty-arg
" prompt fallback was unreachable). Now -nargs=*: a multi-word arg must parse.
diff --git a/development/tests/test-keymaps.lua b/development/tests/test-keymaps.lua
index 5e7fd64..c0e68ae 100644
--- a/development/tests/test-keymaps.lua
+++ b/development/tests/test-keymaps.lua
@@ -305,6 +305,31 @@ vim.defer_fn(function()
vim.cmd('bwipeout!')
end
+ -- auto_header: the function inserts `= Stem =` on an empty new wiki buffer,
+ -- and skips the wiki index page. Operate on dedicated buffer handles so the
+ -- harness's own buffer is untouched.
+ do
+ local wroot = require('nuwiki.config').wiki_cfg(0).root
+ local root = vim.fn.fnamemodify(vim.fn.expand(wroot), ':p')
+ if root:sub(-1) ~= '/' then root = root .. '/' end
+ local function ah_line(name)
+ local buf = vim.api.nvim_create_buf(true, false)
+ vim.api.nvim_buf_set_name(buf, name)
+ require('nuwiki.commands').auto_header(buf)
+ local line = vim.api.nvim_buf_get_lines(buf, 0, 1, false)[1] or ''
+ vim.api.nvim_buf_delete(buf, { force = true })
+ return line
+ end
+ -- A normal page (outside any wiki root) → header inserted.
+ local got = ah_line('/tmp/nuwiki-ah-plain/MyNewPage.wiki')
+ record(got == '= MyNewPage =', 'cmd.auto_header_inserts', 'line1=' .. got)
+ -- The diary index page → skipped (no header). (The wiki index itself is the
+ -- harness's open buffer, so use the diary index to avoid an E95 collision.)
+ local c = require('nuwiki.config').wiki_cfg(0)
+ local idx_line = ah_line(root .. c.diary_rel .. '/' .. c.diary_idx .. '.wiki')
+ record(idx_line == '', 'cmd.auto_header_skips_diary_index', 'line1=' .. idx_line)
+ end
+
-- ===== Lists =====
run('list.toggle_via_C-Space', {
diff --git a/lua/nuwiki/commands.lua b/lua/nuwiki/commands.lua
index b48c631..eee6e6d 100644
--- a/lua/nuwiki/commands.lua
+++ b/lua/nuwiki/commands.lua
@@ -285,6 +285,37 @@ function M.show_version()
}, false, {})
end
+-- vimwiki `auto_header`: on a new wiki page, insert a level-1 header derived
+-- from the filename. Skips the wiki index + diary index pages, and only acts
+-- on a genuinely empty buffer. Called from a BufNewFile autocmd.
+function M.auto_header(bufnr)
+ bufnr = bufnr or vim.api.nvim_get_current_buf()
+ local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
+ if #lines > 1 or (lines[1] or '') ~= '' then
+ return -- not an empty new buffer
+ end
+ local file = vim.api.nvim_buf_get_name(bufnr)
+ local config = require('nuwiki.config')
+ for i = 0, 64 do
+ local c = config.wiki_cfg(i)
+ if not c then break end
+ local root = vim.fn.fnamemodify(vim.fn.expand(c.root), ':p')
+ if root:sub(-1) ~= '/' then root = root .. '/' end
+ if file:sub(1, #root) == root then
+ -- Skip the wiki index and the diary index pages.
+ local index_path = root .. c.idx .. c.ext
+ local diary_index_path = root .. c.diary_rel .. '/' .. c.diary_idx .. c.ext
+ if file == index_path or file == diary_index_path then
+ return
+ end
+ break
+ end
+ if not (config.options.wikis or vim.g.nuwiki_wikis) then break end
+ end
+ local title = vim.fn.fnamemodify(file, ':t:r')
+ vim.api.nvim_buf_set_lines(bufnr, 0, 1, false, { '= ' .. title .. ' =', '' })
+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
diff --git a/lua/nuwiki/init.lua b/lua/nuwiki/init.lua
index be37b71..9443799 100644
--- a/lua/nuwiki/init.lua
+++ b/lua/nuwiki/init.lua
@@ -113,6 +113,22 @@ function M.setup(opts)
vim.g.nuwiki_no_calendar = 1
end
+ -- vimwiki `auto_header` (default off): insert a level-1 header from the
+ -- filename on new wiki pages. BufNewFile (not FileType) so it only fires for
+ -- genuinely new files.
+ if config.options.auto_header == true then
+ local ext = (config.options.file_extension or '.wiki'):gsub('^%.', '')
+ local pats = { '*.wiki' }
+ if ext ~= 'wiki' and ext ~= '' then
+ pats[#pats + 1] = '*.' .. ext
+ end
+ vim.api.nvim_create_autocmd('BufNewFile', {
+ pattern = pats,
+ group = vim.api.nvim_create_augroup('nuwiki_auto_header', { clear = true }),
+ callback = function(a) require('nuwiki.commands').auto_header(a.buf) end,
+ })
+ end
+
lsp.register()
_setup_global_mappings()
_setup_global_commands()
diff --git a/plugin/nuwiki.vim b/plugin/nuwiki.vim
index 003afdb..d70300b 100644
--- a/plugin/nuwiki.vim
+++ b/plugin/nuwiki.vim
@@ -69,6 +69,19 @@ augroup nuwiki_vim_lsp_start
autocmd FileType vimwiki call nuwiki#lsp#start()
augroup END
+" vimwiki `auto_header` (default off): insert a level-1 header from the filename
+" on new wiki pages. BufNewFile fires only for genuinely new files. Matches the
+" configured extension(s).
+if get(g:, 'nuwiki_auto_header', 0)
+ let s:awh_ext = get(g:, 'nuwiki_file_extension', '.wiki')
+ let s:awh_ext = s:awh_ext[0] ==# '.' ? s:awh_ext : '.' . s:awh_ext
+ augroup nuwiki_auto_header
+ autocmd!
+ execute 'autocmd BufNewFile *' . s:awh_ext . ' call nuwiki#commands#auto_header()'
+ augroup END
+ unlet s:awh_ext
+endif
+
" Global wiki-picker commands — available from any buffer so a wiki can be
" chosen before a .wiki file exists. The picker reads its list from config
" (no LSP); opening the chosen index then auto-starts the server. The