Skip to content
Open
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
27 changes: 25 additions & 2 deletions lua/orgmode/files/file.lua
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ local Buffers = require('orgmode.state.buffers')
---@field metadata OrgFileMetadata
---@field parser vim.treesitter.LanguageTree
---@field root TSNode
---@field _parse_tick? number Buffer changedtick at last parse (for staleness detection)
local OrgFile = {}

local memoize = Memoize:new(OrgFile, function(self)
Expand Down Expand Up @@ -193,6 +194,13 @@ function OrgFile:parse(skip_if_not_modified)
self.parser = self:_get_parser()
local trees = self.parser:parse()
self.root = trees[1]:root()

-- Track changedtick for staleness detection
local bufnr = self:bufnr()
if bufnr > -1 then
self._parse_tick = vim.api.nvim_buf_get_changedtick(bufnr)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this used for?

end

return self.root
end

Expand Down Expand Up @@ -487,21 +495,36 @@ function OrgFile:get_node_at_cursor(cursor)
return self.root:named_descendant_for_range(row, col, row, col)
end

---Get text for a treesitter node
---Uses pcall to gracefully handle stale nodes (when buffer changed after parse)
---@param node? TSNode
---@param range? number[]
---@return string
function OrgFile:get_node_text(node, range)
if not node then
return ''
end

local source = self:get_source()
local ok, result

if range then
return ts.get_node_text(node, self:get_source(), {
ok, result = pcall(ts.get_node_text, node, source, {
metadata = {
range = range,
},
})
else
ok, result = pcall(ts.get_node_text, node, source)
end

if not ok then
-- Node positions are stale (buffer changed since parse)
-- Return empty string for graceful degradation
return ''
end
return ts.get_node_text(node, self:get_source())

return result
end

---@param node? TSNode
Expand Down