todo.nvim

July 26, 2024 · View on GitHub

Simple but powerful todo manager based on text.

More neovim plugins

Dependencies

Usage

  • features
    • get todo under cursor
      • require("todo").get_cur_todo
      • @return todo.Todo | nil
    • search all todos
      • require("todo").search_all
      • @param map_items (fun(items: todo.TelescopeSearchItem[]): todo.TelescopeSearchItem[]) | nil
      • do filter, sort, etc with map_items
    • search upstream todos
      • require("todo").search_upstream
      • @param map_items (fun(items: todo.TelescopeSearchItem[]): todo.TelescopeSearchItem[]) | nil
    • search downstream todos
      • require("todo").search_downstream
      • @param map_items (fun(items: todo.TelescopeSearchItem[]): todo.TelescopeSearchItem[]) | nil
    • custom decorate
    • custom parser
  • default format: [status] (id:dependencies){tags}: content
    • dependencies and tags are separated with ,.
    • tags is optional, which may be used to indicate importance, urgency, type, etc.
    • status map
      • " " = "TODO"
      • x = "DONE"
      • v = "VERIFY"
      • w = "WORKING"
      • b = "BLOCKED"

Config

  • class Todo
---@class todo.Todo
---@field path string
---@field lnum number
---@field status string
---@field id string
---@field dependencies string[]
---@field tags string[]
---@field content string
  • class TelescopeSearchItem
---@class todo.TelescopeSearchItem
---@field label string
---@field todo todo.Todo
  • default config
local config = {
	---@type fun(): string
	root_dir = function()
		local core = require("core")
		return core.file.root_path()
	end,
	---@type string
	rg_pattern = [[\[.+\] \(.+\)\{?.*\}?: .*]],
	---@type fun(text: string): todo.Todo | nil
	parse = function(text)
		local status, id, dependencies, tags, content =
			string.match(text, "^.*%[([vbwx%s])%] %(([^:]+):?([^%)]*)%){?([^{}]*)}?: (.*)$")
		if status ~= nil then
			local status_map = {
				[" "] = "TODO",
				x = "DONE",
				v = "VERIFY",
				w = "WORKING",
				b = "BLOCKED",
			}
			return {
				status = status_map[status],
				id = id,
				dependencies = dependencies and vim.split(dependencies, ",") or {},
				tags = tags and vim.split(tags, ",") or {},
				content = content,
			}
		end
	end,
	---@type fun(todo: todo.Todo): [string, string][]
	badges = function(todo)
		local core = require("core")

		local tags = core.lua.list.reduce(todo.tags, function(prev, tag)
			return prev == "" and tag or prev .. "," .. tag
		end, "")

		local dependencies = core.lua.list.reduce(todo.dependencies, function(prev, dep)
			return prev == "" and dep or prev .. "," .. dep
		end, "")

		local roundStart = { "", "TodoRound" }
		local roundEnd = { "", "TodoRound" }
		local space = { " ", "TodoSpace" }

		local badges = {
			{ todo.id, "TodoId" },
			{ todo.status, "TodoStatus" },
			{ tags, "TodoTag" },
			{ dependencies, "TodoDependency" },
		}

		local result = {}
		core.lua.list.each(badges, function(badge)
			if badge[1] ~= "" then
				table.insert(result, roundStart)
				table.insert(result, badge)
				table.insert(result, roundEnd)
				table.insert(result, space)
			end
		end)
		return result
	end,
}
  • default hl
local function set_hl()
	local bg = vim.api.nvim_get_hl(0, { name = "CursorLine" }).bg

	vim.api.nvim_set_hl(0, "TodoId", {
		fg = "#E0AF68",
		bg = bg,
		italic = true,
	})
	vim.api.nvim_set_hl(0, "TodoStatus", {
		fg = "#0DB9D7",
		bg = bg,
		italic = true,
	})
	vim.api.nvim_set_hl(0, "TodoTag", {
		fg = "#00FFCC",
		bg = bg,
		italic = true,
	})
	vim.api.nvim_set_hl(0, "TodoDependency", {
		fg = "#FF06C1",
		bg = bg,
		italic = true,
	})
	vim.api.nvim_set_hl(0, "TodoRound", {
		fg = bg,
	})
end