zettelkasten.nvim/lua/zettelkasten/action.lua
Marty Oehme 3a9e04d3ce
Refactor open actions
Open actions now make use of a 'link' data structure containing a text
and ref string, and the respective start and end positions on the line.

Additionally, parsers are now simple objects containing extraction regex
for extracting their text and ref link individually.
2020-11-04 21:37:16 +01:00

86 lines
2.7 KiB
Lua

local A = {}
local o = require 'zettelkasten.options'
local BIGNUMBER = 10000000
local parsers = {
markdown = {ref = "%[.-%]%((.-)%)", text = "%[(.-)%]%(.-%)"},
wiki = {ref = "%[%[(.-)|?.-%]%]", text = "%[%[.-|?(.-)%]%]"}
}
-- Opens the link passed in in the editor's current buffer.
-- Requires a link object passed in.
function A.open(link)
if not link or not link.ref then return end
-- TODO follow: go to anchor, fall back to filename
vim.api.nvim_command(string.format("edit %s", link.ref))
end
-- Gets the input at the current buffer cursor and opens it
-- in the current buffer.
-- Takes an optional style of link following to use,
-- superseding the one set in options.
function A.open_selected(style)
local style = style or o.zettel().link_following
if style == 'line' then
A.open(A.get_next_link_on_line())
elseif style == 'cursor' then
A.open(A.get_link_under_cursor())
end
end
-- Return all links contained in the input given in an array.
-- Returned link tables have the following structure:
-- link = { text=, ref=, startpos=27, endpos=65 }
function A.extract_all_links(input)
if not input then return end
local links = {}
local curpos = 1
for _, parser in pairs(parsers) do
while input:find(parser.ref, curpos) do
local ref = input:match(parser.ref, curpos)
local text = input:match(parser.text, curpos)
local startpos, endpos = input:find(parser.ref, curpos)
table.insert(links, {
ref = ref,
text = text,
startpos = startpos,
endpos = endpos
})
curpos = endpos
end
end
return links
end
-- Returns the link currently under cursor, roughly the vim equivalent of yiW.
-- Works for links containing spaces in their text or reference link.
function A.get_link_under_cursor()
local curpos = vim.api.nvim_win_get_cursor(0)[2]
local links = A.extract_all_links(vim.api.nvim_get_current_line())
for _, link in pairs(links) do
if link.startpos <= curpos + 1 and link.endpos > curpos then
return link
end
end
return nil
end
-- Returns the next link of the line from the cursor onwards.
function A.get_next_link_on_line()
local curpos = vim.api.nvim_win_get_cursor(0)[2]
local links = A.extract_all_links(vim.api.nvim_get_current_line())
local nearestpos = BIGNUMBER
local nearestlink
for k, link in pairs(links) do
if link.endpos > curpos and link.endpos < nearestpos then
nearestpos = link.endpos
nearestlink = link
end
end
return nearestlink
end
return {open = A.open, open_selected = A.open_selected}