From d243d5897a76052582694c3581607ab898298bd9 Mon Sep 17 00:00:00 2001 From: Barrett Ruth Date: Tue, 24 Feb 2026 23:14:53 -0500 Subject: [PATCH] refactor(buffer): update syntax, extmarks, and render for checkbox format Problem: syntax patterns matched the old indent/[N] format; right_align virtual text produced a broken layout in narrow windows; the done strikethrough skipped past the ' ' indent leaving '- [x] ' unstyled; render() added undo history entries so 'u' could undo a re-render. Solution: update taskHeader/taskLine patterns for '## '/'- [.]'; rename taskPriority -> taskCheckbox matching '[!]'; switch virt_text_pos to 'eol'; drop the +2 col_start offset so strikethrough covers '- [x] '; guard nvim_buf_set_lines with undolevels=-1 so renders are not undoable. Also fix open_line to insert '- [ ] ' and position cursor at col 6. --- lua/pending/buffer.lua | 19 +++++++++++-------- syntax/pending.vim | 8 ++++---- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/lua/pending/buffer.lua b/lua/pending/buffer.lua index 2036357..b60d633 100644 --- a/lua/pending/buffer.lua +++ b/lua/pending/buffer.lua @@ -56,9 +56,9 @@ local function setup_syntax(bufnr) vim.cmd([[ syntax clear syntax match taskId /^\/\d\+\// conceal - syntax match taskHeader /^\S.*$/ contains=taskId - syntax match taskPriority /\[\d\+\] / contained containedin=taskLine - syntax match taskLine /^\/\d\+\/ .*$/ contains=taskId,taskPriority + syntax match taskHeader /^## .*$/ contains=taskId + syntax match taskCheckbox /\[!\]/ contained containedin=taskLine + syntax match taskLine /^\/\d\+\/- \[.\] .*$/ contains=taskId,taskCheckbox ]]) end) end @@ -72,8 +72,8 @@ function M.open_line(above) local row = vim.api.nvim_win_get_cursor(0)[1] local insert_row = above and (row - 1) or row vim.bo[bufnr].modifiable = true - vim.api.nvim_buf_set_lines(bufnr, insert_row, insert_row, false, { ' ' }) - vim.api.nvim_win_set_cursor(0, { insert_row + 1, 2 }) + vim.api.nvim_buf_set_lines(bufnr, insert_row, insert_row, false, { '- [ ] ' }) + vim.api.nvim_win_set_cursor(0, { insert_row + 1, 6 }) vim.cmd('startinsert!') end @@ -113,18 +113,18 @@ local function apply_extmarks(bufnr, line_meta) if virt_text then vim.api.nvim_buf_set_extmark(bufnr, task_ns, row, 0, { virt_text = virt_text, - virt_text_pos = 'right_align', + virt_text_pos = 'eol', }) end elseif m.due then vim.api.nvim_buf_set_extmark(bufnr, task_ns, row, 0, { virt_text = { { m.due, due_hl } }, - virt_text_pos = 'right_align', + virt_text_pos = 'eol', }) end if m.status == 'done' then local line = vim.api.nvim_buf_get_lines(bufnr, row, row + 1, false)[1] or '' - local col_start = line:find('/%d+/') and select(2, line:find('/%d+/')) + 2 or 0 + local col_start = line:find('/%d+/') and select(2, line:find('/%d+/')) or 0 vim.api.nvim_buf_set_extmark(bufnr, task_ns, row, col_start, { end_col = #line, hl_group = 'PendingDone', @@ -168,8 +168,11 @@ function M.render(bufnr) _meta = line_meta vim.bo[bufnr].modifiable = true + local saved = vim.bo[bufnr].undolevels + vim.bo[bufnr].undolevels = -1 vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines) vim.bo[bufnr].modified = false + vim.bo[bufnr].undolevels = saved setup_syntax(bufnr) apply_extmarks(bufnr, line_meta) diff --git a/syntax/pending.vim b/syntax/pending.vim index b5f3da1..a8a0258 100644 --- a/syntax/pending.vim +++ b/syntax/pending.vim @@ -3,12 +3,12 @@ if exists('b:current_syntax') endif syntax match taskId /^\/\d\+\// conceal -syntax match taskHeader /^\S.*$/ contains=taskId -syntax match taskPriority /!\ze / contained -syntax match taskLine /^\/\d\+\/ .*$/ contains=taskId,taskPriority +syntax match taskHeader /^## .*$/ contains=taskId +syntax match taskCheckbox /\[!\]/ contained containedin=taskLine +syntax match taskLine /^\/\d\+\/- \[.\] .*$/ contains=taskId,taskCheckbox highlight default link taskHeader PendingHeader -highlight default link taskPriority PendingPriority +highlight default link taskCheckbox PendingPriority highlight default link taskLine Normal let b:current_syntax = 'task'