Skip to content

Commit 5bd38a6

Browse files
feat(orgfile): Parse links from document
1 parent c6647a5 commit 5bd38a6

File tree

3 files changed

+74
-1
lines changed

3 files changed

+74
-1
lines changed

lua/orgmode/files/file.lua

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ local Headline = require('orgmode.files.headline')
55
local ts = vim.treesitter
66
local config = require('orgmode.config')
77
local Block = require('orgmode.files.elements.block')
8+
local Link = require('orgmode.org.hyperlinks.link')
89

910
---@class OrgFileMetadata
1011
---@field mtime number
@@ -598,6 +599,23 @@ function OrgFile:get_archive_file_location()
598599
return config:parse_archive_location(self.filename, archive_location)
599600
end
600601

602+
memoize('get_links')
603+
---@return OrgLink[]
604+
function OrgFile:get_links()
605+
self:parse(true)
606+
local ts_query = ts_utils.get_query([[
607+
(paragraph (expr) @links)
608+
(drawer (contents (expr) @links))
609+
(headline (item (expr)) @links)
610+
]])
611+
612+
local links = {}
613+
for _, match in ts_query:iter_captures(self.root, self:_get_source()) do
614+
vim.list_extend(links, Link.all_from_line(self:get_node_text(match)))
615+
end
616+
return links
617+
end
618+
601619
---@private
602620
---@return string | nil
603621
function OrgFile:_get_directive(directive_name)

lua/orgmode/org/hyperlinks/link.lua

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ local Url = require('orgmode.org.hyperlinks.url')
55
---@field desc string | nil
66
local Link = {}
77

8+
local pattern = '%[%[([^%]]+.-)%]%]'
9+
810
---@param str string
911
---@return OrgLink
1012
function Link:new(str)
@@ -30,7 +32,6 @@ end
3032
function Link.at_pos(line, pos)
3133
local links = {}
3234
local found_link = nil
33-
local pattern = '%[%[([^%]]+.-)%]%]'
3435
local position
3536
for link in line:gmatch(pattern) do
3637
local start_from = #links > 0 and links[#links].to or nil
@@ -49,4 +50,17 @@ function Link.at_pos(line, pos)
4950
return Link:new(found_link), position
5051
end
5152

53+
function Link.all_from_line(line)
54+
local links = {}
55+
for link in line:gmatch(pattern) do
56+
local start_from = #links > 0 and links[#links].to or nil
57+
local from, to = line:find(pattern, start_from)
58+
if from and to then
59+
table.insert(links, Link:new(link))
60+
end
61+
end
62+
63+
return links
64+
end
65+
5266
return Link

tests/plenary/files/file_spec.lua

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -738,4 +738,45 @@ describe('OrgFile', function()
738738
assert.are.same('112233', file:get_property('custom_id'))
739739
end)
740740
end)
741+
742+
describe('get_links', function()
743+
it('should get all links from a file', function()
744+
local file = load_file_sync({
745+
'Top level [[https://google.com]]',
746+
'',
747+
'* TODO Headline link to file [[./some-file.org]]',
748+
' - list item link to [[https://duckduckgo.com][duck]]',
749+
'',
750+
' :LOGBOOK:',
751+
' :TEST: And link in drawer [[https://github.com][github]]',
752+
' :END:',
753+
})
754+
local links = file:get_links()
755+
756+
assert.are.same(4, #links)
757+
assert.are.same('https://google.com', links[1].url:to_string())
758+
assert.is.Nil(links[1].desc)
759+
760+
assert.are.same('./some-file.org', links[2].url:to_string())
761+
assert.is.Nil(links[2].desc)
762+
763+
assert.are.same('https://duckduckgo.com', links[3].url:to_string())
764+
assert.are.same('duck', links[3].desc)
765+
766+
assert.are.same('https://github.com', links[4].url:to_string())
767+
assert.are.same('github', links[4].desc)
768+
end)
769+
770+
it('should get file level property', function()
771+
local file = load_file_sync({
772+
':PROPERTIES:',
773+
':ID: 443355',
774+
':CUSTOM_ID: 112233',
775+
':END:',
776+
'#+title: test',
777+
'* TODO Headline 1',
778+
})
779+
assert.are.same('112233', file:get_property('custom_id'))
780+
end)
781+
end)
741782
end)

0 commit comments

Comments
 (0)