Skip to content

Commit 17c18f0

Browse files
committed
feat(attach): add OrgAttach:expand_links()
This corresponds to the Emacs function `org-attach-expand-links`.
1 parent 3d9c455 commit 17c18f0

File tree

2 files changed

+68
-0
lines changed

2 files changed

+68
-0
lines changed

lua/orgmode/attach/core.lua

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,4 +575,40 @@ function AttachCore:sync(node, delete_empty_dir)
575575
end)
576576
end
577577

578+
---Call `callback` with every attachment link in the file.
579+
---
580+
---@param file OrgFile
581+
---@param callback fun(attach_dir: string|false, basename: string): string|nil
582+
---@return OrgPromise<nil>
583+
function AttachCore:on_every_attachment_link(file, callback)
584+
-- TODO: In a better world, this would use treesitter for parsing ...
585+
return file:update(function()
586+
local lines = vim.api.nvim_buf_get_lines(0, 0, -1, true)
587+
local prev_node = nil ---@type OrgAttachNode | nil
588+
local attach_dir = nil ---@type string | false | nil
589+
for i, line in ipairs(lines) do
590+
-- Check if node has changed; if yes, invalidate cached attach_dir.
591+
local node = AttachNode.at_cursor(file, { i + 1, 0 })
592+
if node ~= prev_node then
593+
attach_dir = nil
594+
end
595+
---@param basename string
596+
---@param bracket '[' | ']'
597+
---@return string
598+
local replaced = line:gsub('%[%[attachment:([^%]]+)%]([%[%]])', function(basename, bracket)
599+
-- Only compute attach_dir when we know that we need it!
600+
if attach_dir == nil then
601+
attach_dir = self:get_dir_or_nil(node, true) or false
602+
end
603+
local res = callback(attach_dir, basename)
604+
return res and ('[[%s]%s'):format(res, bracket) or ('[[attachment:%s]%s'):format(basename, bracket)
605+
end)
606+
if replaced ~= line then
607+
vim.api.nvim_buf_set_lines(0, i - 1, i, true, { replaced })
608+
end
609+
prev_node = node
610+
end
611+
end)
612+
end
613+
578614
return AttachCore

lua/orgmode/attach/init.lua

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,4 +640,36 @@ function Attach:sync(node)
640640
return self.core:sync(node, delete_empty_dir):wait(MAX_TIMEOUT)
641641
end
642642

643+
---Expand links in current buffer.
644+
---
645+
---It is meant to be added to `org_export_before_parsing_hook`."
646+
---TODO: Add this hook. Will require refactoring `orgmode.export`.
647+
---
648+
---@param bufnr? integer
649+
---@return nil
650+
function Attach:expand_links(bufnr)
651+
bufnr = bufnr or 0
652+
local file = self.core.files:get(vim.api.nvim_buf_get_name(bufnr))
653+
local total = 0
654+
local miss = 0
655+
self.core
656+
:on_every_attachment_link(file, function(attach_dir, basename)
657+
total = total + 1
658+
if not attach_dir then
659+
miss = miss + 1
660+
return
661+
end
662+
return 'file:' .. vim.fs.joinpath(attach_dir, basename)
663+
end)
664+
:next(function()
665+
if miss > 0 then
666+
utils.echo_warning(('failed to expand %d/%d attachment links'):format(miss, total))
667+
else
668+
utils.echo_info(('expanded %d attachment links'):format(total))
669+
end
670+
return nil
671+
end)
672+
:wait(MAX_TIMEOUT)
673+
end
674+
643675
return Attach

0 commit comments

Comments
 (0)