Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(links)!: Use refactor links structure #803

Merged
merged 3 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions lua/orgmode/api/file.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
---@diagnostic disable: invisible
local OrgHeadline = require('orgmode.api.headline')
local Hyperlinks = require('orgmode.org.hyperlinks')
local org = require('orgmode')

---@class OrgApiFile
Expand Down Expand Up @@ -112,12 +111,12 @@ function OrgFile:get_link()
-- do remote edit
return org.files
:update_file(filename, function(file)
return Hyperlinks.get_link_to_file(file)
return org.links:get_link_to_file(file)
end)
:wait()
end

return Hyperlinks.get_link_to_file(self._file)
return org.links:get_link_to_file(self._file)
end

return OrgFile
5 changes: 2 additions & 3 deletions lua/orgmode/api/headline.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ local PriorityState = require('orgmode.objects.priority_state')
local Date = require('orgmode.objects.date')
local Calendar = require('orgmode.objects.calendar')
local Promise = require('orgmode.utils.promise')
local Hyperlinks = require('orgmode.org.hyperlinks')
local org = require('orgmode')

---@class OrgApiHeadline
Expand Down Expand Up @@ -281,12 +280,12 @@ function OrgHeadline:get_link()
-- do remote edit
return org.files
:update_file(filename, function(_)
return Hyperlinks.get_link_to_headline(self._section)
return org.links:get_link_to_headline(self._section)
end)
:wait()
end

return Hyperlinks.get_link_to_headline(self._section)
return org.links:get_link_to_headline(self._section)
end

return OrgHeadline
4 changes: 2 additions & 2 deletions lua/orgmode/api/init.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
---@diagnostic disable: invisible
local OrgFile = require('orgmode.api.file')
local OrgHeadline = require('orgmode.api.headline')
local Hyperlinks = require('orgmode.org.hyperlinks')
local orgmode = require('orgmode')

---@class OrgApiRefileOpts
Expand Down Expand Up @@ -110,7 +109,8 @@ end
--- @param link_location string
--- @return boolean
function OrgApi.insert_link(link_location)
Hyperlinks.insert_link(link_location)
orgmode.links:insert_link(link_location)
return true
end

return OrgApi
6 changes: 3 additions & 3 deletions lua/orgmode/files/file.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ local Headline = require('orgmode.files.headline')
local ts = vim.treesitter
local config = require('orgmode.config')
local Block = require('orgmode.files.elements.block')
local Link = require('orgmode.org.hyperlinks.link')
local Hyperlink = require('orgmode.org.links.hyperlink')
local Range = require('orgmode.files.elements.range')
local Memoize = require('orgmode.utils.memoize')

Expand Down Expand Up @@ -722,7 +722,7 @@ function OrgFile:get_archive_file_location()
end

