diff options
| author | Thomas Vanbesien <tvanbesi@proton.me> | 2026-05-18 23:43:22 +0200 |
|---|---|---|
| committer | Thomas Vanbesien <tvanbesi@proton.me> | 2026-05-18 23:43:22 +0200 |
| commit | 927c59b16ab2685431a9cdc9c17112b9c366b390 (patch) | |
| tree | c9ab4a588a756850b91ba01a0c08a523d2042320 /.config/nvim/after/ftplugin/markdown.lua | |
| parent | a9a3a7af754f370e6d4a045523d8dbeef2d3cbfa (diff) | |
| download | dotfiles-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.lua | 85 |
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" }) |
