From a8f3df14fd66514db2df37448f7452a0fccf7448 Mon Sep 17 00:00:00 2001 From: Kristijan Husak Date: Mon, 15 Sep 2025 17:18:58 +0200 Subject: [PATCH] feat(agenda)!: Add time grid This is considered a breaking change commit because it adds a new time grid option to the agenda view, which was not there before. It is set to `true` by default to align with how Emacs Orgmode works out of the box. To disable the time grid, set `org_agenda_use_time_grid = false` in your orgmode config. --- docs/configuration.org | 48 +++++++ lua/orgmode/agenda/agenda_item.lua | 4 +- lua/orgmode/agenda/sorting_strategy.lua | 20 ++- lua/orgmode/agenda/types/agenda.lua | 147 +++++++++++++++++++++- lua/orgmode/colors/highlights.lua | 6 + lua/orgmode/config/_meta.lua | 9 ++ lua/orgmode/config/defaults.lua | 8 ++ tests/plenary/agenda/agenda_item_spec.lua | 42 +++---- 8 files changed, 258 insertions(+), 26 deletions(-) diff --git a/docs/configuration.org b/docs/configuration.org index bbcf609cf..b648c3c4c 100644 --- a/docs/configuration.org +++ b/docs/configuration.org @@ -787,6 +787,53 @@ To change the highlight, override =@org.agenda.separator= hl group. - Default: =false= Should tags be hidden from all agenda views. +*** org_agenda_time_grid +:PROPERTIES: +:CUSTOM_ID: org_agenda_time_grid +:END: +- Type: ={ type: ('daily', 'weekly', 'require-timed', 'remove-match')[], times: number[], time_separator: string, time_label: string }= +- Default: + #+begin_src lua + { + type = { 'daily', 'today', 'require-timed' }, + times = { 800, 1000, 1200, 1400, 1600, 1800, 2000 }, + time_separator = '┄┄┄┄┄', + time_label = '┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄' + } + #+end_src + +Settings for the time grid visible in agenda. To disable showing the time grid altogether, set [[#org_agenda_use_time_grid][org_agenda_use_time_grid]] to =false=. + +- =type=: List of options where all have to apply to show the grid + - =daily= - Show grid in daily agenda (1 day view) + - =weekly= - Show grid in any agenda type + - =today= - Show grid only for today + - =require-timed= - Show grid only if day has any entries with time specification + - =remove-match= - Hide grid entries that overlap with the existing time slot taken by an agenda item +- =times=: List of times (in 24h format) to show on the grid. It should be integer value, example =1030= represents =10:30= +- =time_separator=: Value that is showed after the grid time as a separator +- =time_label=: Value that is showed after the =time_separator= to fill in the place that is usually for the agenda item title + +To customize the label for the current time, check [[#org_agenda_current_time_string][org_agenda_current_time_string]] + +*** org_agenda_use_time_grid +:PROPERTIES: +:CUSTOM_ID: org_agenda_use_time_grid +:END: +- Type: =boolean= +- Default: =true= +Show time grid in agenda. See [[#org_agenda_time_grid][org_agenda_time_grid]] for configuration options. + +*** org_agenda_current_time_string +:PROPERTIES: +:CUSTOM_ID: org_agenda_current_time_string +:END: +- Type: =string= +- Default: =<- now -----------------------------------------------= +Label value for the current time in the agenda time grid. +See [[#org_agenda_time_grid][org_agenda_time_grid]] for time grid configuration or [[#org_agenda_use_time_grid][org_agenda_use_time_grid]] to disable the grid. + + *** org_capture_templates :PROPERTIES: :CUSTOM_ID: org_capture_templates @@ -2872,6 +2919,7 @@ The following highlight groups are used: - =@org.agenda.deadline=: A item deadline in the agenda view - Parsed from =Error= (see note below) - =@org.agenda.scheduled=: A scheduled item in the agenda view - Parsed from =DiffAdd= (see note below) - =@org.agenda.scheduled_past=: A item past its scheduled date in the agenda view - Parsed from =WarningMsg= (see note below) +- =@org.agenda.time_grid=: Time grid line - Parsed from =WarningMsg= (see note below) - =@org.agenda.day=: Highlight for all days in Agenda view - linked to =Statement= - =@org.agenda.today=: Highlight for today in Agenda view - linked to =@org.bold= - =@org.agenda.weekend=: Highlight for weekend days in Agenda view - linked to =@org.bold= diff --git a/lua/orgmode/agenda/agenda_item.lua b/lua/orgmode/agenda/agenda_item.lua index ee311e74b..1253d6432 100644 --- a/lua/orgmode/agenda/agenda_item.lua +++ b/lua/orgmode/agenda/agenda_item.lua @@ -3,10 +3,10 @@ local hl_map = Highlights.get_agenda_hl_map() local config = require('orgmode.config') local FUTURE_DEADLINE_AS_WARNING_DAYS = math.floor(config.org_deadline_warning_days / 2) local function add_padding(datetime) - if datetime:len() >= 11 then + if datetime:len() >= 10 then return datetime .. ' ' end - return datetime .. string.rep('.', 11 - datetime:len()) .. ' ' + return datetime .. ' ' .. config.org_agenda_time_grid.time_separator .. ' ' end ---@class OrgAgendaItem diff --git a/lua/orgmode/agenda/sorting_strategy.lua b/lua/orgmode/agenda/sorting_strategy.lua index 3dc19b216..73c7fef5c 100644 --- a/lua/orgmode/agenda/sorting_strategy.lua +++ b/lua/orgmode/agenda/sorting_strategy.lua @@ -17,7 +17,7 @@ local SortingStrategy = {} ---@class SortableEntry ---@field date OrgDate Available only in agenda view ----@field headline OrgHeadline +---@field headline? OrgHeadline ---@field index number Index of the entry in the fetched list ---@field is_day_match? boolean Is this entry a match for the given day. Available only in agenda view @@ -53,6 +53,9 @@ end ---@param a SortableEntry ---@param b SortableEntry function SortingStrategy.priority_down(a, b) + if not a.headline or not b.headline then + return + end 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 @@ -77,6 +80,9 @@ end ---@param a SortableEntry ---@param b SortableEntry function SortingStrategy.tag_up(a, b) + if not a.headline or not b.headline then + return + end local a_tags = a.headline:tags_to_string(true) local b_tags = b.headline:tags_to_string(true) if a_tags == '' and b_tags == '' then @@ -106,6 +112,9 @@ end ---@param a SortableEntry ---@param b SortableEntry function SortingStrategy.todo_state_up(a, b) + if not a.headline or not b.headline then + return + end local _, _, _, a_index = a.headline:get_todo() local _, _, _, b_index = b.headline:get_todo() if a_index and b_index then @@ -134,6 +143,9 @@ end ---@param a SortableEntry ---@param b SortableEntry function SortingStrategy.category_up(a, b) + if not a.headline or not b.headline then + return + end if a.headline.file:get_category() ~= b.headline.file:get_category() then return a.headline.file:get_category() < b.headline.file:get_category() end @@ -151,6 +163,9 @@ end ---@param a SortableEntry ---@param b SortableEntry function SortingStrategy.category_keep(a, b) + if not a.headline or not b.headline then + return + end if a.headline.file.index ~= b.headline.file.index then return a.headline.file.index < b.headline.file.index end @@ -179,6 +194,9 @@ end ---@param a SortableEntry ---@param b SortableEntry local fallback_sort = function(a, b) + if not a.headline or not b.headline then + return + end if a.headline.file.index ~= b.headline.file.index then return a.headline.file.index < b.headline.file.index end diff --git a/lua/orgmode/agenda/types/agenda.lua b/lua/orgmode/agenda/types/agenda.lua index 53ea6388c..cb81b41ef 100644 --- a/lua/orgmode/agenda/types/agenda.lua +++ b/lua/orgmode/agenda/types/agenda.lua @@ -11,6 +11,8 @@ local utils = require('orgmode.utils') local SortingStrategy = require('orgmode.agenda.sorting_strategy') local Promise = require('orgmode.utils.promise') +---@alias OrgAgendaDay { day: OrgDate, agenda_items: OrgAgendaItem[], category_length: number, label_length: 0 } + ---@class OrgAgendaTypeOpts ---@field files OrgFiles ---@field highlighter OrgHighlighter @@ -51,6 +53,7 @@ local Promise = require('orgmode.utils.promise') ---@field remove_tags? boolean ---@field valid_filters? OrgAgendaFilter[] ---@field id? string +---@field private _grid_times { hour: number, min: number }[] local OrgAgendaType = {} OrgAgendaType.__index = OrgAgendaType @@ -264,7 +267,12 @@ function OrgAgendaType:render(bufnr, current_line) })) for _, agenda_item in ipairs(agenda_day.agenda_items) do - agendaView:add_line(self:_build_line(agenda_item, agenda_day)) + -- If there is an index value, this is an AgendaItem instance + if agenda_item.index then + agendaView:add_line(self:_build_line(agenda_item, agenda_day)) + else + agendaView:add_line(self:_build_time_grid_line(agenda_item, agenda_day)) + end end end @@ -318,6 +326,140 @@ function OrgAgendaType:render(bufnr, current_line) return self.view end +---@param grid_line { real_date: OrgDate, is_same_day: boolean, is_now: boolean } +---@param agenda_day OrgAgendaDay +---@return OrgAgendaLine +function OrgAgendaType:_build_time_grid_line(grid_line, agenda_day) + local line = AgendaLine:new({ + hl_group = '@org.agenda.time_grid', + metadata = { + date = grid_line.real_date, + }, + }) + + line:add_token(AgendaLineToken:new({ + content = ' ' .. utils.pad_right(' ', agenda_day.category_length), + })) + line:add_token(AgendaLineToken:new({ + content = grid_line.real_date:format_time() .. ' ' .. config.org_agenda_time_grid.time_separator, + })) + line:add_token(AgendaLineToken:new({ + content = grid_line.is_now and config.org_agenda_current_time_string or config.org_agenda_time_grid.time_label, + })) + + return line +end + +---@param date_range OrgDate[] +---@param agenda_day OrgAgendaDay +---@return { real_date: OrgDate, is_same_day: boolean, is_now: boolean }[] +function OrgAgendaType:_prepare_grid_lines(date_range, agenda_day) + if not config.org_agenda_use_time_grid then + return {} + end + + local time_grid_opts = config.org_agenda_time_grid + if not time_grid_opts or not time_grid_opts.type or #time_grid_opts.type == 0 then + return {} + end + + local today = false + local weekly = false + local daily = false + local require_timed = false + local remove_match = false + + for _, t in ipairs(time_grid_opts.type) do + if t == 'daily' then + daily = true + end + if t == 'weekly' then + weekly = true + end + if t == 'today' then + today = true + end + if t == 'require-timed' then + require_timed = true + end + if t == 'remove-match' then + remove_match = true + end + end + + local show_grid = (daily and #date_range == 1) or weekly + if not show_grid and today then + show_grid = agenda_day.day:is_today() + end + + local same_day_agenda_items_with_time = {} + + if require_timed or remove_match then + for _, agenda_item in ipairs(agenda_day.agenda_items) do + if agenda_item.is_same_day and agenda_item.real_date:has_time() then + table.insert(same_day_agenda_items_with_time, agenda_item) + end + end + end + + if show_grid and require_timed then + show_grid = #same_day_agenda_items_with_time > 0 + end + + if not show_grid then + return {} + end + + local grid_lines = {} + local now = Date.now() + for _, time in ipairs(self:_parse_grid_times()) do + local date = agenda_day.day:set({ + hour = time.hour, + min = time.min, + date_only = false, + }) + if remove_match then + for _, item in ipairs(same_day_agenda_items_with_time) do + if item.real_date:is_same(date) then + goto continue + end + end + end + if date:is_today() and date > now and (#grid_lines == 0 or grid_lines[#grid_lines].real_date < now) then + local now_line = { + real_date = now, + is_same_day = true, + is_now = true, + } + table.insert(grid_lines, now_line) + end + table.insert(grid_lines, { + real_date = date, + is_same_day = true, + is_now = false, + }) + + ::continue:: + end + return grid_lines +end + +function OrgAgendaType:_parse_grid_times() + if self._grid_times then + return self._grid_times + end + local grid_times = {} + for _, time in ipairs(config.org_agenda_time_grid.times) do + local str = tostring(time) + table.insert(grid_times, { + min = tonumber(str:sub(#str - 1, #str)), + hour = tonumber(str:sub(1, #str - 2)), + }) + end + self._grid_times = grid_times + return grid_times +end + ---@private ---@param agenda_item OrgAgendaItem ---@param metadata table @@ -381,7 +523,7 @@ function OrgAgendaType:rerender_agenda_line(agenda_line, headline) self.view:replace_line(agenda_line, line) end ----@return { day: OrgDate, agenda_items: OrgAgendaItem[], category_length: number, label_length: 0 }[] +---@return OrgAgendaDay[] function OrgAgendaType:_get_agenda_days() local dates = self.from:get_range_until(self.to) local agenda_days = {} @@ -413,6 +555,7 @@ function OrgAgendaType:_get_agenda_days() end end + vim.list_extend(date.agenda_items, self:_prepare_grid_lines(dates, date)) date.agenda_items = self:_sort(date.agenda_items) date.category_length = math.max(11, date.category_length + 1) date.label_length = math.min(11, date.label_length) diff --git a/lua/orgmode/colors/highlights.lua b/lua/orgmode/colors/highlights.lua index b9e4c1aab..dc0885a73 100644 --- a/lua/orgmode/colors/highlights.lua +++ b/lua/orgmode/colors/highlights.lua @@ -95,6 +95,12 @@ function M.define_agenda_colors() string.format('hi default %s guifg=%s ctermfg=%s', hlname, keyword_colors[type].gui, keyword_colors[type].cterm) ) end + vim.cmd( + ('hi default @org.agenda.time_grid guifg=%s ctermfg=%s'):format( + keyword_colors.warning.gui, + keyword_colors.warning.cterm + ) + ) M.define_org_todo_keyword_colors() end diff --git a/lua/orgmode/config/_meta.lua b/lua/orgmode/config/_meta.lua index 02b8161e4..d0c62997d 100644 --- a/lua/orgmode/config/_meta.lua +++ b/lua/orgmode/config/_meta.lua @@ -21,6 +21,12 @@ ---@field org_agenda_todo_ignore_scheduled? OrgAgendaTodoIgnoreScheduledTypes ---@field org_agenda_todo_ignore_deadlines? OrgAgendaTodoIgnoreDeadlinesTypes +---@class OrgAgendaTimeGridOpts +---@field type ('daily' | 'weekly' | 'today' | 'require-timed' | 'remove-match')[] +---@field times number[] +---@field time_separator string +---@field time_label string + ---@alias OrgAgendaCustomCommandType (OrgAgendaCustomCommandAgenda | OrgAgendaCustomCommandTags) ---@class OrgAgendaCustomCommand @@ -211,6 +217,9 @@ ---@field org_agenda_block_separator? string Separator for blocks in the agenda view. Default: '-' ---@field org_agenda_sorting_strategy? table<'agenda' | 'todo' | 'tags', OrgAgendaSortingStrategy[]> Sorting strategy for the agenda view. See docs for default value ---@field org_agenda_remove_tags? boolean If true, tags will be removed from the all agenda views. Default: false +---@field org_agenda_use_time_grid? boolean If true, Render time grid in agenda as set by org_agenda_time_grid. Default: true +---@field org_agenda_time_grid? OrgAgendaTimeGridOpts Agenda time grid configuration. Default: { type = { 'daily', 'today', 'require-timed' }, times = { 800, 1000, 1200, 1400, 1600, 1800, 2000 }, time_separator = '┄┄┄┄┄', time_label = '┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄' } +---@field org_agenda_current_time_string? string String to indicate current time on the time grid. Default: '<- now -----------------------------------------------' ---@field org_priority_highest? string | number Highest priority level. Default: 'A' ---@field org_priority_default? string | number Default priority level. Default: 'B' ---@field org_priority_lowest? string | number Lowest priority level. Default: 'C' diff --git a/lua/orgmode/config/defaults.lua b/lua/orgmode/config/defaults.lua index 79f748bcf..c1dc679eb 100644 --- a/lua/orgmode/config/defaults.lua +++ b/lua/orgmode/config/defaults.lua @@ -33,6 +33,14 @@ local DefaultConfig = { tags = { 'priority-down', 'category-keep' }, }, org_agenda_remove_tags = false, + org_agenda_time_grid = { + type = { 'daily', 'today', 'require-timed' }, + times = { 800, 1000, 1200, 1400, 1600, 1800, 2000 }, + time_separator = '┄┄┄┄┄', + time_label = '┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄', + }, + org_agenda_current_time_string = '<- now -----------------------------------------------', + org_agenda_use_time_grid = true, org_priority_highest = 'A', org_priority_default = 'B', org_priority_lowest = 'C', diff --git a/tests/plenary/agenda/agenda_item_spec.lua b/tests/plenary/agenda/agenda_item_spec.lua index 9d0596157..56981f572 100644 --- a/tests/plenary/agenda/agenda_item_spec.lua +++ b/tests/plenary/agenda/agenda_item_spec.lua @@ -38,7 +38,7 @@ describe('Agenda item', function() assert.is.same(hl_map.TODO, agenda_item:get_todo_hlgroup()) assert.is.Nil(agenda_item:get_hlgroup()) assert.is.Nil(agenda_item:get_priority_hlgroup()) - assert.are.same(today:format_time() .. '...... ', agenda_item.label) + assert.are.same(today:format_time() .. ' ┄┄┄┄┄ ', agenda_item.label) headline = generate(string.format('Some content <%s>', today:subtract({ day = 2 }):to_string())) agenda_item = AgendaItem:new(headline:get_all_dates()[1], headline, today) @@ -60,7 +60,7 @@ describe('Agenda item', function() assert.is.same(hl_map.TODO, agenda_item:get_todo_hlgroup()) assert.is.same(hl_map.deadline, agenda_item:get_hlgroup()) assert.is.Nil(agenda_item:get_priority_hlgroup()) - assert.are.same(today:format_time() .. '...... Deadline:', agenda_item.label) + assert.are.same(today:format_time() .. ' ┄┄┄┄┄ Deadline:', agenda_item.label) -- past headline = generate(string.format('DEADLINE: <%s>', today:subtract({ day = 7 }):to_string())) @@ -133,7 +133,7 @@ describe('Agenda item', function() assert.is.same(hl_map.TODO, agenda_item:get_todo_hlgroup()) assert.is.same(hl_map.ok, agenda_item:get_hlgroup()) assert.is.Nil(agenda_item:get_priority_hlgroup()) - assert.are.same(today:format_time() .. '...... Scheduled:', agenda_item.label) + assert.are.same(today:format_time() .. ' ┄┄┄┄┄ Scheduled:', agenda_item.label) -- Past undone headline = generate(string.format('SCHEDULED: <%s>', today:subtract({ day = 7 }):to_string())) @@ -190,7 +190,7 @@ describe('Agenda item', function() assert.is.same(hl_map.DONE, agenda_item:get_todo_hlgroup()) assert.is.same(hl_map.ok, agenda_item:get_hlgroup()) assert.is.Nil(agenda_item:get_priority_hlgroup()) - assert.are.same(today:format_time() .. '...... Scheduled:', agenda_item.label) + assert.are.same(today:format_time() .. ' ┄┄┄┄┄ Scheduled:', agenda_item.label) -- Deadline done shown by default local headline_deadline = generate(string.format('DEADLINE: <%s>', today:to_string()), 'DONE') @@ -199,7 +199,7 @@ describe('Agenda item', function() assert.is.same(hl_map.DONE, agenda_item:get_todo_hlgroup()) assert.is.same(hl_map.ok, agenda_item:get_hlgroup()) assert.is.Nil(agenda_item:get_priority_hlgroup()) - assert.are.same(today:format_time() .. '...... Deadline:', agenda_item_deadline.label) + assert.are.same(today:format_time() .. ' ┄┄┄┄┄ Deadline:', agenda_item_deadline.label) config:extend({ org_agenda_skip_scheduled_if_done = true }) @@ -213,7 +213,7 @@ describe('Agenda item', function() assert.is.same(hl_map.DONE, agenda_item:get_todo_hlgroup()) assert.is.same(hl_map.ok, agenda_item:get_hlgroup()) assert.is.Nil(agenda_item:get_priority_hlgroup()) - assert.are.same(today:format_time() .. '...... Deadline:', agenda_item_deadline.label) + assert.are.same(today:format_time() .. ' ┄┄┄┄┄ Deadline:', agenda_item_deadline.label) config:extend({ org_agenda_skip_scheduled_if_done = false }) end) @@ -227,7 +227,7 @@ describe('Agenda item', function() assert.is.same(hl_map.DONE, agenda_item:get_todo_hlgroup()) assert.is.same(hl_map.ok, agenda_item:get_hlgroup()) assert.is.Nil(agenda_item:get_priority_hlgroup()) - assert.are.same(today:format_time() .. '...... Scheduled:', agenda_item.label) + assert.are.same(today:format_time() .. ' ┄┄┄┄┄ Scheduled:', agenda_item.label) -- Deadline done shown by default local headline_deadline = generate(string.format('DEADLINE: <%s>', today:to_string()), 'DONE') @@ -236,7 +236,7 @@ describe('Agenda item', function() assert.is.same(hl_map.DONE, agenda_item:get_todo_hlgroup()) assert.is.same(hl_map.ok, agenda_item:get_hlgroup()) assert.is.Nil(agenda_item:get_priority_hlgroup()) - assert.are.same(today:format_time() .. '...... Deadline:', agenda_item_deadline.label) + assert.are.same(today:format_time() .. ' ┄┄┄┄┄ Deadline:', agenda_item_deadline.label) config:extend({ org_agenda_skip_deadline_if_done = true }) @@ -245,7 +245,7 @@ describe('Agenda item', function() assert.is.same(hl_map.DONE, agenda_item:get_todo_hlgroup()) assert.is.same(hl_map.ok, agenda_item:get_hlgroup()) assert.is.Nil(agenda_item:get_priority_hlgroup()) - assert.are.same(today:format_time() .. '...... Scheduled:', agenda_item.label) + assert.are.same(today:format_time() .. ' ┄┄┄┄┄ Scheduled:', agenda_item.label) -- Deadline done hidden agenda_item_deadline = AgendaItem:new(headline_deadline:get_all_dates()[1], headline_deadline, today) @@ -309,7 +309,7 @@ describe('Agenda item', function() assert.is.same(hl_map.TODO, agenda_item:get_todo_hlgroup()) assert.is.Nil(agenda_item:get_hlgroup()) assert.is.Nil(agenda_item:get_priority_hlgroup()) - assert.are.same(future_day:format_time() .. '...... ', agenda_item.label) + assert.are.same(future_day:format_time() .. ' ┄┄┄┄┄ ', agenda_item.label) -- Invalid for any other day headline = generate(string.format('Some content <%s>', future_day:add({ day = 1 }):to_string())) @@ -327,7 +327,7 @@ describe('Agenda item', function() assert.is.same(hl_map.TODO, agenda_item:get_todo_hlgroup()) assert.is.same(hl_map.deadline, agenda_item:get_hlgroup()) assert.is.Nil(agenda_item:get_priority_hlgroup()) - assert.are.same(future_day:format_time() .. '...... Deadline:', agenda_item.label) + assert.are.same(future_day:format_time() .. ' ┄┄┄┄┄ Deadline:', agenda_item.label) -- Green highlight if it's done headline = generate(string.format('DEADLINE: <%s>', future_day:to_string()), 'DONE') @@ -336,7 +336,7 @@ describe('Agenda item', function() assert.is.same(hl_map.DONE, agenda_item:get_todo_hlgroup()) assert.is.same(hl_map.ok, agenda_item:get_hlgroup()) assert.is.Nil(agenda_item:get_priority_hlgroup()) - assert.are.same(future_day:format_time() .. '...... Deadline:', agenda_item.label) + assert.are.same(future_day:format_time() .. ' ┄┄┄┄┄ Deadline:', agenda_item.label) -- Invalid for any other day headline = generate(string.format('DEADLINE: <%s>', future_day:add({ day = 1 }):to_string())) @@ -354,7 +354,7 @@ describe('Agenda item', function() assert.is.same(hl_map.TODO, agenda_item:get_todo_hlgroup()) assert.is.same(hl_map.ok, agenda_item:get_hlgroup()) assert.is.Nil(agenda_item:get_priority_hlgroup()) - assert.are.same(future_day:format_time() .. '...... Scheduled:', agenda_item.label) + assert.are.same(future_day:format_time() .. ' ┄┄┄┄┄ Scheduled:', agenda_item.label) -- Valid for same day, shows as yellow if it's past local past_day = Date.now():subtract({ day = 3 }) @@ -364,7 +364,7 @@ describe('Agenda item', function() assert.is.same(hl_map.TODO, agenda_item:get_todo_hlgroup()) assert.is.same(hl_map.warning, agenda_item:get_hlgroup()) assert.is.Nil(agenda_item:get_priority_hlgroup()) - assert.are.same(past_day:format_time() .. '...... Scheduled:', agenda_item.label) + assert.are.same(past_day:format_time() .. ' ┄┄┄┄┄ Scheduled:', agenda_item.label) -- Invalid for any other day headline = generate(string.format('SCHEDULED: <%s>', future_day:add({ day = 1 }):to_string())) @@ -391,7 +391,7 @@ describe('Agenda item', function() local day_with_only_time = Date.now():set({ hour = 10, min = 0 }) headline = generate(string.format('SCHEDULED: <%s>', day_with_only_time:to_string())) agenda_item = AgendaItem:new(headline:get_all_dates()[1], headline, day_with_only_time) - assert.are.same('10:00...... Scheduled:', agenda_item.label) + assert.are.same('10:00 ┄┄┄┄┄ Scheduled:', agenda_item.label) end) it('should properly read same day date ranges and time ranges', function() @@ -433,7 +433,7 @@ describe('Agenda item', function() assert.is.same(hl_map.DONE, agenda_item:get_todo_hlgroup()) assert.is.same(hl_map.ok, agenda_item:get_hlgroup()) assert.is.Nil(agenda_item:get_priority_hlgroup()) - assert.are.same(future_day:format_time() .. '...... Scheduled:', agenda_item.label) + assert.are.same(future_day:format_time() .. ' ┄┄┄┄┄ Scheduled:', agenda_item.label) -- Deadline done shown by default local headline_deadline = generate(string.format('DEADLINE: <%s>', future_day:to_string()), 'DONE') @@ -442,7 +442,7 @@ describe('Agenda item', function() assert.is.same(hl_map.DONE, agenda_item:get_todo_hlgroup()) assert.is.same(hl_map.ok, agenda_item:get_hlgroup()) assert.is.Nil(agenda_item:get_priority_hlgroup()) - assert.are.same(future_day:format_time() .. '...... Deadline:', agenda_item_deadline.label) + assert.are.same(future_day:format_time() .. ' ┄┄┄┄┄ Deadline:', agenda_item_deadline.label) config:extend({ org_agenda_skip_scheduled_if_done = true }) @@ -456,7 +456,7 @@ describe('Agenda item', function() assert.is.same(hl_map.DONE, agenda_item:get_todo_hlgroup()) assert.is.same(hl_map.ok, agenda_item:get_hlgroup()) assert.is.Nil(agenda_item:get_priority_hlgroup()) - assert.are.same(future_day:format_time() .. '...... Deadline:', agenda_item_deadline.label) + assert.are.same(future_day:format_time() .. ' ┄┄┄┄┄ Deadline:', agenda_item_deadline.label) config:extend({ org_agenda_skip_scheduled_if_done = false }) end) @@ -470,7 +470,7 @@ describe('Agenda item', function() assert.is.same(hl_map.DONE, agenda_item:get_todo_hlgroup()) assert.is.same(hl_map.ok, agenda_item:get_hlgroup()) assert.is.Nil(agenda_item:get_priority_hlgroup()) - assert.are.same(past_day:format_time() .. '...... Scheduled:', agenda_item.label) + assert.are.same(past_day:format_time() .. ' ┄┄┄┄┄ Scheduled:', agenda_item.label) -- Deadline done shown by default local headline_deadline = generate(string.format('DEADLINE: <%s>', past_day:to_string()), 'DONE') @@ -479,7 +479,7 @@ describe('Agenda item', function() assert.is.same(hl_map.DONE, agenda_item:get_todo_hlgroup()) assert.is.same(hl_map.ok, agenda_item:get_hlgroup()) assert.is.Nil(agenda_item:get_priority_hlgroup()) - assert.are.same(past_day:format_time() .. '...... Deadline:', agenda_item_deadline.label) + assert.are.same(past_day:format_time() .. ' ┄┄┄┄┄ Deadline:', agenda_item_deadline.label) config:extend({ org_agenda_skip_deadline_if_done = true }) @@ -488,7 +488,7 @@ describe('Agenda item', function() assert.is.same(hl_map.DONE, agenda_item:get_todo_hlgroup()) assert.is.same(hl_map.ok, agenda_item:get_hlgroup()) assert.is.Nil(agenda_item:get_priority_hlgroup()) - assert.are.same(past_day:format_time() .. '...... Scheduled:', agenda_item.label) + assert.are.same(past_day:format_time() .. ' ┄┄┄┄┄ Scheduled:', agenda_item.label) -- Deadline done hidden agenda_item_deadline = AgendaItem:new(headline_deadline:get_all_dates()[1], headline_deadline, past_day)