memoize('get_links')
---@return OrgLink[]
---@return OrgHyperlink[]
function OrgFile:get_links()
self:parse(true)
local ts_query = ts_utils.get_query([[
Expand All @@ -736,7 +736,7 @@ function OrgFile:get_links()
for _, match in ts_query:iter_captures(self.root, self:_get_source()) do
local line = match:start()
if not processed_lines[line] then
vim.list_extend(links, Link.all_from_line(self.lines[line + 1], line + 1))
vim.list_extend(links, Hyperlink.all_from_line(self.lines[line + 1], line + 1))
processed_lines[line] = true
end
end
Expand Down
7 changes: 2 additions & 5 deletions lua/orgmode/org/autocompletion/sources/hyperlinks.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
local Hyperlinks = require('orgmode.org.hyperlinks')
local Link = require('orgmode.org.hyperlinks.link')
---@class OrgCompletionHyperlinks:OrgCompletionSource
---@field completion OrgCompletion
---@field private pattern vim.regex
Expand All @@ -24,11 +22,10 @@ function OrgCompletionHyperlinks:get_start(context)
return self.pattern:match_str(context.line)
end

---@param context OrgCompletionContext
---@return string[]
function OrgCompletionHyperlinks:get_results(context)
local link = Link:new(context.base)
local result, mapper = Hyperlinks.find_matching_links(link.url)
return mapper(result)
return self.completion.links:autocomplete(context.base)
end

return OrgCompletionHyperlinks
13 changes: 12 additions & 1 deletion lua/orgmode/org/links/types/headline_search.lua
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,13 @@ function OrgLinkHeadlineSearch:follow(link)
end

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

if file then
if is_file_only then
return link_utils.goto_file(file)
end

local pattern = ('<<<?(%s[^>]*)>>>?'):format(opts.headline_text):lower()
local headlines = file:find_headlines_matching_search_term(pattern, true)
if #headlines == 0 then
Expand All @@ -44,7 +49,13 @@ function OrgLinkHeadlineSearch:follow(link)
)
end

return link_utils.open_file_and_search(opts.file_path, opts.headline_text)
local search_text = opts.headline_text

if is_file_only then
search_text = ''
end

return link_utils.open_file_and_search(opts.file_path, search_text)
end

---@param link string
Expand Down
7 changes: 6 additions & 1 deletion lua/orgmode/org/links/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ function link_utils.goto_oneof_headlines(headlines, file_path, error_message)
end

---@param file_path string
---@param search_text string
---@param search_text string | nil
---@return boolean
function link_utils.open_file_and_search(file_path, search_text)
if not file_path or file_path == '' then
Expand All @@ -68,6 +68,11 @@ function link_utils.open_file_and_search(file_path, search_text)
if file_path ~= utils.current_file_path() then
vim.cmd(('edit %s'):format(file_path))
end

if not search_text or search_text == '' then
return true
end

local result = vim.fn.search(search_text, 'W')
if result == 0 then
utils.echo_warning(string.format('No match found for expression: %s', search_text))
Expand Down
98 changes: 8 additions & 90 deletions lua/orgmode/org/mappings.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ local Calendar = require('orgmode.objects.calendar')
local Date = require('orgmode.objects.date')
local EditSpecial = require('orgmode.objects.edit_special')
local Help = require('orgmode.objects.help')
local Hyperlinks = require('orgmode.org.hyperlinks')
local OrgHyperlink = require('orgmode.org.links.hyperlink')
local PriorityState = require('orgmode.objects.priority_state')
local TodoState = require('orgmode.objects.todo_state')
local config = require('orgmode.config')
Expand Down Expand Up @@ -785,18 +785,20 @@ end
-- Inserts a new link after the cursor position or modifies the link the cursor is
-- currently on
function OrgMappings:insert_link()
local link_location = vim.fn.OrgmodeInput('Links: ', '', Hyperlinks.autocomplete_links)
local link_location = vim.fn.OrgmodeInput('Links: ', '', function(arg_lead)
return self.links:autocomplete(arg_lead)
end)
if vim.trim(link_location) == '' then
utils.echo_warning('No Link selected')
return
end

Hyperlinks.insert_link(link_location)
self.links:insert_link(link_location)
end

function OrgMappings:store_link()
local headline = self.files:get_closest_headline()
Hyperlinks.store_link_to_headline(headline)
self.links:store_link_to_headline(headline)
return utils.echo_info('Stored: ' .. headline:get_title())
end

Expand Down Expand Up @@ -861,7 +863,7 @@ function OrgMappings:add_note()
end

function OrgMappings:open_at_point()
local link = Hyperlinks.get_link_under_cursor()
local link = OrgHyperlink.at_cursor()
if not link then
local date = self:_get_date_under_cursor()
if date then
Expand All @@ -870,91 +872,7 @@ function OrgMappings:open_at_point()
return
end

-- handle external links (non-org or without org-specific line target)

if link.url:is_id() then
local id = link.url:get_id() or ''
local files = self.files:find_files_with_property('id', id)
if #files > 0 then
if #files > 1 then
utils.echo_warning(string.format('Multiple files found with id: %s, jumping to first one found', id))
end
vim.cmd(('edit %s'):format(files[1].filename))
return
end

local headlines = self.files:find_headlines_with_property('id', id)
if #headlines == 0 then
return utils.echo_warning(string.format('No headline found with id: %s', id))
end
if #headlines > 1 then
return utils.echo_warning(string.format('Multiple headlines found with id: %s', id))
end
local headline = headlines[1]
return self:_goto_headline(headline)
end

if link.url:is_file_line_number() then
local line_number = link.url:get_line_number() or 0
local file_path = link.url:get_file() or utils.current_file_path()
local cmd = string.format('edit +%s %s', line_number, fs.get_real_path(file_path))
vim.cmd(cmd)
return vim.cmd([[normal! zv]])
end

if link.url:is_external_url() then
if vim.ui['open'] then
return vim.ui.open(link.url:to_string())
end
if not vim.g.loaded_netrwPlugin then
return utils.echo_warning('Netrw plugin must be loaded in order to open urls.')
end
return vim.fn['netrw#BrowseX'](link.url:to_string(), vim.fn['netrw#CheckIfRemote']())
end

if link.url:is_file_only() then
local file_path = link.url:get_file()
local cmd = file_path and string.format('edit %s', fs.get_real_path(file_path)) or ''
vim.cmd(cmd)
vim.cmd([[normal! zv]])
end

if link.url.protocol and not link.url:is_supported_protocol() then
utils.echo_warning(string.format('Unsupported link protocol: %q', link.url.protocol))
return
end

local headlines = Hyperlinks.find_matching_links(link.url)
local current_headline = self.files:get_closest_headline_or_nil()
if current_headline then
headlines = vim.tbl_filter(function(headline)
return not current_headline:is_same(headline)
end, headlines)
end
if #headlines == 0 then
return
end
local headline = headlines[1]
if #headlines > 1 then
local longest_headline = utils.reduce(headlines, function(acc, h)
return math.max(acc, h:get_headline_line_content():len())
end, 0)
local options = {}
for i, h in ipairs(headlines) do
table.insert(
options,
string.format('%d) %-' .. longest_headline .. 's (%s)', i, h:get_headline_line_content(), h.file.filename)
)
end
vim.cmd([[echo "Multiple targets found. Select target:"]])
local choice = vim.fn.inputlist(options)
if choice < 1 or choice > #headlines then
return
end
headline = headlines[choice]
end

return self:_goto_headline(headline)
return self.links:follow(link.url:to_string())
end

function OrgMappings:export()
Expand Down
43 changes: 6 additions & 37 deletions tests/plenary/ui/mappings/hyperlink_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,11 @@ describe('Hyperlink mappings', function()
vim.cmd([[norm ,ols]])
assert.are.same({
[('file:%s::*headline of target id'):format(target_file.filename)] = 'headline of target id',
}, require('orgmode.org.hyperlinks').stored_links)
---@diagnostic disable-next-line: invisible
}, require('orgmode').links.stored_links)
end)

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

