From 6bb6fece61f6c0df7053d731e4b993bc1ac2b7dd Mon Sep 17 00:00:00 2001 From: Lyz Date: Tue, 24 Dec 2024 15:22:00 +0100 Subject: [PATCH 1/2] feat: improve order of the todo agenda --- lua/orgmode/agenda/views/todos.lua | 50 ++++++++++++++++++++++++++++++ lua/orgmode/files/headline.lua | 13 ++++++++ 2 files changed, 63 insertions(+) diff --git a/lua/orgmode/agenda/views/todos.lua b/lua/orgmode/agenda/views/todos.lua index 725aa02c8..52ec74b24 100644 --- a/lua/orgmode/agenda/views/todos.lua +++ b/lua/orgmode/agenda/views/todos.lua @@ -6,9 +6,59 @@ local hl_map = agenda_highlights.get_agenda_hl_map() local function sort_todos(todos) table.sort(todos, function(a, b) + -- Tasks marked as clocked_in appear first + if a:is_clocked_in() then + return true + end + if b:is_clocked_in() then + return false + end + + -- Then tasks are sorted by their priority if a:get_priority_sort_value() ~= b:get_priority_sort_value() then return a:get_priority_sort_value() > b:get_priority_sort_value() end + + -- Then tasks are sorted by their TODO keyword + local a_keyword = a:get_todo() + local b_keyword = b:get_todo() + if (a_keyword and b_keyword) and (a_keyword ~= b_keyword) then + return a:get_todo_sort_value() < b:get_todo_sort_value() + end + + -- Then tasks which have a DEADLINE have priority over SCHEDULED over nothing + local a_deadline = a:get_deadline_date() + local a_scheduled = a:get_scheduled_date() + local b_deadline = b:get_deadline_date() + local b_scheduled = b:get_scheduled_date() + + -- If both have deadlines, earlier deadline comes first + if a_deadline and b_deadline then + return a_deadline < b_deadline + end + + -- If only one has deadline, it comes first + if a_deadline then + return true + end + if b_deadline then + return false + end + + -- If both have scheduled dates, earlier date comes first + if a_scheduled and b_scheduled then + return a_scheduled < b_scheduled + end + + -- If only one has scheduled date, it comes first + if a_scheduled then + return true + end + if b_scheduled then + return false + end + + -- Then tasks are sorted by their category keyword return a:get_category() < b:get_category() end) return todos diff --git a/lua/orgmode/files/headline.lua b/lua/orgmode/files/headline.lua index c008dd2aa..085b26660 100644 --- a/lua/orgmode/files/headline.lua +++ b/lua/orgmode/files/headline.lua @@ -196,6 +196,19 @@ function Headline:get_priority_sort_value() return PriorityState:new(priority, prio_range):get_sort_value() end +---@return integer | nil +function Headline:get_todo_sort_value() + local todo_keyword = self:get_todo() + if todo_keyword == nil then + return nil + end + local todo_state = config:get_todo_keywords():find(todo_keyword) + if todo_state == nil then + return nil + end + return todo_state.index +end + function Headline:is_archived() return #vim.tbl_filter(function(tag) return tag:upper() == 'ARCHIVE' From 8a1acbf964388cefae57803f4ac29ff4f2045f60 Mon Sep 17 00:00:00 2001 From: Lyz Date: Tue, 24 Dec 2024 16:08:25 +0100 Subject: [PATCH 2/2] fix: allow the user to set the default todo state As the order of the org_todo_keywords define the order of the todo in the agenda, a user may want to have a default TODO state different than the first one in the org_todo_keywords list --- lua/orgmode/config/defaults.lua | 1 + lua/orgmode/org/mappings.lua | 15 +++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/lua/orgmode/config/defaults.lua b/lua/orgmode/config/defaults.lua index f2c18d9a4..b30f8aa0a 100644 --- a/lua/orgmode/config/defaults.lua +++ b/lua/orgmode/config/defaults.lua @@ -7,6 +7,7 @@ local DefaultConfig = { org_agenda_files = '', org_default_notes_file = '', org_todo_keywords = { 'TODO', '|', 'DONE' }, + org_todo_default_state = nil, org_todo_repeat_to_state = nil, org_todo_keyword_faces = {}, org_deadline_warning_days = 14, diff --git a/lua/orgmode/org/mappings.lua b/lua/orgmode/org/mappings.lua index ae63928e2..d4a9e3c2b 100644 --- a/lua/orgmode/org/mappings.lua +++ b/lua/orgmode/org/mappings.lua @@ -739,18 +739,25 @@ function OrgMappings:insert_heading_respect_content(suffix) end function OrgMappings:insert_todo_heading_respect_content() - return self:insert_heading_respect_content(config:get_todo_keywords():first_by_type('TODO').value .. ' ') + local first_todo_keyword = config.org_todo_default_state or config:get_todo_keywords():first_by_type('TODO').value + if not first_todo_keyword then + error('No default TODO keyword found') + end + return self:insert_heading_respect_content(first_todo_keyword .. ' ') end function OrgMappings:insert_todo_heading() local item = self.files:get_closest_headline_or_nil() - local first_todo_keyword = config:get_todo_keywords():first_by_type('TODO') + local first_todo_keyword = config.org_todo_default_state or config:get_todo_keywords():first_by_type('TODO').value + if not first_todo_keyword then + error('No default TODO keyword found') + end if not item then - self:_insert_heading_from_plain_line(first_todo_keyword.value .. ' ') + self:_insert_heading_from_plain_line(first_todo_keyword .. ' ') return vim.cmd([[startinsert!]]) else vim.fn.cursor(item:get_range().start_line, 1) - return self:meta_return(first_todo_keyword.value .. ' ') + return self:meta_return(first_todo_keyword .. ' ') end end