feat(mini.pairs): smart Markdown code-fence expansion on 3rd backtick

Typing a 3rd backtick after mini.pairs' `` pair now expands into a fenced
code block instead of pairing into 4 backticks: the cursor lands right
after the opener (ready for a language id), and backspacing the fence
back out removes the empty closing fence too.

Also includes an already-in-progress .gitignore expansion (AGENTS/ and
agent-generated docs/ subdirs) and a plugins.lua tabs-to-spaces reformat
that were sitting uncommitted in the working tree.
This commit is contained in:
2026-08-24 22:01:49 -04:00
parent 1a1963232e
commit fc535b6688
3 changed files with 533 additions and 453 deletions
+13
View File
@@ -175,3 +175,16 @@ Thumbs.db
.[Rr][Ee][Mm][Ee][Mm][Bb][Ee][Rr] .[Rr][Ee][Mm][Ee][Mm][Bb][Ee][Rr]
# ────────────────────────────────────────────────────────────── # ──────────────────────────────────────────────────────────────
# ──────────────── Added by agents-init ──────────────────
# agents-init --agents
AGENTS/
# ────────────────────────────────────────────────────────
# ──────────────── Added by agents-init ──────────────────
# agents-init --plugins
docs/superpowers
docs/plans
docs/specs
docs/devlogs
# ────────────────────────────────────────────────────────
+2 -2
View File
@@ -14,7 +14,7 @@ A modern, modular, and high-performance Neovim configuration built from scratch
- **AI-Powered**: Native integration with **GitHub Copilot** — inline completions via **blink-copilot** and multi-line refactoring via **Sidekick.nvim** Next Edit Suggestions (NES). - **AI-Powered**: Native integration with **GitHub Copilot** — inline completions via **blink-copilot** and multi-line refactoring via **Sidekick.nvim** Next Edit Suggestions (NES).
- **User-Centric QoL**: Hybrid line numbers, autosave-on-edit, and seamless system clipboard integration. - **User-Centric QoL**: Hybrid line numbers, autosave-on-edit, and seamless system clipboard integration.
- **Resilient & Portable**: Intelligent terminal title management (Kitty + Fallback), automatic project root detection, and machine-local override support. - **Resilient & Portable**: Intelligent terminal title management (Kitty + Fallback), automatic project root detection, and machine-local override support.
- **Lean & Readable**: ~850 lines of Lua code (excluding comments and blanks). - **Lean & Readable**: ~980 lines of Lua code (excluding comments and blanks).
## 📁 Architecture ## 📁 Architecture
@@ -42,7 +42,7 @@ The configuration is strictly modular:
- **Focusline**: Keeps the active line at a configurable screen position (30%) during scrolling motions. - **Focusline**: Keeps the active line at a configurable screen position (30%) during scrolling motions.
- **Mini.ai**: Better text objects (including `g` for entire buffer). - **Mini.ai**: Better text objects (including `g` for entire buffer).
- **Mini.surround**: Surround text objects (add/delete/change). - **Mini.surround**: Surround text objects (add/delete/change).
- **Mini.pairs**: Auto-close brackets and quotes. - **Mini.pairs**: Auto-close brackets and quotes. In Markdown, a 3rd backtick expands `` `` `` into a fenced code block (cursor after the opener, ready for a language id) instead of pairing into 4 backticks; backspacing the fence back out removes the closing fence too.
- **Persistence**: Session management. - **Persistence**: Session management.
- **Which-key**: Interactive keybinding documentation. - **Which-key**: Interactive keybinding documentation.
- **Gitsigns**: In-buffer git indicators and line highlights. - **Gitsigns**: In-buffer git indicators and line highlights.
+68 -1
View File
@@ -188,6 +188,71 @@ lazyload.on_vim_enter(function()
vim.pack.add({ { src = "https://github.com/echasnovski/mini.pairs", name = "mini.pairs" } }) vim.pack.add({ { src = "https://github.com/echasnovski/mini.pairs", name = "mini.pairs" } })
require("mini.pairs").setup() require("mini.pairs").setup()
-- Smart backtick handling for Markdown: typing a 3rd backtick after an
-- existing `` `` `` pair expands into a fenced code block instead of
-- pairing into ```` ` ```` (4 backticks).
local function attach_markdown_smart_backtick(buf)
vim.keymap.set("i", "`", function()
local row, col = unpack(vim.api.nvim_win_get_cursor(0))
local line = vim.api.nvim_get_current_line()
local before, after = line:sub(1, col), line:sub(col + 1)
local disabled = vim.g.minipairs_disable == true or vim.b.minipairs_disable == true
if not disabled and before:sub(-2) == "``" and after:sub(1, 1) ~= "`" then
local prefix = before:sub(1, -3)
local indent = prefix:match("^%s*")
vim.api.nvim_set_current_line(prefix .. "```")
vim.api.nvim_buf_set_lines(0, row, row, false, { indent .. "```" .. after })
vim.api.nvim_win_set_cursor(0, { row, #prefix + 3 })
return
end
local keys = MiniPairs.closeopen("``", "^[^\\]")
vim.api.nvim_feedkeys(keys, "in", false)
end, { buffer = buf, desc = "Smart Markdown backtick / code fence" })
-- Deleting the opening fence's last backtick also removes the untouched
-- closing fence line it created, so undoing a fence is a clean backspace.
vim.keymap.set("i", "<BS>", function()
local row, col = unpack(vim.api.nvim_win_get_cursor(0))
local line = vim.api.nvim_get_current_line()
local before, after = line:sub(1, col), line:sub(col + 1)
local disabled = vim.g.minipairs_disable == true or vim.b.minipairs_disable == true
if not disabled and before:sub(-1) == "`" and before:sub(-2, -2) ~= "`" then
local prefix = before:sub(1, -2)
local indent = prefix:match("^%s*")
local next_line = vim.api.nvim_buf_get_lines(0, row, row + 1, false)[1]
if next_line == indent .. "```" then
vim.api.nvim_buf_set_lines(0, row, row + 1, false, {})
vim.api.nvim_set_current_line(prefix .. after)
vim.api.nvim_win_set_cursor(0, { row, #prefix })
return
end
end
local keys = MiniPairs.bs()
vim.api.nvim_feedkeys(keys, "in", false)
end, { buffer = buf, desc = "Smart Markdown fence backspace" })
end
vim.api.nvim_create_autocmd("FileType", {
group = vim.api.nvim_create_augroup("markdown_smart_backtick", { clear = true }),
pattern = "markdown",
desc = "Expand `` ` `` pair into a fenced code block on 3rd backtick",
callback = function(args)
attach_markdown_smart_backtick(args.buf)
end,
})
-- Catch buffers that already had their FileType event fire before this
-- deferred setup ran (e.g. `nvim file.md` opened directly at startup).
for _, buf in ipairs(vim.api.nvim_list_bufs()) do
if vim.bo[buf].filetype == "markdown" then
attach_markdown_smart_backtick(buf)
end
end
-- Gx.nvim -- Gx.nvim
vim.pack.add({ { src = "https://github.com/chrishrb/gx.nvim", name = "gx" } }) vim.pack.add({ { src = "https://github.com/chrishrb/gx.nvim", name = "gx" } })
---@diagnostic disable-next-line: missing-fields ---@diagnostic disable-next-line: missing-fields
@@ -284,7 +349,9 @@ lazyload.on_vim_enter(function()
vim.pack.add({ { src = "https://github.com/fang2hou/blink-copilot", name = "blink-copilot" } }) vim.pack.add({ { src = "https://github.com/fang2hou/blink-copilot", name = "blink-copilot" } })
-- 3. Blink.cmp setup -- 3. Blink.cmp setup
require("blink.cmp").setup({ local cmp = require('blink.cmp')
cmp.build():wait(60000)
cmp.setup({
keymap = { keymap = {
preset = "default", preset = "default",
["<Tab>"] = { ["<Tab>"] = {