From 527fd981aa747a5d247eb613cd1ae1c4ca351198 Mon Sep 17 00:00:00 2001 From: Kristijan Husak Date: Wed, 25 Jun 2025 19:19:18 +0200 Subject: [PATCH] perf(api): Load headlines only when requested --- lua/orgmode/api/file.lua | 48 ++++++++++++++++++------------- tests/plenary/fixtures/refile.org | 2 ++ 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/lua/orgmode/api/file.lua b/lua/orgmode/api/file.lua index 728a26928..172580bca 100644 --- a/lua/orgmode/api/file.lua +++ b/lua/orgmode/api/file.lua @@ -29,44 +29,52 @@ local function map_child_headlines(headline, headlines_by_id) return headline end +---@param instance OrgApiFile +local function load_headlines(instance) + local headlines = {} + local headlines_by_id = {} + for i, section in ipairs(instance._file:get_headlines()) do + local headline = OrgHeadline._build_from_internal_headline(section, i) + table.insert(headlines, headline) + headlines_by_id[section:get_range().start_line] = headline + end + + for _, headline in ipairs(headlines) do + map_child_headlines(headline, headlines_by_id) + headline.file = instance + end + + rawset(instance, 'headlines', headlines) +end + ---@private function OrgFile:_new(opts) local data = {} data.category = opts.category data.filename = opts.filename - data.headlines = opts.headlines data.is_archive_file = opts.is_archive_file or false data._file = opts._file - setmetatable(data, self) - self.__index = self + setmetatable(data, { + __index = function(tbl, key) + if key == 'headlines' and rawget(tbl, 'headlines') == nil then + load_headlines(tbl) + end + + return rawget(tbl, key) + end, + }) return data end ---@param file OrgFile ---@private function OrgFile._build_from_internal_file(file) - local headlines = {} - local headlines_by_id = {} - for i, section in ipairs(file:get_headlines()) do - local headline = OrgHeadline._build_from_internal_headline(section, i) - table.insert(headlines, headline) - headlines_by_id[section:get_range().start_line] = headline - end - - local instance = OrgFile:_new({ + return OrgFile:_new({ _file = file, category = file:get_category(), filename = file.filename, - headlines = headlines, is_archive_file = file:is_archive_file(), }) - - for _, headline in ipairs(instance.headlines) do - map_child_headlines(headline, headlines_by_id) - headline.file = instance - end - - return instance end --- Return refreshed instance of the file diff --git a/tests/plenary/fixtures/refile.org b/tests/plenary/fixtures/refile.org index e69de29bb..a69fb7428 100644 --- a/tests/plenary/fixtures/refile.org +++ b/tests/plenary/fixtures/refile.org @@ -0,0 +1,2 @@ +* TODO Second level :NESTEDTAG: + DEADLINE: <2021-07-21 Wed 22:02>