Skip to content

Commit

Permalink
feat(todo-introspector): correctly enumerate amounts of done/undone i…
Browse files Browse the repository at this point in the history
…tems
  • Loading branch information
vhyrro committed Mar 28, 2024
1 parent 257a9bd commit d284488
Showing 1 changed file with 65 additions and 9 deletions.
74 changes: 65 additions & 9 deletions lua/neorg/modules/core/todo-introspector/module.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ local modules = neorg.modules

local module = modules.create("core.todo-introspector")

-- TODO: When searching recursive children also account for generic_list nodes

module.private = {
namespace = vim.api.nvim_create_namespace("neorg/todo-introspector"),

Expand Down Expand Up @@ -47,37 +49,91 @@ function module.public.attach_introspector(buffer)
end

vim.api.nvim_buf_attach(buffer, false, {
on_lines = function(_, buf, _, first)
on_lines = vim.schedule_wrap(function(_, buf, _, first)
---@type TSNode?
local node = module.required["core.integrations.treesitter"].get_first_node_on_line(buf, first)

assert(node)

---@type TSNode?
local parent = node

while parent do
local child = parent:named_child(1)

if child and child:type() == "detached_modifier_extension" then
module.public.perform_introspection(buffer, node)
break
module.public.perform_introspection(buffer, parent)
-- NOTE: do not break here as we want the introspection to propagate all the way up the syntax tree
end

parent = parent:parent()
end
end,
end),

on_detach = function()
module.private.buffers[buffer] = nil
end,
})
end

---
--- Aggregates TODO item counts from children.
---@param node TSNode
---@return { undone: number, pending: number, done: number, cancelled: number, recurring: number, on_hold: number, urgent: number, uncertain: number }
---@return number total
function module.public.calculate_items(node)
local counts = {
undone = 0,
pending = 0,
done = 0,
cancelled = 0,
recurring = 0,
on_hold = 0,
urgent = 0,
uncertain = 0,
}

local total = 0

-- Go through all the children of the current todo item node and count the amount of "done" children
for child in node:iter_children() do
if child:named_child(1) and child:named_child(1):type() == "detached_modifier_extension" then
for status in child:named_child(1):iter_children() do
if status:type():match("^todo_item_") then
local type = status:type():match("^todo_item_(.+)$")

counts[type] = counts[type] + 1

if type == "cancelled" then
break
end

total = total + 1
end
end
end
end

return counts, total
end

--- Displays the amount of done items in the form of an extmark.
---@param buffer number
---@param node TSNode
function module.public.perform_introspection(buffer, node)
assert(false)
local counts, total = module.public.calculate_items(node)

local line, col = node:start()

local unique_id = assert(tonumber(tostring(buffer) .. tostring(node:symbol()) .. tostring(line)))

if total == 0 then
vim.api.nvim_buf_del_extmark(buffer, module.private.namespace, unique_id)
return
end

-- TODO: Make configurable, make colours customizable, don't display [x/total]
-- as the total also includes things like uncertain tasks.
vim.api.nvim_buf_set_extmark(buffer, module.private.namespace, line, col, {
id = unique_id,
virt_text = { { string.format("[%d/%d]", counts.done, total), "Normal" } },
})
end

return module

0 comments on commit d284488

Please sign in to comment.