# Testing Neovim

> Test markdown-oxide LSP features in Neovim Use when this capability is needed.

- Skill: `tomevault-io/testing-neovim` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/testing-neovim`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/testing-neovim/raw
- Safety review: pending (external: skill-scanner WARNING, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/testing-neovim

---


# Test Markdown-Oxide in Neovim

## Overview
markdown-oxide is an LSP server for markdown/Obsidian vaults. It cannot be tested via browser or direct CLI invocation -- it requires an editor with LSP support. Neovim v0.11+ is the recommended testing environment.

## Outcome

Verify that markdown-oxide LSP features work correctly in Neovim, including wiki link completions, block linking (with block ID insertion via `:wall`), go-to-definition, hover with backlinks, and tag completions against the `TestFiles/` directory. Testing is done in two recorded phases: first reproduce/demonstrate the current behavior, then validate the fix or expected behavior.

## Procedure

### 1. Build the markdown-oxide binary

```bash
cd ~/repos/markdown-oxide && cargo build
sudo cp target/debug/markdown-oxide /usr/local/bin/markdown-oxide
```

Verify it's on PATH: `which markdown-oxide`

For release builds (slower but optimized): `cargo build --release` then copy from `target/release/`.

### 2. Install Neovim (if not installed)

```bash
curl -fsSL -o /tmp/nvim.appimage https://github.com/neovim/neovim/releases/latest/download/nvim-linux-x86_64.appimage
chmod +x /tmp/nvim.appimage
cd /tmp && /tmp/nvim.appimage --appimage-extract
sudo mv /tmp/squashfs-root /opt/nvim
sudo ln -sf /opt/nvim/usr/bin/nvim /usr/local/bin/nvim
```

Verify: `nvim --version | head -1` (should be v0.11+)

On headless/VM environments, the AppImage may fail with FUSE errors. Use `--appimage-extract` to extract without FUSE.

### 3. Configure Neovim for markdown-oxide

Create `~/.config/nvim/init.lua`:

```lua
-- Minimal Neovim config for testing markdown-oxide LSP
vim.opt.number = true
vim.opt.signcolumn = "yes"
vim.opt.completeopt = { "menu", "menuone", "noselect" }

vim.lsp.config('markdown_oxide', {
  cmd = { 'markdown-oxide' },
  filetypes = { 'markdown' },
  root_markers = { '.obsidian', '.moxide.toml', '.git' },
  capabilities = {
    workspace = {
      didChangeWatchedFiles = {
        dynamicRegistration = true,
      },
    },
  },
})

vim.lsp.enable('markdown_oxide')

