From 04a50de7aecf4311fe306c31891548da0893281f Mon Sep 17 00:00:00 2001 From: Andreas Wachowski Date: Wed, 22 May 2024 08:42:20 +0200 Subject: [PATCH] feat(archive): set outline path when archiving --- lua/orgmode/capture/init.lua | 7 ++++- lua/orgmode/files/headline.lua | 26 ++++++++++++++++++ tests/plenary/ui/mappings/archive_spec.lua | 32 ++++++++++++++++++++++ 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/lua/orgmode/capture/init.lua b/lua/orgmode/capture/init.lua index 297a332aa..24c1335ba 100644 --- a/lua/orgmode/capture/init.lua +++ b/lua/orgmode/capture/init.lua @@ -275,6 +275,7 @@ function Capture:refile_file_headline_to_archive(headline) end local destination_file = self.files:get(archive_location) + local todo_state = headline:get_todo() local target_line = self:_refile_from_org_file({ source_headline = headline, @@ -287,8 +288,12 @@ function Capture:refile_file_headline_to_archive(headline) local archived_headline = archive_file:get_closest_headline({ target_line, 0 }) archived_headline:set_property('ARCHIVE_TIME', Date.now():to_string()) archived_headline:set_property('ARCHIVE_FILE', file.filename) + local outline_path = headline:get_outline_path() + if outline_path ~= '' then + archived_headline:set_property('ARCHIVE_OLPATH', outline_path) + end archived_headline:set_property('ARCHIVE_CATEGORY', headline:get_category()) - archived_headline:set_property('ARCHIVE_TODO', headline:get_todo() or '') + archived_headline:set_property('ARCHIVE_TODO', todo_state or '') end) end diff --git a/lua/orgmode/files/headline.lua b/lua/orgmode/files/headline.lua index cf86dd2c4..10888384a 100644 --- a/lua/orgmode/files/headline.lua +++ b/lua/orgmode/files/headline.lua @@ -226,6 +226,32 @@ function Headline:get_category() return self.file:get_category() end +memoize('get_outline_path') +--- @return string +function Headline:get_outline_path() + local inner_to_outer_parent_headlines = {} + local parent_section = self:node():parent():parent() + + while parent_section do + local headline_node = parent_section:field('headline')[1] + if headline_node then + local headline = Headline:new(headline_node, self.file) + local headline_title = headline:get_title() + table.insert(inner_to_outer_parent_headlines, headline_title) + end + parent_section = parent_section:parent() + end + + -- reverse headline order + local outer_to_inner_parent_headlines = {} + for i = #inner_to_outer_parent_headlines, 1, -1 do + table.insert(outer_to_inner_parent_headlines, inner_to_outer_parent_headlines[i]) + end + + local outline_path = table.concat(outer_to_inner_parent_headlines, '/') + return outline_path +end + ---@param tags string function Headline:set_tags(tags) ---@type TSNode diff --git a/tests/plenary/ui/mappings/archive_spec.lua b/tests/plenary/ui/mappings/archive_spec.lua index 178b4a260..5c974aa8c 100644 --- a/tests/plenary/ui/mappings/archive_spec.lua +++ b/tests/plenary/ui/mappings/archive_spec.lua @@ -28,6 +28,7 @@ describe('Archive', function() ' :PROPERTIES:', ' :ARCHIVE_TIME: ' .. now:to_string(), ' :ARCHIVE_FILE: ' .. file.filename, + -- no ARCHIVE_OLPATH because top-level headline ' :ARCHIVE_CATEGORY: ' .. file:get_category(), ' :ARCHIVE_TODO: ', ' :END:', @@ -55,10 +56,41 @@ describe('Archive', function() ' :PROPERTIES:', ' :ARCHIVE_TIME: ' .. now:to_string(), ' :ARCHIVE_FILE: ' .. file.filename, + -- no ARCHIVE_OLPATH because top-level headline ' :ARCHIVE_CATEGORY: ' .. file:get_category(), ' :ARCHIVE_TODO: ', ' :END:', '** baz', }, vim.api.nvim_buf_get_lines(0, 0, -1, false)) end) + + it('sets outline path when archiving lower-level headline', function() + local file = helpers.create_agenda_file({ + '* foo', + '** TODO bar', + '*** TODO baz', + ' Body text baz', + }) + + vim.cmd([[exe "norm G,o$"]]) + -- Pause to finish the archiving + vim.wait(50) + assert.are.same({ + '* foo', + '** TODO bar', + }, vim.api.nvim_buf_get_lines(0, 0, -1, false)) + + vim.cmd(('edit %s'):format(file.filename .. '_archive')) + assert.are.same({ + '* TODO baz', -- keep todo state in the title + ' :PROPERTIES:', + ' :ARCHIVE_TIME: ' .. Date.now():to_string(), + ' :ARCHIVE_FILE: ' .. file.filename, + ' :ARCHIVE_OLPATH: foo/bar', -- remove todo state in any headline in outline path + ' :ARCHIVE_CATEGORY: ' .. file:get_category(), + ' :ARCHIVE_TODO: TODO', + ' :END:', + ' Body text baz', + }, vim.api.nvim_buf_get_lines(0, 0, -1, false)) + end) end)