Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve order of the todo agenda #842

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions lua/orgmode/agenda/views/todos.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions lua/orgmode/config/defaults.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
13 changes: 13 additions & 0 deletions lua/orgmode/files/headline.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
15 changes: 11 additions & 4 deletions lua/orgmode/org/mappings.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Loading