summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Vanbesien <tvanbesi@proton.me>2026-05-21 16:05:21 +0200
committerThomas Vanbesien <tvanbesi@proton.me>2026-05-21 16:05:21 +0200
commitb413d9c470f3597be1a51b52e58c854db5f31bd2 (patch)
treedec198b28121792107e551e1ca86823e3b67cb33
parent19bf0d5cd95a2643736dd35d7b127c7d023429cf (diff)
downloaddotfiles-b413d9c470f3597be1a51b52e58c854db5f31bd2.tar.gz
dotfiles-b413d9c470f3597be1a51b52e58c854db5f31bd2.zip
fix(nvim): live highlight TODO strings
Previously, extended marks for TODO strings were only set once on `'FileType'`.
-rw-r--r--.config/nvim/plugin/50-extmarks.lua50
1 files changed, 37 insertions, 13 deletions
diff --git a/.config/nvim/plugin/50-extmarks.lua b/.config/nvim/plugin/50-extmarks.lua
index c11d10c..1324da0 100644
--- a/.config/nvim/plugin/50-extmarks.lua
+++ b/.config/nvim/plugin/50-extmarks.lua
@@ -37,7 +37,7 @@ end
local function pmatches(lines, pattern)
local col1, col2, row = nil, nil, 1
return function()
- while row < #lines do
+ while row <= #lines do
col1, col2 = string.find(lines[row], pattern, (col2 or 0) + 1)
if col1 then
return { col1 = col1, col2 = col2, row = row }
@@ -55,18 +55,18 @@ end
-- predicate: is passed row and col, if true then set the mark
-- hl_group: highlight group
-- }
-local function set_extmarks(next_pos, opts)
+local function set_extmarks(buf, next_pos, opts)
for pos in next_pos do
local marks = vim.api.nvim_buf_get_extmarks(
- 0,
+ buf,
opts.ns,
{ pos.row - 1, pos.col1 - 1 },
{ pos.row - 1, pos.col2 - 1 },
{}
)
- if #marks == 0 and opts.predicate(pos.row - 1, pos.col1 - 1) then
+ if #marks == 0 and opts.predicate(buf, pos.row - 1, pos.col1 - 1) then
vim.api.nvim_buf_set_extmark(
- 0,
+ buf,
opts.ns,
pos.row - 1,
pos.col1 - 1,
@@ -79,11 +79,11 @@ end
-- TODO a better way to do this:
-- For code, only check in "comment" node ranges
-- For non-code, do it per type. For Markdown, only check "paragraph" nodes
-local function hl_todo_predicate(row, col)
- if vim.o.filetype == "markdown" or vim.treesitter.get_parser() == nil then
+local function hl_todo_predicate(buf, row, col)
+ if vim.bo[buf].filetype == "markdown" or vim.treesitter.get_parser(buf) == nil then
return true
end
- local node = assert(vim.treesitter.get_node({ pos = { row, col } }))
+ local node = assert(vim.treesitter.get_node({ bufnr = buf, pos = { row, col } }))
return node_within_type(node, "comment")
end
@@ -94,12 +94,36 @@ local extmarks_todo_opts = {
predicate = hl_todo_predicate,
}
--- Initialize extmarks
+local function scan(buf, first, last)
+ local lines = vim.api.nvim_buf_get_lines(buf, first, last, false)
+ local iter = pmatches(lines, patterns.todo)
+ set_extmarks(buf, function()
+ local pos = iter()
+ if pos then
+ pos.row = pos.row + first
+ end
+ return pos
+ end, extmarks_todo_opts)
+end
+
vim.api.nvim_create_autocmd("FileType", {
- desc = "Initialize extmarks",
+ desc = "Initialize and watch TODO extmarks",
group = vim.g.dotfiles.augroup,
- callback = function()
- local lines = vim.api.nvim_buf_get_lines(0, 0, -1, false)
- set_extmarks(pmatches(lines, patterns.todo), extmarks_todo_opts)
+ callback = function(args)
+ local buf = args.buf
+ scan(buf, 0, -1)
+ if vim.b[buf].dotfiles_todo_attached then
+ return
+ end
+ vim.b[buf].dotfiles_todo_attached = true
+ vim.api.nvim_buf_attach(buf, false, {
+ on_lines = function(_, b, _, first, _, last_new)
+ vim.schedule(function()
+ if vim.api.nvim_buf_is_valid(b) then
+ scan(b, first, last_new)
+ end
+ end)
+ end,
+ })
end,
})