diff --git a/lua/orgmode/agenda/init.lua b/lua/orgmode/agenda/init.lua index d117f80f5..37358baf0 100644 --- a/lua/orgmode/agenda/init.lua +++ b/lua/orgmode/agenda/init.lua @@ -12,45 +12,104 @@ local Search = require('orgmode.parser.search') local AgendaFilter = require('orgmode.agenda.filter') local hl_map = agenda_highlights.get_agenda_hl_map() +--@return table[] +local function get_category_inds() + local files = config:get_all_files() + local categories = config:get_categories(files) + local category_inds = {} + for i, category in ipairs(categories) do + category_inds[category] = i + end + return category_inds +end + ---@param agenda_items AgendaItem[] ---@return AgendaItem[] local function sort_agenda_items(agenda_items) + local category_inds = get_category_inds() + table.sort(agenda_items, function(a, b) - if a.is_today and a.is_same_day then + -- sort items with a time of day in order of scheduling + if not a.headline_date.date_only and not b.headline_date.date_only then + if a.is_today and a.is_same_day then + if b.is_today and b.is_same_day then + return a.headline_date:is_before(b.headline_date) + end + return true + end + if b.is_today and b.is_same_day then - return a.headline_date:is_before(b.headline_date) + if a.is_today and a.is_same_day then + return a.headline_date:is_before(b.headline_date) + end + return false end - return true end - if b.is_today and b.is_same_day then - if a.is_today and a.is_same_day then - return a.headline_date:is_before(b.headline_date) - end + -- sort items with a time of day before ones that have a date only + -- true means sort a before b + if not a.headline_date.date_only and b.headline_date.date_only then + return true + end + if a.headline_date.date_only and not b.headline_date.date_only then return false end + -- else both items are date only, sort in this order: + -- category > priority > overdue deadline > overdue schedule > + -- > today deadline > today schedule + + -- if different categories sort by category + if a.headline:get_category() ~= b.headline:get_category() then + return category_inds[a.headline:get_category()] < category_inds[b.headline:get_category()] + end + + -- if different priorities sort by priority if a.headline:get_priority_sort_value() ~= b.headline:get_priority_sort_value() then return a.headline:get_priority_sort_value() > b.headline:get_priority_sort_value() end - if a.headline:has_priority() and b.headline:has_priority() then - return a.headline_date:is_before(b.headline_date) + -- overdue > today > future + if a.is_today and a.is_same_day then + if b.is_today and not b.is_same_day then + return a.headline_date:is_before(b.headline_date) + end + end + + if b.is_today and b.is_same_day then + if a.is_today and not a.is_same_day then + return a.headline_date:is_before(b.headline_date) + end end if a.is_in_date_range and not b.is_in_date_range then return false end - if not a.is_in_date_range and b.is_in_date_range then return true end + -- if same due sort by deadline + if a.headline_date:is_deadline() and not b.headline_date:is_deadline() then + return true + elseif not a.headline_date:is_deadline() and b.headline_date:is_deadline() then + return false + -- either both are deadlines or both are not deadlines + -- overdue deadline and overdue schedule > deadline today and schedule today + end + return a.headline_date:is_before(b.headline_date) end) return agenda_items end +local function sort_agenda_items_categories(agenda_items, category_inds) + table.sort(agenda_items, function(a, b) + return category_inds[a.headline:get_category()] < category_inds[b.headline:get_category()] + end) + return agenda_items +end + local function sort_todos(todos) table.sort(todos, function(a, b) if a:get_priority_sort_value() ~= b:get_priority_sort_value() then @@ -461,10 +520,9 @@ function Agenda:agenda() for _, item in ipairs(headline_dates) do local agenda_item = AgendaItem:new(item.headline_date, item.headline, day) if agenda_item.is_valid and self.filters:matches(item.headline) then - table.insert(date.agenda_items, agenda_item) + table.insert(date.agenda_items, agenda_item) end end - date.agenda_items = sort_agenda_items(date.agenda_items) table.insert(agenda_days, date) diff --git a/lua/orgmode/config/init.lua b/lua/orgmode/config/init.lua index f29c4d09c..6eba185f1 100644 --- a/lua/orgmode/config/init.lua +++ b/lua/orgmode/config/init.lua @@ -64,6 +64,16 @@ function Config:_deprecation_notify(opts) end end +---@return string[] +function Config:get_categories(files) + local categories = {} + for _, item in ipairs(files) do + local category = vim.fn.fnamemodify(item, ':t:r') + table.insert(categories, category) + end + return categories +end + ---@return string[] function Config:get_all_files() local all_filenames = {} diff --git a/lua/orgmode/parser/files.lua b/lua/orgmode/parser/files.lua index 6f8f9ebac..934029150 100644 --- a/lua/orgmode/parser/files.lua +++ b/lua/orgmode/parser/files.lua @@ -85,9 +85,10 @@ end function Files.all() Files.ensure_loaded() local files = vim.tbl_values(Files.orgfiles) - table.sort(files, function(a, b) - return a.category < b.category - end) + -- this sorts files alphabetically, I'm not sure if it's useful + -- table.sort(files, function(a, b) + -- return a.category < b.category + -- end) return files end diff --git a/lua/orgmode/utils/init.lua b/lua/orgmode/utils/init.lua index 38b93be78..5acbaa04f 100644 --- a/lua/orgmode/utils/init.lua +++ b/lua/orgmode/utils/init.lua @@ -427,4 +427,31 @@ function utils.promisify(fn) return fn end +---debug printing a table +---source https://stackoverflow.com/questions/41942289/display-contents-of-tables-in-lua +function utils.tprint(tbl, indent) + if not indent then indent = 0 end + local toprint = string.rep(" ", indent) .. "{\r\n" + indent = indent + 2 + for k, v in pairs(tbl) do + toprint = toprint .. string.rep(" ", indent) + if (type(k) == "number") then + toprint = toprint .. "[" .. k .. "] = " + elseif (type(k) == "string") then + toprint = toprint .. k .. "= " + end + if (type(v) == "number") then + toprint = toprint .. v .. ",\r\n" + elseif (type(v) == "string") then + toprint = toprint .. "\"" .. v .. "\",\r\n" + elseif (type(v) == "table") then + toprint = toprint .. utils.tprint(v, indent + 2) .. ",\r\n" + else + toprint = toprint .. "\"" .. tostring(v) .. "\",\r\n" + end + end + toprint = toprint .. string.rep(" ", indent-2) .. "}" + return toprint +end + return utils