summaryrefslogtreecommitdiffstats
path: root/.config/nvim/after/ftplugin/markdown.lua
diff options
context:
space:
mode:
authorThomas Vanbesien <tvanbesi@proton.me>2026-05-18 23:43:22 +0200
committerThomas Vanbesien <tvanbesi@proton.me>2026-05-18 23:43:22 +0200
commit927c59b16ab2685431a9cdc9c17112b9c366b390 (patch)
treec9ab4a588a756850b91ba01a0c08a523d2042320 /.config/nvim/after/ftplugin/markdown.lua
parenta9a3a7af754f370e6d4a045523d8dbeef2d3cbfa (diff)
downloaddotfiles-927c59b16ab2685431a9cdc9c17112b9c366b390.tar.gz
dotfiles-927c59b16ab2685431a9cdc9c17112b9c366b390.zip
fix(nvim): MarkdownListCheck/Uncheck work on multi-line items
Diffstat (limited to '.config/nvim/after/ftplugin/markdown.lua')
-rw-r--r--.config/nvim/after/ftplugin/markdown.lua85
1 files changed, 73 insertions, 12 deletions
diff --git a/.config/nvim/after/ftplugin/markdown.lua b/.config/nvim/after/ftplugin/markdown.lua
index 160b6cc..c7be170 100644
--- a/.config/nvim/after/ftplugin/markdown.lua
+++ b/.config/nvim/after/ftplugin/markdown.lua
@@ -71,26 +71,87 @@ vim.api.nvim_set_hl(0, "@markup.link.label.markdown_inline", { underline = true,
vim.b.autoformat = true
vim.b.format_func = format
+local function item_range()
+ local cursor_row = vim.api.nvim_win_get_cursor(0)[1]
+ local lines = vim.api.nvim_buf_get_lines(0, 0, -1, false)
+
+ -- Walk up to the task bullet. Any other bullet, or a line that's neither
+ -- blank nor indented, means we're not inside a task item.
+ local start_row = cursor_row
+ while start_row >= 1 do
+ local line = lines[start_row]
+ if line:match("^%s*%- %[[ Xx]%] ") then
+ break
+ end
+ if line:match("^%s*%- ") then
+ return nil
+ end
+ if not (line:match("^%s*$") or line:match("^%s+%S")) then
+ return nil
+ end
+ start_row = start_row - 1
+ end
+ if start_row < 1 then
+ return nil
+ end
+
+ -- Walk down through continuation paragraphs. Blank lines are inside the
+ -- item as long as a later line is still indented to the content column.
+ local bullet_indent = #lines[start_row]:match("^(%s*)")
+ local cont_min = bullet_indent + 2
+ local end_row = start_row
+ for r = start_row + 1, #lines do
+ local line = lines[r]
+ if line:match("^%s*$") then
+ -- blank, keep scanning
+ elseif line:match("^%s*%- ") then
+ break
+ elseif #line:match("^(%s*)") < cont_min then
+ break
+ else
+ end_row = r
+ end
+ end
+
+ return start_row, end_row
+end
+
local function check_checklist_item()
- local line = vim.api.nvim_get_current_line()
- if line:match("^%s*%- %[ %] ") == nil then
+ local start_row, end_row = item_range()
+ if not start_row then
+ return
+ end
+ local lines = vim.api.nvim_buf_get_lines(0, start_row - 1, end_row, false)
+ if not lines[1]:match("^%s*%- %[ %] ") then
return
end
- local edited_line = line:gsub("%[ %]", "[X]", 1)
- edited_line = edited_line:gsub("^(%s*%- %[X%] )(.*)", "%1~%2~", 1)
- local start = vim.api.nvim_win_get_cursor(0)[1] - 1
- vim.api.nvim_buf_set_lines(0, start, start + 1, false, { edited_line })
+ for i, line in ipairs(lines) do
+ if i == 1 then
+ lines[i] = line:gsub("^(%s*%- )%[ %] (.-)(%s*\\?)$", "%1[X] ~%2~%3", 1)
+ elseif not line:match("^%s*$") then
+ lines[i] = line:gsub("^(%s*)(.-)(%s*\\?)$", "%1~%2~%3", 1)
+ end
+ end
+ vim.api.nvim_buf_set_lines(0, start_row - 1, end_row, false, lines)
end
local function uncheck_checklist_item()
- local line = vim.api.nvim_get_current_line()
- if line:match("^%s*%- %[X%] ") == nil then
+ local start_row, end_row = item_range()
+ if not start_row then
return
end
- local edited_line = line:gsub("%[X%]", "[ ]", 1)
- edited_line = edited_line:gsub("~", "", 2)
- local start = vim.api.nvim_win_get_cursor(0)[1] - 1
- vim.api.nvim_buf_set_lines(0, start, start + 1, false, { edited_line })
+ local lines = vim.api.nvim_buf_get_lines(0, start_row - 1, end_row, false)
+ if not lines[1]:match("^%s*%- %[X%] ") then
+ return
+ end
+ for i, line in ipairs(lines) do
+ if i == 1 then
+ lines[i] = line:gsub("%[X%]", "[ ]", 1):gsub("~", "", 2)
+ elseif not line:match("^%s*$") then
+ lines[i] = line:gsub("~", "", 2)
+ end
+ end
+ vim.api.nvim_buf_set_lines(0, start_row - 1, end_row, false, lines)
end
vim.api.nvim_buf_create_user_command(0, "MarkdownListCheck", check_checklist_item, { desc = "Check checklist item" })