@@ -575,4 +575,40 @@ function AttachCore:sync(node, delete_empty_dir)
575
575
end )
576
576
end
577
577
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
+
578
614
return AttachCore
0 commit comments