Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit c5940d3

Browse files
feat(links)!: Use refactor links structure (#803)
* feat(links)!: Use refactor links structure * fix(hyperlink): Fix jumping to file * fix(hyperlink): Do not attempt to search for expression if it's file only path
1 parent e3500ad commit c5940d3

File tree

9 files changed

+43
-145
lines changed

9 files changed

+43
-145
lines changed

lua/orgmode/api/file.lua

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
---@diagnostic disable: invisible
22
local OrgHeadline = require('orgmode.api.headline')
3-
local Hyperlinks = require('orgmode.org.hyperlinks')
43
local org = require('orgmode')
54

65
---@class OrgApiFile
@@ -112,12 +111,12 @@ function OrgFile:get_link()
112111
-- do remote edit
113112
return org.files
114113
:update_file(filename, function(file)
115-
return Hyperlinks.get_link_to_file(file)
114+
return org.links:get_link_to_file(file)
116115
end)
117116
:wait()
118117
end
119118

120-
return Hyperlinks.get_link_to_file(self._file)
119+
return org.links:get_link_to_file(self._file)
121120
end
122121

123122
return OrgFile

lua/orgmode/api/headline.lua

+2-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ local PriorityState = require('orgmode.objects.priority_state')
44
local Date = require('orgmode.objects.date')
55
local Calendar = require('orgmode.objects.calendar')
66
local Promise = require('orgmode.utils.promise')
7-
local Hyperlinks = require('orgmode.org.hyperlinks')
87
local org = require('orgmode')
98

109
---@class OrgApiHeadline
@@ -281,12 +280,12 @@ function OrgHeadline:get_link()
281280
-- do remote edit
282281
return org.files
283282
:update_file(filename, function(_)
284-
return Hyperlinks.get_link_to_headline(self._section)
283+
return org.links:get_link_to_headline(self._section)
285284
end)
286285
:wait()
287286
end
288287

289-
return Hyperlinks.get_link_to_headline(self._section)
288+
return org.links:get_link_to_headline(self._section)
290289
end
291290

292291
return OrgHeadline

lua/orgmode/api/init.lua

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
---@diagnostic disable: invisible
22
local OrgFile = require('orgmode.api.file')
33
local OrgHeadline = require('orgmode.api.headline')
4-
local Hyperlinks = require('orgmode.org.hyperlinks')
54
local orgmode = require('orgmode')
65

76
---@class OrgApiRefileOpts
@@ -110,7 +109,8 @@ end
110109
--- @param link_location string
111110
--- @return boolean
112111
function OrgApi.insert_link(link_location)
113-
Hyperlinks.insert_link(link_location)
112+
orgmode.links:insert_link(link_location)
113+
return true
114114
end
115115

116116
return OrgApi

lua/orgmode/files/file.lua

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +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')
8+
local Hyperlink = require('orgmode.org.links.hyperlink')
99
local Range = require('orgmode.files.elements.range')
1010
local Memoize = require('orgmode.utils.memoize')
1111

@@ -722,7 +722,7 @@ function OrgFile:get_archive_file_location()
722722
end
723723

724724
memoize('get_links')
725-
---@return OrgLink[]
725+
---@return OrgHyperlink[]
726726
function OrgFile:get_links()
727727
self:parse(true)
728728
local ts_query = ts_utils.get_query([[
@@ -736,7 +736,7 @@ function OrgFile:get_links()
736736
for _, match in ts_query:iter_captures(self.root, self:_get_source()) do
737737
local line = match:start()
738738
if not processed_lines[line] then
739-
vim.list_extend(links, Link.all_from_line(self.lines[line + 1], line + 1))
739+
vim.list_extend(links, Hyperlink.all_from_line(self.lines[line + 1], line + 1))
740740
processed_lines[line] = true
741741
end
742742
end

lua/orgmode/org/autocompletion/sources/hyperlinks.lua

+2-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
local Hyperlinks = require('orgmode.org.hyperlinks')
2-
local Link = require('orgmode.org.hyperlinks.link')
31
---@class OrgCompletionHyperlinks:OrgCompletionSource
42
---@field completion OrgCompletion
53
---@field private pattern vim.regex
@@ -24,11 +22,10 @@ function OrgCompletionHyperlinks:get_start(context)
2422
return self.pattern:match_str(context.line)
2523
end
2624

25+
---@param context OrgCompletionContext
2726
---@return string[]
2827
function OrgCompletionHyperlinks:get_results(context)
29-
local link = Link:new(context.base)
30-
local result, mapper = Hyperlinks.find_matching_links(link.url)
31-
return mapper(result)
28+
return self.completion.links:autocomplete(context.base)
3229
end
3330

3431
return OrgCompletionHyperlinks

lua/orgmode/org/links/types/headline_search.lua

+12-1
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,13 @@ function OrgLinkHeadlineSearch:follow(link)
2929
end
3030

3131
local file = self.files:load_file_sync(opts.file_path)
32+
local is_file_only = opts.type == 'file' and not opts.target
3233

3334
if file then
35+
if is_file_only then
36+
return link_utils.goto_file(file)
37+
end
38+
3439
local pattern = ('<<<?(%s[^>]*)>>>?'):format(opts.headline_text):lower()
3540
local headlines = file:find_headlines_matching_search_term(pattern, true)
3641
if #headlines == 0 then
@@ -44,7 +49,13 @@ function OrgLinkHeadlineSearch:follow(link)
4449
)
4550
end
4651

47-
return link_utils.open_file_and_search(opts.file_path, opts.headline_text)
52+
local search_text = opts.headline_text
53+
54+
if is_file_only then
55+
search_text = ''
56+
end
57+
58+
return link_utils.open_file_and_search(opts.file_path, search_text)
4859
end
4960

5061
---@param link string

lua/orgmode/org/links/utils.lua

+6-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ function link_utils.goto_oneof_headlines(headlines, file_path, error_message)
5959
end
6060

6161
---@param file_path string
62-
---@param search_text string
62+
---@param search_text string | nil
6363
---@return boolean
6464
function link_utils.open_file_and_search(file_path, search_text)
6565
if not file_path or file_path == '' then
@@ -68,6 +68,11 @@ function link_utils.open_file_and_search(file_path, search_text)
6868
if file_path ~= utils.current_file_path() then
6969
vim.cmd(('edit %s'):format(file_path))
7070
end
71+
72+
if not search_text or search_text == '' then
73+
return true
74+
end
75+
7176
local result = vim.fn.search(search_text, 'W')
7277
if result == 0 then
7378
utils.echo_warning(string.format('No match found for expression: %s', search_text))

lua/orgmode/org/mappings.lua

+8-90
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ local Calendar = require('orgmode.objects.calendar')
22
local Date = require('orgmode.objects.date')
33
local EditSpecial = require('orgmode.objects.edit_special')
44
local Help = require('orgmode.objects.help')
5-
local Hyperlinks = require('orgmode.org.hyperlinks')
5+
local OrgHyperlink = require('orgmode.org.links.hyperlink')
66
local PriorityState = require('orgmode.objects.priority_state')
77
local TodoState = require('orgmode.objects.todo_state')
88
local config = require('orgmode.config')
@@ -785,18 +785,20 @@ end
785785
-- Inserts a new link after the cursor position or modifies the link the cursor is
786786
-- currently on
787787
function OrgMappings:insert_link()
788-
local link_location = vim.fn.OrgmodeInput('Links: ', '', Hyperlinks.autocomplete_links)
788+
local link_location = vim.fn.OrgmodeInput('Links: ', '', function(arg_lead)
789+
return self.links:autocomplete(arg_lead)
790+
end)
789791
if vim.trim(link_location) == '' then
790792
utils.echo_warning('No Link selected')
791793
return
792794
end
793795

794-
Hyperlinks.insert_link(link_location)
796+
self.links:insert_link(link_location)
795797
end
796798

797799
function OrgMappings:store_link()
798800
local headline = self.files:get_closest_headline()
799-
Hyperlinks.store_link_to_headline(headline)
801+
self.links:store_link_to_headline(headline)
800802
return utils.echo_info('Stored: ' .. headline:get_title())
801803
end
802804

@@ -861,7 +863,7 @@ function OrgMappings:add_note()
861863
end
862864

863865
function OrgMappings:open_at_point()
864-
local link = Hyperlinks.get_link_under_cursor()
866+
local link = OrgHyperlink.at_cursor()
865867
if not link then
866868
local date = self:_get_date_under_cursor()
867869
if date then
@@ -870,91 +872,7 @@ function OrgMappings:open_at_point()
870872
return
871873
end
872874

873-
-- handle external links (non-org or without org-specific line target)
874-
875-
if link.url:is_id() then
876-
local id = link.url:get_id() or ''
877-
local files = self.files:find_files_with_property('id', id)
878-
if #files > 0 then
879-
if #files > 1 then
880-
utils.echo_warning(string.format('Multiple files found with id: %s, jumping to first one found', id))
881-
end
882-
vim.cmd(('edit %s'):format(files[1].filename))
883-
return
884-
end
885-
886-
local headlines = self.files:find_headlines_with_property('id', id)
887-
if #headlines == 0 then
888-
return utils.echo_warning(string.format('No headline found with id: %s', id))
889-
end
890-
if #headlines > 1 then
891-
return utils.echo_warning(string.format('Multiple headlines found with id: %s', id))
892-
end
893-
local headline = headlines[1]
894-
return self:_goto_headline(headline)
895-
end
896-
897-
if link.url:is_file_line_number() then
898-
local line_number = link.url:get_line_number() or 0
899-
local file_path = link.url:get_file() or utils.current_file_path()
900-
local cmd = string.format('edit +%s %s', line_number, fs.get_real_path(file_path))
901-
vim.cmd(cmd)
902-
return vim.cmd([[normal! zv]])
903-
end
904-
905-
if link.url:is_external_url() then
906-
if vim.ui['open'] then
907-
return vim.ui.open(link.url:to_string())
908-
end
909-
if not vim.g.loaded_netrwPlugin then
910-
return utils.echo_warning('Netrw plugin must be loaded in order to open urls.')
911-
end
912-
return vim.fn['netrw#BrowseX'](link.url:to_string(), vim.fn['netrw#CheckIfRemote']())
913-
end
914-
915-
if link.url:is_file_only() then
916-
local file_path = link.url:get_file()
917-
local cmd = file_path and string.format('edit %s', fs.get_real_path(file_path)) or ''
918-
vim.cmd(cmd)
919-
vim.cmd([[normal! zv]])
920-
end
921-
922-
if link.url.protocol and not link.url:is_supported_protocol() then
923-
utils.echo_warning(string.format('Unsupported link protocol: %q', link.url.protocol))
924-
return
925-
end
926-
927-
local headlines = Hyperlinks.find_matching_links(link.url)
928-
local current_headline = self.files:get_closest_headline_or_nil()
929-
if current_headline then
930-
headlines = vim.tbl_filter(function(headline)
931-
return not current_headline:is_same(headline)
932-
end, headlines)
933-
end
934-
if #headlines == 0 then
935-
return
936-
end
937-
local headline = headlines[1]
938-
if #headlines > 1 then
939-
local longest_headline = utils.reduce(headlines, function(acc, h)
940-
return math.max(acc, h:get_headline_line_content():len())
941-
end, 0)
942-
local options = {}
943-
for i, h in ipairs(headlines) do
944-
table.insert(
945-
options,
946-
string.format('%d) %-' .. longest_headline .. 's (%s)', i, h:get_headline_line_content(), h.file.filename)
947-
)
948-
end
949-
vim.cmd([[echo "Multiple targets found. Select target:"]])
950-
local choice = vim.fn.inputlist(options)
951-
if choice < 1 or choice > #headlines then
952-
return
953-
end
954-
headline = headlines[choice]
955-
end
956-
957-
return self:_goto_headline(headline)
875+
return self.links:follow(link.url:to_string())
958876
end
959877

960878
function OrgMappings:export()

tests/plenary/ui/mappings/hyperlink_spec.lua

+6-37
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,11 @@ describe('Hyperlink mappings', function()
104104
vim.cmd([[norm ,ols]])
105105
assert.are.same({
106106
[('file:%s::*headline of target id'):format(target_file.filename)] = 'headline of target id',
107-
}, require('orgmode.org.hyperlinks').stored_links)
107+
---@diagnostic disable-next-line: invisible
108+
}, require('orgmode').links.stored_links)
108109
end)
109110

110111
it('should store link to a headline with id', function()
111-
require('orgmode.org.hyperlinks').stored_links = {}
112112
local org = require('orgmode').setup({
113113
org_id_link_to_org_use_id = true,
114114
})
@@ -123,9 +123,12 @@ describe('Hyperlink mappings', function()
123123
})
124124

125125
org:init()
126+
---@diagnostic disable-next-line: invisible
127+
require('orgmode').links.stored_links = {}
126128
vim.fn.cursor(4, 10)
127129
vim.cmd([[norm ,ols]])
128-
local stored_links = require('orgmode.org.hyperlinks').stored_links
130+
---@diagnostic disable-next-line: invisible
131+
local stored_links = require('orgmode').links.stored_links
129132
local keys = vim.tbl_keys(stored_links)
130133
local values = vim.tbl_values(stored_links)
131134
assert.is.True(keys[1]:match('^id:' .. OrgId.uuid_pattern .. '.*$') ~= nil)
@@ -207,38 +210,4 @@ describe('Hyperlink mappings', function()
207210
vim.cmd([[norm ,oo]])
208211
assert.is.same(' --> eleven <--', vim.api.nvim_get_current_line())
209212
end)
210-
211-
it('should follow link to certain line (nvim-orgmode compatibility)', function()
212-
local target_file = helpers.create_file({
213-
'* Test hyperlink',
214-
' - some',
215-
' - boiler',
216-
' - plate',
217-
'** some headline',
218-
' - more',
219-
' - boiler',
220-
' - plate',
221-
' -> 9',
222-
' -> 10',
223-
' --> eleven <--',
224-
' -> 12',
225-
' -> 13',
226-
' -> 14',
227-
' -> 15 <--',
228-
})
229-
vim.cmd([[norm w]])
230-
assert.is.truthy(target_file)
231-
if not target_file then
232-
return
233-
end
234-
local dir = vim.fs.dirname(target_file.filename)
235-
local url = target_file.filename:gsub(dir, '.')
236-
helpers.create_file({
237-
string.format('This [[%s +11][link]] should bring us to the 11th line.', url),
238-
})
239-
vim.cmd([[norm w]])
240-
vim.fn.cursor(1, 10)
241-
vim.cmd([[norm ,oo]])
242-
assert.is.same(' --> eleven <--', vim.api.nvim_get_current_line())
243-
end)
244213
end)

0 commit comments

Comments
 (0)