org:init()
---@diagnostic disable-next-line: invisible
require('orgmode').links.stored_links = {}
vim.fn.cursor(4, 10)
vim.cmd([[norm ,ols]])
local stored_links = require('orgmode.org.hyperlinks').stored_links
---@diagnostic disable-next-line: invisible
local stored_links = require('orgmode').links.stored_links
local keys = vim.tbl_keys(stored_links)
local values = vim.tbl_values(stored_links)
assert.is.True(keys[1]:match('^id:' .. OrgId.uuid_pattern .. '.*$') ~= nil)
Expand Down Expand Up @@ -207,38 +210,4 @@ describe('Hyperlink mappings', function()
vim.cmd([[norm ,oo]])
assert.is.same(' --> eleven <--', vim.api.nvim_get_current_line())
end)

it('should follow link to certain line (nvim-orgmode compatibility)', function()
local target_file = helpers.create_file({
'* Test hyperlink',
' - some',
' - boiler',
' - plate',
'** some headline',
' - more',
' - boiler',
' - plate',
' -> 9',
' -> 10',
' --> eleven <--',
' -> 12',
' -> 13',
' -> 14',
' -> 15 <--',
})
vim.cmd([[norm w]])
assert.is.truthy(target_file)
if not target_file then
return
end
local dir = vim.fs.dirname(target_file.filename)
local url = target_file.filename:gsub(dir, '.')
helpers.create_file({
string.format('This [[%s +11][link]] should bring us to the 11th line.', url),
})
vim.cmd([[norm w]])
vim.fn.cursor(1, 10)
vim.cmd([[norm ,oo]])
assert.is.same(' --> eleven <--', vim.api.nvim_get_current_line())
end)
end)
Loading