@@ -575,4 +575,40 @@ function AttachCore:sync(node, delete_empty_dir)
575575 end )
576576end
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+
578614return AttachCore
0 commit comments