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