vim.api.nvim_create_autocmd('LspAttach', {
  callback = function(args)
    local opts = { buffer = args.buf }
    vim.keymap.set('n', 'gd', vim.lsp.buf.definition, opts)
    vim.keymap.set('n', 'gr', vim.lsp.buf.references, opts)
    vim.keymap.set('n', 'K', vim.lsp.buf.hover, opts)
    vim.keymap.set('n', '<leader>rn', vim.lsp.buf.rename, opts)
    vim.keymap.set('n', '<leader>ca', vim.lsp.buf.code_action, opts)
    vim.keymap.set('i', '<C-Space>', function()
      vim.lsp.completion.trigger()
    end, opts)
    vim.lsp.completion.enable(true, args.data.client_id, args.buf, { autotrigger = true })

    local client = vim.lsp.get_client_by_id(args.data.client_id)
    if client and client.name == "markdown_oxide" then
      vim.api.nvim_create_user_command("Daily", function(cmd_args)
        vim.lsp.buf.execute_command({ command = "jump", arguments = { cmd_args.args } })
      end, { desc = "Open daily note", nargs = "*" })
    end
  end,
})
```

This uses Neovim 0.11+ built-in LSP support (`vim.lsp.config` / `vim.lsp.enable`). The `dynamicRegistration = true` setting is critical for block linking to work.

### 4. Launch Neovim

Open a terminal emulator (e.g., `konsole`) and launch Neovim on TestFiles:

```bash
konsole --workdir ~/repos/markdown-oxide/TestFiles -e bash -c "nvim Test.md" &
```

Wait for Neovim to open and the LSP to attach. Verify with: `pgrep -a markdown-oxide`

### 5. Test LSP features

Testing is split into two recorded phases:

#### Phase 1: Reproduce current behavior

Start a screen recording (`recording_start`). Demonstrate the current state of each feature **before any fix**. This establishes a baseline and captures any issues:

- Annotate the recording: "Phase 1: Reproducing current behavior in Neovim"
- Exercise each feature below and note what works and what doesn't
- Stop the recording (`recording_stop`) when done

#### Phase 2: Validate the fix

After applying the fix (rebuild markdown-oxide, copy to PATH, quit and relaunch Neovim to restart the LSP):

- Start a new screen recording (`recording_start`)
- Annotate the recording: "Phase 2: Validating fix in Neovim"
- Re-test each feature and confirm it works correctly
- Stop the recording (`recording_stop`) when done

Test each feature:

#### Wiki Link Completions
- In Normal mode, press `G` to go to end of file, then `o` to open a new line
- Type `[[` -- a completion menu should appear with files, headings, and blocks
- Type to fuzzy-filter (e.g., `[[Reso` should show "Resolved File")
- Press `Escape` and `u` to undo when done

#### Block Linking (CRITICAL Neovim-specific feature)
- Press `o` to open a new line in insert mode
- Type `[[ ` (two brackets then a space) -- this triggers the unindexed block completer
- A list of text blocks from across the vault appears
- Type to fuzzy-filter (e.g., `test file with some`)
- Use `Ctrl+n`/`Ctrl+p` to navigate, `Ctrl+y` to accept
- After accepting, a link like `[[Another Test 2#^f311g|text]]` is inserted with a generated block ID
- **You MUST run `:wall` to write all buffers** -- the block ID is inserted into the target file as an unsaved buffer edit
- Verify the block ID was inserted: check the target file for the `^blockid` suffix

#### Go-to-Definition
- Navigate to a line with `[[This is another link]]` (around line 31)
- Position cursor inside the link text (e.g., `fT` to find the `T`)
- Press `gd` -- should navigate to `This is another link.md`
- Press `Ctrl+o` to go back

#### Hover
- With cursor on a wiki link like `[[This is another link]]`
- Press `K` (Shift+k) -- a hover popup should show:
  - **File Preview**: contents of the linked file
  - **Backlinks**: all files referencing this entity
- Press `Escape` or any key to dismiss

#### Tag Completions
- Press `o` to open a new line, type `#ta`
- Should show hierarchical tags: `tag`, `tag/subtag`, `tag/othersubtag`, `mapofcontent/tag`, etc.
- Press `Escape` and `u` to undo when done

#### References (optional)
- Place cursor on a heading like `# Heading 1`
- Press `gr` to find all references/backlinks

#### Testing Heading Links Specifically
- Heading links with dashes (`[[File#My-Heading]]`) should resolve correctly
- Heading links with spaces (`[[File#My Heading]]`) should also resolve (lenient matching)
- Completions for headings show dash-separated format only when `heading_slug` config is true
- Test headings in `TestFiles/Test.md`: `# Heading 1`, `## Here is a nested`, `### Here is a nested third`
- Test cross-file heading links using `TestFiles/Resolved File.md` which has `# Resolved Heading`

### 6. Post recordings to PR

After both recording phases are complete, post the recordings as comments on the PR:

1. Use `git_comment_on_pr` to post the Phase 1 recording with a comment like:
   > **Phase 1: Reproducing current behavior in Neovim**
   > ![Phase 1 recording](/path/to/phase1-recording.mp4)

2. Use `git_comment_on_pr` to post the Phase 2 recording with a comment like:
   > **Phase 2: Validating fix in Neovim**
   > ![Phase 2 recording](/path/to/phase2-recording.mp4)

This provides reviewers with visual evidence of the issue and its resolution.

### 7. Clean up

Undo any test edits: `Escape`, then `u` repeatedly until "Already at oldest change".
Quit without saving: `:qa!`

## Available Test Files

- `TestFiles/Test.md` -- Main test file with headings, wiki links, block refs, tags
- `TestFiles/Resolved File.md` -- Has `# Resolved Heading` and heading links
- `TestFiles/Another Test.md` -- Has `# This is a test heading` and `## This is a nested test heading`
- `TestFiles/This is another link.md` -- Target for wiki link navigation tests

## Specifications

- Wiki link completions must show files, headings, and block references
- Block linking must insert a `^blockid` into the target file after `:wall`
- Go-to-definition must navigate to the correct target file
- Hover must show file preview and backlinks
- Tag completions must show hierarchical tags
- The LSP server process (`markdown-oxide`) must be running (verify with `pgrep`)
- Two screen recordings must be produced: one showing current behavior (reproduce), one showing the fix (validate)
- Both recordings must be posted as comments on the PR

## Advice

- Neovim 0.11+ is required for `vim.lsp.config` / `vim.lsp.enable`. Older versions need `nvim-lspconfig` plugin.
- The `dynamicRegistration = true` capability is essential for block linking and the "Create Unresolved File" code action to work.
- On headless/VM environments, the AppImage may fail with FUSE errors. Use `--appimage-extract` to extract without FUSE.
- Block completions are triggered by `[[ ` (with a space after `[[`). Without the space, you get regular file/heading completions.
- After accepting a block completion, the block ID is edited into the target file's buffer but NOT saved. You must run `:wall` to persist it.
- For a richer completion UI, install `nvim-cmp` with `cmp-nvim-lsp`. The built-in `vim.lsp.completion` works but `nvim-cmp` provides better UX.
- Use `:LspLog` to inspect LSP communication for debugging.
- After rebuilding the binary, you must quit Neovim and relaunch to restart the LSP (or copy binary while LSP is running and it may pick up changes).
- Neovim's built-in completion can be slow to trigger -- use `Ctrl+Space` to force trigger.
- `cargo build` (debug) is much faster than `cargo build --release` -- use debug for testing iterations.

## Forbidden Actions

- Do not modify the TestFiles content permanently (undo all test edits)
- Do not force push or modify the main branch

---
> Source: [Feel-ix-343/markdown-oxide](https://github.com/Feel-ix-343/markdown-oxide) — distributed by [TomeVault](https://tomevault.io).
<!-- tomevault:4.0:skill_md:2026-06-22 -->

