summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Soarez <igor@soarez.org>2026-10-07 19:24:51 +0300
committerIgor Soarez <igor@soarez.org>2026-10-07 19:24:51 +0300
commitfdaf6742b0823b088c58ac8e26f6556a0c12c43f (patch)
tree430247857d520bc18e6e7fbb43d8b84d0b92d719
parent6c97cb32cb21beb265a3d5b2b72a92aed52f9040 (diff)
nvim: render markdown in the buffer
render-markdown.nvim draws headings, code blocks, tables and checkboxes in place, in the one buffer, and leaves the cursor line raw so editing is unaffected; <leader>mt toggles it. The markdown and markdown_inline parsers join the install list, which also gives noice's LSP hover rendering the parsers it was already set up to use. None of the colourschemes here define the @markup.heading.N.markdown captures the plugin colours headings from, so every level rendered alike. A ramp fills them in, only where the theme left the group empty, and again on each theme switch. Checked with the real config: 26 marks on a test file, conceallevel 3, H1-H3 in distinct bold colours. AGENTS.md also stops listing nvim as having no machine-local hook: lua/local.lua is one, gitignored and loaded by cfg-watch after the plugins. From change request 12882c.
-rw-r--r--AGENTS.md3
-rw-r--r--config/nvim/lua/plugins/lsp.lua1
-rw-r--r--config/nvim/lua/plugins/markdown.lua73
3 files changed, 76 insertions, 1 deletions
diff --git a/AGENTS.md b/AGENTS.md
index 4cbdd1d..611a1cd 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -172,13 +172,14 @@ tracked config says so, and in no repo:
| `~/.config/git/config-local` | git, this host only -- the work identity, `includeIf` blocks. See `config/git/config-local-example` | `config/git/config`, after the `[user]` block above it, and git takes the last value |
| `~/.config/hammerspoon/local.lua` | Hammerspoon: rebinding a hotkey set here shadows it, and `capslock_off()` gives this machine its Caps Lock back. `require("dotlib")` for the same helpers init.lua uses. See `config/hammerspoon/local-example.lua` | `config/hammerspoon/init.lua`, last, in a `pcall` |
| `~/.tmux.conf.local` | tmux, this host only: loaded last, so it can override anything, colours included | `config/tmux.conf`, last, with `source-file -q` |
+| `~/.config/nvim/lua/local.lua` | Neovim, this host only: any Lua, run after the plugins have loaded. Through the `~/.config/nvim/lua` link it sits in this checkout, gitignored there | `lua/plugins/reload.lua`, via cfg-watch, at VeryLazy; created empty when missing |
| `~/.config/ghostty-local` | Ghostty: later values replace earlier ones, `keybind` accumulates. See `config/ghostty/ghostty-local-example` | `config/ghostty/config`, last, as an optional `config-file` |
| `~/.local/share/alacritty/local.toml` | Alacritty. To change the mux a window opens in, `[terminal] shell = "/path/to/launcher"` -- the string form, since a `[terminal.shell]` table appends its args to the default's. See `config/alacritty/mux.toml` | imported by `config/alacritty/alacritty.toml`, after `mux.toml` |
| `~/.config/dot/skip` | which `link/` parts this machine does not want, one name per line | `link/lib.sh`, as each part starts |
| `~/.config/dot/inbox-key` | the key this machine signs change requests with | `bin/dot-request` |
| `~/.config/pi/models.d/*.json` | pi providers only this machine has -- a model served somewhere other than a vendor's own API | `link/pi.sh`, merged over `config/pi/models.json` |
-Not covered today: nvim, bat, lsd, and `~/.claude/settings.json` -- which
+Not covered today: bat, lsd, and `~/.claude/settings.json` -- which
a machine can only leave alone entirely, by naming `claude` in the skip file.
**When a request is not covered by the table, say so rather than editing a
diff --git a/config/nvim/lua/plugins/lsp.lua b/config/nvim/lua/plugins/lsp.lua
index c3853b3..1470177 100644
--- a/config/nvim/lua/plugins/lsp.lua
+++ b/config/nvim/lua/plugins/lsp.lua
@@ -128,6 +128,7 @@ return {
local TS = require("nvim-treesitter")
local ensure_installed = {
"astro", "go", "html", "javascript", "lua", "python", "tsx", "typescript",
+ "markdown", "markdown_inline",
}
local installed = TS.get_installed("parsers")
local to_install = vim.tbl_filter(function(lang)
diff --git a/config/nvim/lua/plugins/markdown.lua b/config/nvim/lua/plugins/markdown.lua
new file mode 100644
index 0000000..b298554
--- /dev/null
+++ b/config/nvim/lua/plugins/markdown.lua
@@ -0,0 +1,73 @@
+-- In-buffer markdown rendering: headings, code blocks, tables, callouts and
+-- checkboxes rendered in place, in the one buffer. No preview window or split.
+-- The cursor line keeps its raw syntax (the plugin's anti_conceal), so editing
+-- is unaffected. <leader>mt toggles rendering for the current buffer.
+return {
+ {
+ "MeanderingProgrammer/render-markdown.nvim",
+ ft = { "markdown" },
+ dependencies = { "nvim-tree/nvim-web-devicons" },
+ opts = {},
+ config = function(_, opts)
+ require("render-markdown").setup(opts)
+
+ -- render-markdown takes its per-level heading colours from the
+ -- treesitter captures @markup.heading.{1..6}.markdown. None of the
+ -- colourschemes under config/nvim/colors/ define treesitter groups
+ -- at all -- happy_hacking, onehalfdark and ayu were each checked --
+ -- so those captures resolve to nothing and every heading level
+ -- renders with no colour. Supply a ramp, but only where the theme
+ -- left the group undefined, so a theme that does define them keeps
+ -- its own. Re-applied on ColorScheme, since cfg-watch switches the
+ -- theme at runtime and `:colorscheme` can clear highlight groups.
+ local ramps = {
+ dark = {
+ { "#F3F2CC", 230 },
+ { "#FAD566", 221 },
+ { "#B3EBBF", 157 },
+ { "#81A2C7", 103 },
+ { "#F77EBD", 211 },
+ { "#fcb280", 179 },
+ },
+ light = {
+ { "#2F2F2F", 236 },
+ { "#8C6D1F", 136 },
+ { "#3F6B3F", 22 },
+ { "#3A5A8C", 24 },
+ { "#8C3A6B", 89 },
+ { "#8C5A2F", 130 },
+ },
+ }
+ local function set_heading_colors()
+ local ramp = ramps[vim.o.background] or ramps.dark
+ for level = 1, 6 do
+ local name = "RenderMarkdownH" .. level
+ -- Put render-markdown's own link back first, so a theme that
+ -- does define the capture wins, and so this stays correct
+ -- after a theme switch.
+ vim.api.nvim_set_hl(0, name, { link = "@markup.heading." .. level .. ".markdown" })
+ local hl = vim.api.nvim_get_hl(0, { name = name })
+ if not (hl.fg or hl.bg or hl.bold or hl.italic or hl.underline) then
+ vim.api.nvim_set_hl(0, name, {
+ fg = ramp[level][1],
+ ctermfg = ramp[level][2],
+ bold = true,
+ })
+ end
+ end
+ end
+ set_heading_colors()
+ vim.api.nvim_create_autocmd("ColorScheme", { callback = set_heading_colors })
+
+ vim.api.nvim_create_autocmd("FileType", {
+ pattern = "markdown",
+ callback = function(event)
+ vim.keymap.set("n", "<leader>mt", "<cmd>RenderMarkdown buf_toggle<cr>", {
+ buffer = event.buf,
+ desc = "Toggle markdown rendering",
+ })
+ end,
+ })
+ end,
+ },
+}