Skip to content

Commit

Permalink
Enable link opening from agenda
Browse files Browse the repository at this point in the history
  • Loading branch information
jgollenz committed Jul 3, 2022
1 parent 72a7a62 commit 8907992
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 19 deletions.
66 changes: 66 additions & 0 deletions lua/orgmode/agenda/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ local AgendaSearchView = require('orgmode.agenda.views.search')
local AgendaTodosView = require('orgmode.agenda.views.todos')
local AgendaTagsView = require('orgmode.agenda.views.tags')
local AgendaView = require('orgmode.agenda.views.agenda')
local Hyperlinks = require('orgmode.org.hyperlinks')

---@class Agenda
---@field content table[]
Expand Down Expand Up @@ -245,6 +246,71 @@ function Agenda:change_todo_state()
})
end

function Agenda:open_link()
local link = Hyperlinks.get_link_under_cursor()
if not link then
return
end
local parts = vim.split(link, '][', true)
local url = parts[1]
local link_ctx = { base = url, skip_add_prefix = true }
-- file links
if url:find('^file:') then
if url:find(' +', 1, true) then
parts = vim.split(url, ' +', true)
url = parts[1]
local line_number = parts[2]
vim.cmd(string.format('edit +%s %s', line_number, url:sub(6)))
vim.cmd([[normal! zv]])
return
end

if url:find('^file:(.-)::') then
link_ctx.line = url
else
vim.cmd(string.format('edit %s', url:sub(6)))
vim.cmd([[normal! zv]])
return
end
end
-- web links
if url:find('^https?://') then
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'](url, vim.fn['netrw#CheckIfRemote']())
end
-- fallback: filepath
local stat = vim.loop.fs_stat(url)
if stat and stat.type == 'file' then
return vim.cmd(string.format('edit %s', url))
end
-- headline link
local headlines = Hyperlinks.find_matching_links(link_ctx)
if #headlines == 0 then
utils.echo_warning('foobar')
return
end
local headline = headlines[1]
if #headlines > 1 then
local longest_headline = utils.reduce(headlines, function(acc, h)
return math.max(acc, h.line:len())
end, 0)
local options = {}
for i, h in ipairs(headlines) do
table.insert(options, string.format('%d) %-' .. longest_headline .. 's (%s)', i, h.line, h.file))
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
vim.cmd(string.format('edit %s', headline.file))
vim.fn.cursor(headline.range.start_line, 0)
end

function Agenda:clock_in()
return self:_remote_edit({
action = 'clock.org_clock_in',
Expand Down
1 change: 1 addition & 0 deletions lua/orgmode/config/defaults.lua
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ return {
org_agenda_quit = 'q',
org_agenda_switch_to = '<CR>',
org_agenda_goto = '<TAB>',
org_agenda_open_link = '<prefix>o',
org_agenda_goto_date = 'J',
org_agenda_redo = 'r',
org_agenda_todo = 't',
Expand Down
1 change: 1 addition & 0 deletions lua/orgmode/config/mappings/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ return {
{ opts = { desc = 'org open agenda item (same buffer)' } }
),
org_agenda_goto = m.action('agenda.goto_item', { opts = { desc = 'org open agenda item (split buffer)' } }),
org_agenda_open_link = m.action('agenda.open_link', { opts = { desc = 'org open hyperlink' } }),
org_agenda_goto_date = m.action('agenda.goto_date', { opts = { desc = 'org goto date' } }),
org_agenda_redo = m.action('agenda.redo', { opts = { desc = 'org redo' } }),
org_agenda_todo = m.action('agenda.change_todo_state', { opts = { desc = 'org cycle todo state' } }),
Expand Down
18 changes: 18 additions & 0 deletions lua/orgmode/org/hyperlinks.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,24 @@ local Files = require('orgmode.parser.files')
local utils = require('orgmode.utils')
local Hyperlinks = {}

---@return string|nil
function Hyperlinks.get_link_under_cursor()
local found_link = nil
local links = {}
local line = vim.fn.getline('.')
local col = vim.fn.col('.')
for link in line:gmatch('%[%[(.-)%]%]') do
local start_from = #links > 0 and links[#links].to or nil
local from, to = line:find('%[%[(.-)%]%]', start_from)
if col >= from and col <= to then
found_link = link
break
end
table.insert(links, { link = link, from = from, to = to })
end
return found_link
end

local function get_file_from_context(ctx)
return (
ctx.hyperlinks and ctx.hyperlinks.filepath and Files.get(ctx.hyperlinks.filepath, true)
Expand Down
20 changes: 1 addition & 19 deletions lua/orgmode/org/mappings.lua
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,7 @@ function OrgMappings:open_at_point()
return self.agenda:open_day(date)
end

local link = self:_get_link_under_cursor()
local link = Hyperlinks.get_link_under_cursor()
if not link then
return
end
Expand Down Expand Up @@ -910,22 +910,4 @@ function OrgMappings:_adjust_date(amount, span, fallback)
return vim.api.nvim_feedkeys(utils.esc(fallback), 'n', true)
end

---@return string|nil
function OrgMappings:_get_link_under_cursor()
local found_link = nil
local links = {}
local line = vim.fn.getline('.')
local col = vim.fn.col('.')
for link in line:gmatch('%[%[(.-)%]%]') do
local start_from = #links > 0 and links[#links].to or nil
local from, to = line:find('%[%[(.-)%]%]', start_from)
if col >= from and col <= to then
found_link = link
break
end
table.insert(links, { link = link, from = from, to = to })
end
return found_link
end

return OrgMappings

0 comments on commit 8907992

Please sign in to comment.