Skip to content

Commit b7c42e6

Browse files
feat(hyperlinks): Add support to follow id link to a file
1 parent c4eeb3d commit b7c42e6

File tree

4 files changed

+70
-2
lines changed

4 files changed

+70
-2
lines changed

lua/orgmode/files/file.lua

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ function OrgFile:find_headlines_matching_search_term(search_term, no_escape, ign
272272
end, self:get_headlines_including_archived())
273273
end
274274

275+
---Find headlines where property value is matching the term partially from start
275276
---@param property_name string
276277
---@param term string
277278
---@return OrgHeadline[]
@@ -282,6 +283,17 @@ function OrgFile:find_headlines_with_property_matching(property_name, term)
282283
end, self:get_headlines())
283284
end
284285

286+
---Find headlines where property value is matching the term exactly
287+
---@param property_name string
288+
---@param term string
289+
---@return OrgHeadline[]
290+
function OrgFile:find_headlines_with_property(property_name, term)
291+
return vim.tbl_filter(function(item)
292+
local property = item:get_property(property_name)
293+
return property and property:lower() == term:lower()
294+
end, self:get_headlines())
295+
end
296+
285297
memoize('get_opened_headlines')
286298
---@return OrgHeadline[]
287299
function OrgFile:get_opened_headlines()

lua/orgmode/files/init.lua

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ end
208208

209209
---@param property_name string
210210
---@param term string
211+
---@return OrgHeadline[]
211212
function OrgFiles:find_headlines_with_property_matching(property_name, term)
212213
local headlines = {}
213214
for _, orgfile in ipairs(self:all()) do
@@ -218,6 +219,33 @@ function OrgFiles:find_headlines_with_property_matching(property_name, term)
218219
return headlines
219220
end
220221

222+
---@param property_name string
223+
---@param term string
224+
---@return OrgHeadline[]
225+
function OrgFiles:find_headlines_with_property(property_name, term)
226+
local headlines = {}
227+
for _, orgfile in ipairs(self:all()) do
228+
for _, headline in ipairs(orgfile:find_headlines_with_property(property_name, term)) do
229+
table.insert(headlines, headline)
230+
end
231+
end
232+
return headlines
233+
end
234+
235+
---@param property_name string
236+
---@param term string
237+
---@return OrgFile[]
238+
function OrgFiles:find_files_with_property(property_name, term)
239+
local files = {}
240+
for _, orgfile in ipairs(self:all()) do
241+
local property = orgfile:get_property(property_name)
242+
if property and property:lower() == term:lower() then
243+
table.insert(files, orgfile)
244+
end
245+
end
246+
return files
247+
end
248+
221249
---@param term string
222250
---@param no_escape boolean
223251
---@param search_extra_files boolean

lua/orgmode/org/mappings.lua

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -836,7 +836,16 @@ function OrgMappings:open_at_point()
836836

837837
if link.url:is_id() then
838838
local id = link.url:get_id() or ''
839-
local headlines = self.files:find_headlines_with_property_matching('id', id)
839+
local files = self.files:find_files_with_property('id', id)
840+
if #files > 0 then
841+
if #files > 1 then
842+
utils.echo_warning(string.format('Multiple files found with id: %s, jumping to first one found', id))
843+
end
844+
vim.cmd(('edit %s'):format(files[1].filename))
845+
return
846+
end
847+
848+
local headlines = self.files:find_headlines_with_property('id', id)
840849
if #headlines == 0 then
841850
return utils.echo_warning(string.format('No headline found with id: %s', id))
842851
end

tests/plenary/ui/mappings/hyperlink_spec.lua

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ describe('Hyperlink mappings', function()
4949
assert.is.same('** headline of target custom_id', vim.api.nvim_get_current_line())
5050
end)
5151

52-
it('should follow link to id', function()
52+
it('should follow link to id in headline', function()
5353
local target_file = helpers.create_agenda_file({
5454
'* Test hyperlink',
5555
' - some',
@@ -71,6 +71,25 @@ describe('Hyperlink mappings', function()
7171
assert.is.same('** headline of target id', vim.api.nvim_get_current_line())
7272
end)
7373

74+
it('should follow link to id in file', function()
75+
local target_file = helpers.create_agenda_file({
76+
':PROPERTIES:',
77+
':ID: add6b93c-9e0e-4922-a4f5-c00926787197',
78+
':END:',
79+
'* Test hyperlink to file',
80+
' - some',
81+
' - boiler',
82+
' - plate',
83+
})
84+
helpers.create_agenda_file({
85+
'This link should lead to [[id:add6b93c-9e0e-4922-a4f5-c00926787197][target file]]',
86+
})
87+
vim.fn.cursor(1, 30)
88+
vim.cmd([[norm ,oo]])
89+
assert.are.same(target_file.filename, vim.api.nvim_buf_get_name(0))
90+
assert.is.same(':PROPERTIES:', vim.api.nvim_get_current_line())
91+
end)
92+
7493
it('should store link to a headline', function()
7594
local target_file = helpers.create_agenda_file({
7695
'* Test hyperlink',

0 commit comments

Comments
 (0)