Skip to content

Commit d0baf31

Browse files
fix(dates): Fix parsing dates from headlines
Fixes #796 #797
1 parent adf277c commit d0baf31

File tree

3 files changed

+46
-3
lines changed

3 files changed

+46
-3
lines changed

lua/orgmode/files/headline.lua

+4-3
Original file line numberDiff line numberDiff line change
@@ -665,9 +665,10 @@ end
665665
memoize('get_non_plan_dates')
666666
---@return OrgDate[]
667667
function Headline:get_non_plan_dates()
668-
local section = self:node():parent()
668+
local headline_node = self:node()
669+
local section = headline_node:parent()
669670
local body = section and section:field('body')[1]
670-
local headline_text = self.file:get_node_text(self:_get_child_node('item')) or ''
671+
local headline_text = self.file:get_node_text(headline_node) or ''
671672
local dates = Date.parse_all_from_line(headline_text, self:node():start() + 1)
672673
local properties_node = section and section:field('property_drawer')[1]
673674

@@ -684,7 +685,7 @@ function Headline:get_non_plan_dates()
684685
end
685686

686687
local start_line = body:range()
687-
local lines = self.file:get_node_text_list(body)
688+
local lines = self.file:get_node_text_list(body, ts_utils.range_with_zero_start_col(body))
688689
for i, line in ipairs(lines) do
689690
local line_dates = Date.parse_all_from_line(line, start_line + i)
690691
local is_clock_line = line:match('^%s*:?CLOCK:') ~= nil

lua/orgmode/utils/treesitter/init.lua

+11
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,17 @@ function M.node_to_lsp_range(node)
121121
return rtn
122122
end
123123

124+
---Return the range of the given node, but override the start column to be 0.
125+
---This is needed when we want to parse the lines manually to ensure that
126+
---we parse from the start of the line
127+
---@param node TSNode
128+
---@return number[]
129+
function M.range_with_zero_start_col(node)
130+
local range = { node:range() }
131+
range[2] = 0
132+
return range
133+
end
134+
124135
-- Memoizes a function based on the buffer tick of the provided bufnr.
125136
-- The cache entry is cleared when the buffer is detached to avoid memory leaks.
126137
-- The options argument is a table with one optional value:

tests/plenary/files/headline_spec.lua

+31
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,35 @@ describe('Headline', function()
5353
assert.are.same('headline_2_category', file:get_headlines()[2]:get_category())
5454
end)
5555
end)
56+
57+
describe('get_all_dates', function()
58+
it('should properly parse dates from the headline and body', function()
59+
local file = helpers.create_file({
60+
'* TODO testing <2024-08-17 Sat>',
61+
'DEADLINE: <2024-08-19 Mon>',
62+
'* stuff <2024-01-17 Wed>',
63+
' <2024-02-17 Sat>',
64+
' <2024-03-18 Sun>',
65+
})
66+
67+
local assert_range = function(date, expected_range)
68+
assert.are.same(expected_range[1], date.range.start_line, 'Start line is not matching')
69+
assert.are.same(expected_range[2], date.range.start_col, 'Start col is not matching')
70+
assert.are.same(expected_range[3], date.range.end_line, 'End line is not matching')
71+
assert.are.same(expected_range[4], date.range.end_col, 'End col is not matching')
72+
end
73+
74+
local first_headline_dates = file:get_headlines()[1]:get_all_dates()
75+
assert.are.same(2, #first_headline_dates)
76+
assert_range(first_headline_dates[1], { 2, 11, 2, 26 })
77+
assert_range(first_headline_dates[2], { 1, 16, 1, 31 })
78+
79+
local second_headline_dates = file:get_headlines()[2]:get_all_dates()
80+
assert.are.same(3, #second_headline_dates)
81+
-- First date in the list is is always a plan date
82+
assert_range(second_headline_dates[1], { 4, 3, 4, 18 })
83+
assert_range(second_headline_dates[2], { 3, 9, 3, 24 })
84+
assert_range(second_headline_dates[3], { 5, 3, 5, 18 })
85+
end)
86+
end)
5687
end)

0 commit comments

Comments
 (0)