spec: define v1.1 — full vimwiki replacement (Phases 11–18)
v1.0 shipped parsing + highlighting + navigation; the gap-analysis vs
github.com/vimwiki/vimwiki shows nuwiki covers ~95% of the syntax but
0% of the daily-authoring command surface (≈40 :Vimwiki* commands and
≈60 keymaps), the diary, tags, link health, HTML export commands, and
multi-wiki. v1.1 closes that gap without architectural changes — every
new editing operation lands as an LSP executeCommand returning a
WorkspaceEdit, so nuwiki-core stays the single source of truth.
Spec additions:
- Status line: v1.0 shipped; v1.1 in design.
- §1: v1.1 scope summarised; multi-wiki moved out of "non-goals (v1.0)"
and into v1.1.
- §10: 8 new phase rows (11–18) under a v1.1 divider.
- 11 Tags, 12 Workspace edits + executeCommand, 13 List/table edit
commands, 14 Link health + TOC/index generation, 15 Diary,
16 HTML export commands, 17 Multi-wiki, 18 Editor glue v2.
- §11: 8 new pending decisions (P10–P17): command namespace, tag
syntax, list-edit transport, multi-wiki config shape, folding
mechanism, diary path scheme, v1.0 config back-compat, markdown
syntax inclusion.
- §12: new top-level v1.1 plan with 12 subsections covering stability
commitment, tags spec (AST + index), workspace-edit semantics,
~15 nuwiki.* edit commands, link-health diagnostics, diary path
conventions + commands, HTML export commands + per-wiki options,
multi-wiki schema, full editor-glue v2 (:Vimwiki* compatibility
table, default keymaps, text objects, folding, insert-mode behaviour,
health-check additions), updated user-config schema example,
§9 syntax checklist additions (tags, hex colour, table alignment,
multi-line lists), CI/CD notes.
v1.0 stability is preserved: AST + Visitor + LSP capabilities +
HtmlRenderer output + v1.0 config keys are all backward-compatible.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,18 @@
|
||||
# nuwiki — Project Specification
|
||||
|
||||
> Last updated: 2026-05-10
|
||||
> Status: All phases (0–10) complete
|
||||
> Last updated: 2026-05-11
|
||||
> Status: v1.0 (Phases 0–10) shipped; v1.1 (Phases 11–18) in design
|
||||
|
||||
> ### Versioning convention
|
||||
>
|
||||
> - **v1.0** — the parsing + highlighting + navigation foundation. LSP server
|
||||
> speaks the spec's §6.9 method set; editor glue provides install + setup
|
||||
> + health check.
|
||||
> - **v1.1** — full vimwiki replacement. Adds tags, diary, the
|
||||
> text-manipulation command surface (toggle checkbox, change list symbol,
|
||||
> format table, rename page, …), multi-wiki, HTML export commands,
|
||||
> link-health diagnostics, and the keymap/text-object layer that matches
|
||||
> vimwiki's daily-authoring ergonomics.
|
||||
|
||||
---
|
||||
|
||||
@@ -18,10 +29,15 @@ nuwiki is a Vim/Neovim plugin that provides full vimwiki syntax support, impleme
|
||||
|
||||
**Non-goals (v1.0):**
|
||||
- MediaWiki syntax support
|
||||
- Multi-wiki configurations
|
||||
- Multi-wiki configurations *(addressed in v1.1, see §12)*
|
||||
- Incremental / tree-sitter parsing
|
||||
- Browser-based or WASM build
|
||||
|
||||
**v1.1 scope** *(see §12 for the full plan)*:
|
||||
- Vimwiki-parity command surface (`:Vimwiki*` compat aliases over LSP
|
||||
`executeCommand`)
|
||||
- Tags, diary, link health, HTML export commands, multi-wiki, folding
|
||||
|
||||
---
|
||||
|
||||
## 2. Repository
|
||||
@@ -575,6 +591,15 @@ A semver-breaking change (`v0.x` → `v0.x+1` or `v1.x` → `v2.0`) is defined a
|
||||
| 8 | Navigation | Definition, references, hover, completion, workspace index |
|
||||
| 9 | Editor Glue | Installable plugin, health check, binary download |
|
||||
| 10 | CI/CD | Automated lint/test/release pipeline |
|
||||
| **— v1.1: full vimwiki replacement (see §12) —** | | |
|
||||
| 11 | Tags | `:tag:` lex + parse, `TagNode`, index, tag-as-anchor resolution |
|
||||
| 12 | Workspace edits + executeCommand | `workspace/rename` with cross-doc link rewrite, `DeleteFile` ops, `executeCommand` infrastructure |
|
||||
| 13 | List & table edit commands | Server commands returning `WorkspaceEdit` for checkbox toggle, list-symbol/level change, renumber, table align, column move, table insert |
|
||||
| 14 | Link health + link/TOC generation | Broken-link diagnostics, `nuwiki.toc.generate`, `nuwiki.links.generate`, `nuwiki.workspace.checkLinks` |
|
||||
| 15 | Diary | Diary subpath, today/yesterday/tomorrow open commands, diary index generation, calendar hook API |
|
||||
| 16 | HTML export commands | `nuwiki.export.*` commands, `%template` resolution, CSS file management, auto-export option |
|
||||
| 17 | Multi-wiki | `wikis = [...]` config, per-wiki `WorkspaceIndex`, URI → wiki resolution, wiki-picker commands |
|
||||
| 18 | Editor glue v2 | Full `:Vimwiki*` command compat layer, default keymaps, text objects (`ah`/`aH`/`a\\`/`ac`/`al`), `foldexpr` folding |
|
||||
|
||||
---
|
||||
|
||||
@@ -593,3 +618,523 @@ These decisions are required before or during the phase indicated.
|
||||
| ~~P7~~ | ~~**Semantic token type mapping**~~ | ~~Phase 7~~ | ✅ **Custom vimwiki-specific token types** | ~20 types (`vimwikiHeading`, `vimwikiBold`, …) + `level1`..`level6` + `centered` modifiers. Phase 9 ships default highlight groups in `syntax/nuwiki.vim` and the Lua glue. |
|
||||
| ~~P8~~ | ~~**Workspace indexing strategy**~~ | ~~Phase 8~~ | ✅ **Lazy + background with progress** | Initial scan runs as a background tokio task; nav features answer with partial data until complete; progress reported via `window/workDoneProgress`. |
|
||||
| ~~P9~~ | ~~**macOS runner**~~ | ~~Phase 10~~ | ✅ **Stay manual** | Release workflow cross-compiles the 4 Linux targets via `cross`; macOS + Windows binaries are produced ad hoc by maintainers and uploaded to the same Gitea release. Revisit when a Mac runner is available. |
|
||||
| **v1.1 decisions** | | | | |
|
||||
| P10 | **Command namespace** | Phase 12 | `:Vimwiki*` only · `:Nuwiki*` only · both | Both → easy migration *and* discoverable native commands; one canonical name + alias. |
|
||||
| P11 | **Tag syntax** | Phase 11 | Strict vimwiki `:tag:` only · Add markdown `#tag` as a second flavour | Strict keeps parity; adding `#tag` collides with hash list markers and ordered-list `#`. |
|
||||
| P12 | **List-edit transport** | Phase 13 | Server returns `WorkspaceEdit` from `executeCommand` · Editor-side text manipulation in VimL/Lua | `WorkspaceEdit` keeps logic in Rust + testable, but adds latency per keystroke for `<C-Space>`. |
|
||||
| P13 | **Multi-wiki config shape** | Phase 17 | Lua list (Neovim-native) · JSON config file (cross-editor) | Lua is ergonomic for Neovim; JSON works for Vim + arbitrary clients. |
|
||||
| P14 | **Folding mechanism** | Phase 18 | LSP `textDocument/foldingRange` · Vim-side `foldexpr` in ftplugin | LSP is correct (server knows AST); foldexpr is what vimwiki users expect and works offline. |
|
||||
| P15 | **Diary path scheme** | Phase 15 | Fixed `<wiki_root>/diary/` · Per-wiki configurable `diary_rel_path` | Vimwiki has `diary_rel_path`; matching keeps migrations clean. |
|
||||
| P16 | **Backwards-compat for v1.0 config** | Phase 17 | Preserve old single-`wiki_root` shape · Force migration to `wikis = [...]` | Single-wiki should keep working without re-config; `wiki_root` becomes sugar for `wikis = [{ root = wiki_root }]`. |
|
||||
| P17 | **Markdown syntax in v1.1** | Phase 11+ | Include · Defer to v1.2 | Architecture already supports it (`SyntaxPlugin`); cost is parser work + per-syntax differences in commands. |
|
||||
|
||||
---
|
||||
|
||||
## 12. v1.1 — Full vimwiki Replacement
|
||||
|
||||
v1.0 shipped the parsing + highlighting + navigation foundation. A vimwiki
|
||||
user transitioning to nuwiki today gets accurate syntax recognition and
|
||||
modern LSP nav, but loses the dense interactive layer that makes vimwiki
|
||||
ergonomic for daily authoring: ≈40 `:Vimwiki*` commands, ≈60 keymaps, the
|
||||
diary, the tag system, link health, HTML export commands, and multi-wiki
|
||||
configuration.
|
||||
|
||||
v1.1 closes that gap. The architecture is unchanged — every new editing
|
||||
operation lands as an LSP `executeCommand` returning a `WorkspaceEdit`, so
|
||||
the `nuwiki-core` AST stays the single source of truth and the editor glue
|
||||
stays pure wiring.
|
||||
|
||||
### 12.1 Stability commitment
|
||||
|
||||
v1.1 is additive. The following stay backward-compatible:
|
||||
|
||||
- `nuwiki-core` public AST + Visitor (additions only; no field renames)
|
||||
- LSP capabilities advertised in v1.0
|
||||
- `Renderer` trait + `HtmlRenderer` default output shape
|
||||
- v1.0 user-config keys (`wiki_root`, `file_extension`, `syntax`, `log_level`)
|
||||
|
||||
New AST nodes (e.g. `TagNode`) and new LSP capabilities are opt-in by
|
||||
inspection. The Visitor trait gains default-bodied `visit_*` methods for new
|
||||
node kinds so existing Visitor implementations don't break.
|
||||
|
||||
### 12.2 Tags (Phase 11)
|
||||
|
||||
#### Syntax
|
||||
|
||||
Vimwiki tags are colon-delimited sequences of non-space characters:
|
||||
|
||||
```
|
||||
:tag-one:tag-two:other-tag:
|
||||
```
|
||||
|
||||
Placement rules (matching vimwiki):
|
||||
|
||||
- On line 1 or 2 of a file → file-level tag
|
||||
- Within 2 lines after a `= Heading =` → header-level tag
|
||||
- Otherwise → standalone anchor at the source line
|
||||
|
||||
#### AST additions
|
||||
|
||||
```
|
||||
TagNode (block)
|
||||
span: Span
|
||||
tags: Vec<String>
|
||||
scope: TagScope -- File | Heading(idx) | Standalone
|
||||
|
||||
PageMetadata (extend)
|
||||
tags: Vec<String> -- file-level tags, accumulated
|
||||
```
|
||||
|
||||
`TagNode` slots into `BlockNode` as a new variant. The Visitor gains
|
||||
`visit_tag` (default-bodied).
|
||||
|
||||
#### Indexing
|
||||
|
||||
`WorkspaceIndex` extends `IndexedPage` with:
|
||||
|
||||
```
|
||||
IndexedPage (extend)
|
||||
tags: Vec<TagInfo>
|
||||
|
||||
TagInfo
|
||||
name: String
|
||||
scope: TagScope
|
||||
span: Span
|
||||
```
|
||||
|
||||
Plus a `tags_by_name: HashMap<String, Vec<(Url, Span)>>` reverse map. The
|
||||
existing backlink machinery in §6 stays as-is.
|
||||
|
||||
#### LSP behaviour
|
||||
|
||||
- `tags-as-anchors` extends `textDocument/definition`: `[[Page#some-tag]]`
|
||||
resolves to the tag's location in the target page (in addition to headings).
|
||||
- `workspace/symbol` results include tags (with `SymbolKind::PROPERTY` or a
|
||||
custom kind).
|
||||
- New `executeCommand` operations: `nuwiki.tags.search`,
|
||||
`nuwiki.tags.generateLinks(tag, ...)`, `nuwiki.tags.rebuild` (force re-index).
|
||||
|
||||
### 12.3 Workspace edits + `executeCommand` (Phase 12)
|
||||
|
||||
#### Capability
|
||||
|
||||
```
|
||||
ServerCapabilities {
|
||||
execute_command_provider: Some(ExecuteCommandOptions {
|
||||
commands: vec!["nuwiki.*", …],
|
||||
}),
|
||||
rename_provider: Some(true),
|
||||
workspace: Some(WorkspaceServerCapabilities {
|
||||
file_operations: Some(FileOperationOptions {
|
||||
will_rename: Some(...),
|
||||
did_rename: Some(...),
|
||||
will_delete: Some(...),
|
||||
did_delete: Some(...),
|
||||
}),
|
||||
}),
|
||||
}
|
||||
```
|
||||
|
||||
#### `workspace/rename` semantics
|
||||
|
||||
When a user renames `Page A` → `Page B`:
|
||||
|
||||
1. Server emits a `WorkspaceEdit` containing a `RenameFile` op (`A.wiki` →
|
||||
`B.wiki`).
|
||||
2. For every page in the index that links to `A`, the edit also rewrites
|
||||
`[[A]]` → `[[B]]` (preserving description, anchor, kind).
|
||||
3. Anchors don't trigger renames — `[[A#anchor]]` follows.
|
||||
|
||||
#### Custom commands router
|
||||
|
||||
A single `executeCommand` handler dispatches by command name. Every command
|
||||
takes either:
|
||||
|
||||
```
|
||||
{ uri: Url, position?: Position, range?: Range, ...args }
|
||||
```
|
||||
|
||||
and returns a `WorkspaceEdit` (which the client applies via
|
||||
`workspace/applyEdit`).
|
||||
|
||||
### 12.4 List & table editing commands (Phase 13)
|
||||
|
||||
| Command | Operates on | Result |
|
||||
|---|---|---|
|
||||
| `nuwiki.list.toggleCheckbox` | list item under cursor | `[ ]` ↔ `[X]`, propagates parent state |
|
||||
| `nuwiki.list.cycleCheckbox` | list item | `[ ]` → `[.]` → `[o]` → `[O]` → `[X]` cycle |
|
||||
| `nuwiki.list.rejectCheckbox` | list item | toggle `[-]` rejected state |
|
||||
| `nuwiki.list.changeSymbol` | list item, args: `symbol: ListSymbol`, `whole_list: bool` | rewrite marker, renumber if numeric |
|
||||
| `nuwiki.list.changeLevel` | list item, args: `delta: i32`, `whole_subtree: bool` | re-indent + adjust child levels |
|
||||
| `nuwiki.list.renumber` | list, args: `whole_file: bool` | re-sequence numeric markers |
|
||||
| `nuwiki.list.removeDone` | range or current list | remove every `[X]` / `[-]` item and its checked children |
|
||||
| `nuwiki.list.nextTask` | document | navigate to next unfinished task (returns `Location`, not edit) |
|
||||
| `nuwiki.table.align` | table under cursor | reformat columns to max width |
|
||||
| `nuwiki.table.moveColumn` | cell, args: `dir: "left"\|"right"` | swap column with neighbour |
|
||||
| `nuwiki.table.insert` | cursor, args: `cols, rows` | insert blank table at cursor |
|
||||
| `nuwiki.heading.addLevel` | heading | promote (`==` → `===`) |
|
||||
| `nuwiki.heading.removeLevel` | heading | demote |
|
||||
| `nuwiki.link.normalize` | word/selection | convert to `[[wikilink]]`, add description if missing |
|
||||
| `nuwiki.link.pasteWikilink` | cursor | paste current page name as an absolute wikilink |
|
||||
| `nuwiki.link.pasteUrl` | cursor | paste the corresponding HTML output URL |
|
||||
| `nuwiki.colorize` | range, args: `color: String` | wrap in colour tag per `color_tag_template` |
|
||||
|
||||
All operations resolve to a textual diff over the existing source so the
|
||||
AST stays the source of truth. None of them rely on editor-side state.
|
||||
|
||||
### 12.5 Link health + TOC/index generation (Phase 14)
|
||||
|
||||
#### Broken-link diagnostics
|
||||
|
||||
A new diagnostic source `nuwiki.link` runs after each parse:
|
||||
|
||||
- Wiki target → not in `WorkspaceIndex` → severity from config (default
|
||||
`Warning`)
|
||||
- Anchor target → page exists but anchor doesn't → `Warning`
|
||||
- `file:` / `local:` → file exists on disk → `Warning` if missing
|
||||
- Raw URL / external → never diagnosed (we don't fetch)
|
||||
- Configurable filtering via `diagnostic.link.severity` (`off|hint|warn|error`)
|
||||
|
||||
#### Commands
|
||||
|
||||
| Command | Behaviour |
|
||||
|---|---|
|
||||
| `nuwiki.toc.generate` | inserts a nested list of headings in the current page; replaces existing `%toc` placeholder if present |
|
||||
| `nuwiki.links.generate` | inserts a flat list of all wiki pages (vimwiki's `:VimwikiGenerateLinks`) |
|
||||
| `nuwiki.workspace.checkLinks` | returns a `Vec<BrokenLink>` for the client to render in a quickfix-style view; also emits diagnostics |
|
||||
| `nuwiki.workspace.findOrphans` | returns pages with no incoming links |
|
||||
|
||||
### 12.6 Diary (Phase 15)
|
||||
|
||||
#### Path conventions
|
||||
|
||||
```
|
||||
<wiki_root>/<diary_rel_path>/ # default: "diary"
|
||||
diary.wiki # configurable: diary_index
|
||||
2026-05-11.wiki # daily: YYYY-MM-DD
|
||||
2026-W19.wiki # weekly: YYYY-Www (configurable)
|
||||
2026-05.wiki # monthly
|
||||
2026.wiki # yearly
|
||||
```
|
||||
|
||||
#### Custom commands
|
||||
|
||||
| Command | Behaviour |
|
||||
|---|---|
|
||||
| `nuwiki.diary.openToday` | open / create today's diary page |
|
||||
| `nuwiki.diary.openYesterday` | analogous |
|
||||
| `nuwiki.diary.openTomorrow` | analogous |
|
||||
| `nuwiki.diary.openIndex` | open the diary index page |
|
||||
| `nuwiki.diary.generateIndex` | rebuild the diary index page with current entries grouped by year/month |
|
||||
| `nuwiki.diary.next` | navigate to the chronologically next diary entry from the current one |
|
||||
| `nuwiki.diary.prev` | analogous |
|
||||
|
||||
#### Calendar hook
|
||||
|
||||
External plugins (Calendar.vim, neorg-style calendars) can query:
|
||||
|
||||
- `nuwiki.diary.listEntries(year, month)` → list of dates with entries
|
||||
- `nuwiki.diary.openForDate(date)` → opens that date's entry
|
||||
|
||||
These are `executeCommand` operations, not LSP standard methods.
|
||||
|
||||
### 12.7 HTML export commands (Phase 16)
|
||||
|
||||
The `HtmlRenderer` from Phase 5 stays as the engine. v1.1 wraps it in
|
||||
user-facing commands and the per-wiki HTML lifecycle.
|
||||
|
||||
#### Per-wiki HTML options
|
||||
|
||||
| Key | Default | Description |
|
||||
|---|---|---|
|
||||
| `html_path` | `<wiki_root>/_html` | output directory |
|
||||
| `template_path` | `<wiki_root>/_templates` | template lookup root |
|
||||
| `template_default` | `default` | base template name |
|
||||
| `template_ext` | `.tpl` | template extension |
|
||||
| `template_date_format` | `%Y-%m-%d` | format passed to `{{date}}` |
|
||||
| `css_name` | `style.css` | CSS file copied/created at export |
|
||||
| `auto_export` | `false` | export on save |
|
||||
| `html_filename_parameterization` | `false` | URL-safe slugs in output filenames |
|
||||
| `exclude_files` | `[]` | globs to skip |
|
||||
|
||||
#### Commands
|
||||
|
||||
| Command | Behaviour |
|
||||
|---|---|
|
||||
| `nuwiki.export.currentToHtml` | render current page; honours `%template`, copies CSS if missing |
|
||||
| `nuwiki.export.allToHtml` | export every page in the wiki |
|
||||
| `nuwiki.export.allToHtmlForce` | `:VimwikiAll2HTML!` equivalent |
|
||||
| `nuwiki.export.browse` | export current + open default browser to result |
|
||||
| `nuwiki.export.rss` | emit `rss.xml` of recent diary entries (when diary enabled) |
|
||||
|
||||
#### Template variables
|
||||
|
||||
The `HtmlRenderer` template substitution gains:
|
||||
|
||||
- `{{title}}` (already shipped)
|
||||
- `{{content}}` (already shipped)
|
||||
- `{{date}}` (formatted via `template_date_format`)
|
||||
- `{{root_path}}` (relative path from output to `html_path` — for stylesheet
|
||||
hrefs in nested pages)
|
||||
- `{{toc}}` (rendered TOC for current page)
|
||||
|
||||
### 12.8 Multi-wiki (Phase 17)
|
||||
|
||||
#### Config shape
|
||||
|
||||
```lua
|
||||
require('nuwiki').setup({
|
||||
wikis = {
|
||||
{
|
||||
name = 'personal',
|
||||
root = '~/vimwiki',
|
||||
file_extension = '.wiki',
|
||||
syntax = 'vimwiki',
|
||||
diary_rel_path = 'diary',
|
||||
html_path = '~/vimwiki/_html',
|
||||
-- … any per-wiki option
|
||||
},
|
||||
{
|
||||
name = 'work',
|
||||
root = '~/work-notes',
|
||||
syntax = 'vimwiki',
|
||||
},
|
||||
},
|
||||
log_level = 'warn',
|
||||
})
|
||||
```
|
||||
|
||||
The v1.0 single-wiki shape continues to work; internally it desugars to
|
||||
`wikis = [{ root = wiki_root, file_extension = file_extension, syntax = syntax }]`.
|
||||
|
||||
#### Per-wiki context
|
||||
|
||||
`WorkspaceIndex` becomes one per wiki. Backend holds:
|
||||
|
||||
```
|
||||
indexes: Arc<DashMap<WikiId, Arc<RwLock<WorkspaceIndex>>>>
|
||||
```
|
||||
|
||||
URI → wiki resolution walks the URI's filesystem path upward, matching
|
||||
against each registered root. Cross-wiki links (interwiki) resolve through
|
||||
the matching wiki's index.
|
||||
|
||||
#### Custom commands
|
||||
|
||||
| Command | Behaviour |
|
||||
|---|---|
|
||||
| `nuwiki.wiki.select` | client-side picker over `wikis`; resolves to a wiki id |
|
||||
| `nuwiki.wiki.openIndex` | open the selected wiki's `index.wiki` |
|
||||
| `nuwiki.wiki.tabOpenIndex` | open in new tab (client-side) |
|
||||
| `nuwiki.wiki.listAll` | returns the registered wikis for editor UIs |
|
||||
|
||||
### 12.9 Editor glue v2 (Phase 18)
|
||||
|
||||
The thickest user-facing layer. Per SPEC §6.3 it still contains no logic —
|
||||
every command body is a wrapper that issues `workspace/executeCommand`.
|
||||
|
||||
#### `:Vimwiki*` command compatibility
|
||||
|
||||
`ftplugin/nuwiki.vim` defines every command listed in §4 of vimwiki's help,
|
||||
mapped to the corresponding `executeCommand`:
|
||||
|
||||
| Vimwiki command | nuwiki implementation |
|
||||
|---|---|
|
||||
| `:VimwikiIndex` `[count]` | `nuwiki.wiki.openIndex(count)` |
|
||||
| `:VimwikiTabIndex` | tab-open variant |
|
||||
| `:VimwikiUISelect` | `nuwiki.wiki.select` |
|
||||
| `:VimwikiDiaryIndex` | `nuwiki.diary.openIndex` |
|
||||
| `:VimwikiMakeDiaryNote` | `nuwiki.diary.openToday` |
|
||||
| `:VimwikiMakeYesterdayDiaryNote` | `nuwiki.diary.openYesterday` |
|
||||
| `:VimwikiMakeTomorrowDiaryNote` | `nuwiki.diary.openTomorrow` |
|
||||
| `:VimwikiFollowLink` | client `vim.lsp.buf.definition()` |
|
||||
| `:VimwikiGoBackLink` | client `<C-o>` (jumplist) |
|
||||
| `:VimwikiSplitLink` / `:VimwikiVSplitLink` | client-side `:split`/`:vsplit` + `definition` |
|
||||
| `:VimwikiTabnewLink` / `:VimwikiTabDropLink` | client-side `:tabnew` + `definition` |
|
||||
| `:VimwikiNextLink` / `:VimwikiPrevLink` | `nuwiki.cursor.nextLink` / `prevLink` |
|
||||
| `:VimwikiGoto {name}` | `nuwiki.wiki.gotoPage(name)` |
|
||||
| `:VimwikiDeleteFile` | server-side delete via `executeCommand` |
|
||||
| `:VimwikiRenameFile` | client prompt → `workspace/rename` |
|
||||
| `:VimwikiRemoveDone` | `nuwiki.list.removeDone` |
|
||||
| `:VimwikiNextTask` | `nuwiki.list.nextTask` |
|
||||
| `:Vimwiki2HTML` | `nuwiki.export.currentToHtml` |
|
||||
| `:Vimwiki2HTMLBrowse` | `nuwiki.export.browse` |
|
||||
| `:VimwikiAll2HTML[!]` | `nuwiki.export.allToHtml[Force]` |
|
||||
| `:VimwikiRss` | `nuwiki.export.rss` |
|
||||
| `:VimwikiToggleListItem` | `nuwiki.list.toggleCheckbox` |
|
||||
| `:VimwikiToggleRejectedListItem` | `nuwiki.list.rejectCheckbox` |
|
||||
| `:VimwikiListChangeLvl CMD` | `nuwiki.list.changeLevel` / `changeSymbol` |
|
||||
| `:VimwikiSearch` / `:VWS` | client `:lvimgrep` wrapper over wiki root |
|
||||
| `:VimwikiBacklinks` / `:VWB` | client `vim.lsp.buf.references()` |
|
||||
| `:VimwikiTable [cols] [rows]` | `nuwiki.table.insert` |
|
||||
| `:VimwikiTableMoveColumnLeft/Right` | `nuwiki.table.moveColumn` |
|
||||
| `:VimwikiGenerateLinks` | `nuwiki.links.generate` |
|
||||
| `:VimwikiDiaryGenerateLinks` | `nuwiki.diary.generateIndex` |
|
||||
| `:VimwikiDiaryNextDay` / `:VimwikiDiaryPrevDay` | `nuwiki.diary.next/prev` |
|
||||
| `:VimwikiTOC` | `nuwiki.toc.generate` |
|
||||
| `:VimwikiCheckLinks` | `nuwiki.workspace.checkLinks` |
|
||||
| `:VimwikiRebuildTags` | `nuwiki.tags.rebuild` |
|
||||
| `:VimwikiSearchTags {tag}` | `nuwiki.tags.search` |
|
||||
| `:VimwikiGenerateTagLinks` | `nuwiki.tags.generateLinks` |
|
||||
| `:VimwikiColorize {color}` | `nuwiki.colorize` |
|
||||
| `:VimwikiPasteLink` | `nuwiki.link.pasteWikilink` |
|
||||
| `:VimwikiPasteUrl` | `nuwiki.link.pasteUrl` |
|
||||
|
||||
Each `:Vimwiki*` form ships with a matching `:Nuwiki*` alias (P10
|
||||
resolution).
|
||||
|
||||
#### Default keymaps
|
||||
|
||||
`g:nuwiki_key_mappings` (Vim) / `mappings = { … }` (Neovim) controls
|
||||
opt-in keymap registration. Default: enabled; group flags let users disable
|
||||
the table/list/heading/diary subsets independently.
|
||||
|
||||
Buffer-local maps mirror vimwiki:
|
||||
|
||||
- `<Leader>ww` / `<Leader>wt` / `<Leader>ws` / `<Leader>wi` /
|
||||
`<Leader>w<Leader>w` etc. — wiki navigation
|
||||
- `<CR>` / `<S-CR>` / `<C-CR>` / `<M-CR>` / `<C-S-CR>` — link follow variants
|
||||
- `<Backspace>` / `<Tab>` / `<S-Tab>` — link history + per-page link navigation
|
||||
- `=` / `-` / `[[` / `]]` / `[=` / `]=` / `]u` / `[u` — header manipulation +
|
||||
navigation (pure VimL/Lua, regex over current buffer — no LSP round-trip)
|
||||
- `+` — `nuwiki.link.normalize`
|
||||
- `<C-Space>` — `nuwiki.list.toggleCheckbox`
|
||||
- `gnt` — `nuwiki.list.nextTask`
|
||||
- `gl<Space>` / `gL<Space>` — checkbox remove (single / list)
|
||||
- `gln` / `glp` — checkbox cycle up/down
|
||||
- `gll` / `gLl` / `glh` / `gLh` — list level change (single / subtree)
|
||||
- `glr` / `gLr` — list renumber
|
||||
- `gl*` / `gl#` / `gl-` / `gl+` / `gl1` / `gla` / `glA` / `gli` / `glI` —
|
||||
list symbol change (single / subtree variants `gL`*)
|
||||
- `glx` — `:VimwikiToggleRejectedListItem`
|
||||
- `gqq` / `gww` / `gq1` / `gw1` — table align
|
||||
- `<A-Left>` / `<A-Right>` — table move column
|
||||
- `<C-Up>` / `<C-Down>` — diary prev/next day
|
||||
- `<Leader>wh` / `<Leader>whh` — HTML export current / browse
|
||||
- `<Leader>wc` — colorize (asks for colour)
|
||||
- `<Leader>wn` — goto/create new page
|
||||
- `<Leader>wd` / `<Leader>wr` — delete / rename current page
|
||||
- Mouse: `<2-LeftMouse>`, `<S-2-LeftMouse>`, `<C-2-LeftMouse>`,
|
||||
`<RightMouse><LeftMouse>` (opt-in via `g:nuwiki_mouse_mappings`)
|
||||
|
||||
#### Insert-mode behaviour
|
||||
|
||||
- Table cells: `<CR>`/`<Tab>`/`<S-Tab>` navigate cells, create rows
|
||||
on overflow; implemented in Lua/VimL via a small autocmd
|
||||
- Lists: `<CR>` inserts the next bullet/number; `<S-CR>` continues without
|
||||
a new bullet; `<C-T>`/`<C-D>` indent/dedent; `<C-L><C-J>`/`<C-L><C-K>`
|
||||
cycle the list symbol; `<C-L><C-M>` toggles a list item on/off
|
||||
- All gated by `b:did_ftplugin` and remappable
|
||||
|
||||
#### Text objects
|
||||
|
||||
`omap`/`xmap` defining:
|
||||
|
||||
| Object | Selects |
|
||||
|---|---|
|
||||
| `ah` / `ih` | a header (with/without trailing blank lines + header line itself) |
|
||||
| `aH` / `iH` | a header + all sub-headers ([count] climbs parent levels) |
|
||||
| `a\` / `i\` | a table cell |
|
||||
| `ac` / `ic` | a table column |
|
||||
| `al` / `il` | a list item (with/without children) |
|
||||
|
||||
Pure VimL/Lua — no LSP round-trip. Reuses our AST-shaped regexes.
|
||||
|
||||
#### Folding
|
||||
|
||||
Per P14 resolution; the spec'd default (subject to that decision):
|
||||
|
||||
- `setlocal foldmethod=expr` + `foldexpr=NuwikiFold(v:lnum)` (or LSP
|
||||
`foldingRange` driving it on Neovim 0.11+)
|
||||
- Folds at heading boundaries; nested headings nest folds
|
||||
- List-item folds when configured via `g:nuwiki_folding = 'list'`
|
||||
- Custom variant via `g:nuwiki_folding = 'custom'`
|
||||
|
||||
#### Health check additions
|
||||
|
||||
`:checkhealth nuwiki` v1.1 reports:
|
||||
|
||||
- LSP commands registered (per command name)
|
||||
- Index loaded for each registered wiki
|
||||
- Tags table built
|
||||
- HTML output path writable
|
||||
- Default keymaps installed (or disabled by config)
|
||||
|
||||
### 12.10 Updated user-config schema
|
||||
|
||||
```lua
|
||||
require('nuwiki').setup({
|
||||
-- single-wiki shorthand (v1.0 compat)
|
||||
wiki_root = '~/vimwiki',
|
||||
file_extension = '.wiki',
|
||||
syntax = 'vimwiki',
|
||||
log_level = 'warn',
|
||||
|
||||
-- or the v1.1 multi-wiki form
|
||||
wikis = {
|
||||
{
|
||||
name = 'personal',
|
||||
root = '~/vimwiki',
|
||||
file_extension = '.wiki',
|
||||
syntax = 'vimwiki',
|
||||
diary_rel_path = 'diary',
|
||||
diary_frequency = 'daily', -- daily | weekly | monthly | yearly
|
||||
diary_start_week_day = 'monday',
|
||||
template_path = '~/vimwiki/_templates',
|
||||
template_default = 'default',
|
||||
template_ext = '.tpl',
|
||||
css_name = 'style.css',
|
||||
html_path = '~/vimwiki/_html',
|
||||
auto_export = false,
|
||||
auto_toc = false,
|
||||
auto_tags = false,
|
||||
exclude_files = {},
|
||||
bullet_types = { '-', '*', '#' },
|
||||
listsyms = ' .oOX',
|
||||
listsym_rejected = '-',
|
||||
listsyms_propagate = true,
|
||||
color_dic = { red = 'red', green = 'green' },
|
||||
},
|
||||
},
|
||||
|
||||
-- workspace-wide behaviour
|
||||
diagnostic = {
|
||||
link_severity = 'warn', -- off | hint | warn | error
|
||||
},
|
||||
mappings = {
|
||||
enabled = true,
|
||||
table_editing = true,
|
||||
list_editing = true,
|
||||
header_nav = true,
|
||||
diary = true,
|
||||
html_export = true,
|
||||
mouse = false,
|
||||
},
|
||||
folding = 'syntax', -- off | syntax | list | custom
|
||||
})
|
||||
```
|
||||
|
||||
### 12.11 Updated §9 syntax checklist (additions)
|
||||
|
||||
The following items extend the v1.0 checklist:
|
||||
|
||||
#### Tags
|
||||
- [ ] Inline tag sequence: `:tag-one:tag-two:`
|
||||
- [ ] File-level tag (line 1–2 of a wiki page)
|
||||
- [ ] Header-level tag (within 2 lines after a heading)
|
||||
- [ ] Tag-as-anchor target (`[[Page#some-tag]]`)
|
||||
- [ ] Hex-colour code rendering in code blocks (`` `#ffe119` ``)
|
||||
|
||||
#### Tables (additions)
|
||||
- [ ] Column-alignment markers in header separator: `|:--|` / `|:--:|` / `|--:|`
|
||||
|
||||
#### Lists (parser extensions)
|
||||
- [ ] Multi-line list item (indented continuation lines)
|
||||
- [ ] Mixed-symbol lists at the same level
|
||||
|
||||
### 12.12 Updated CI/CD
|
||||
|
||||
No new workflow files. The existing `ci.yaml` continues to gate
|
||||
`fmt`/`clippy`/`test`. New phases land behind feature additions in the
|
||||
existing crates; the test suite grows accordingly.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user