Move link extraction to link module

Both link creation and extraction, all derived from parser
functionality, should run within the link module and actions should only
make use of it to invoke editor functionality.
This commit is contained in:
Marty Oehme 2020-11-04 22:04:31 +01:00
parent 3a9e04d3ce
commit 2a3e213ac8
Signed by: Marty
GPG key ID: B7538B8F50A1C800
3 changed files with 104 additions and 73 deletions

View file

@ -1,14 +1,10 @@
local A = {}
local o = require 'zettelkasten.options'
local link = require 'zettelkasten.link'
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)
@ -30,35 +26,11 @@ function A.open_selected(style)
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())
local links = link.extract_all(vim.api.nvim_get_current_line())
for _, link in pairs(links) do
if link.startpos <= curpos + 1 and link.endpos > curpos then
return link
@ -67,10 +39,10 @@ function A.get_link_under_cursor()
return nil
end
-- Returns the next link of the line from the cursor onwards.
-- Returns the next link of the current 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 links = link.extract_all(vim.api.nvim_get_current_line())
local nearestpos = BIGNUMBER
local nearestlink
for k, link in pairs(links) do

View file

@ -3,6 +3,27 @@ local L = {}
local o = require 'zettelkasten.options'
local a = require 'zettelkasten.anchor'
local parsers = {
markdown = {
ref = "%[.-%]%((.-)%)",
text = "%[(.-)%]%(.-%)",
style_func = function(link, text, extension)
return "[" .. L.trimmed(text) .. "](" .. link .. extension .. ")"
end
},
wiki = {
ref = "%[%[(.-)|?.-%]%]",
text = "%[%[.-|?(.-)%]%]",
style_func = function(link, text)
local pipe = ""
text = L.trimmed(text)
if text and text ~= "" then pipe = "|" .. text end
return "[[" .. link .. pipe .. "]]"
end
}
}
-- Returns the text cleaned up to be more useful in a link.
-- Spaces are replaced by dashes and everything is lowercased.
function L.urlify(text)
@ -22,7 +43,7 @@ end
-- Returns text with surrounding whitespace trimmed. Returns empty string
-- if only whitespace.
local function trimmed(text)
function L.trimmed(text)
if not text then return end
return text:match '^()%s*$' and '' or text:match '^%s*(.*%S)'
end
@ -32,7 +53,7 @@ end
function L.style_markdown(link, text)
must_have(link)
return "[" .. trimmed(text) .. "](" .. link .. ")"
return "[" .. L.trimmed(text) .. "](" .. link .. ")"
end
-- Returns a wikilink-compatible transformation of the link and text combination
@ -40,7 +61,7 @@ end
function L.style_wiki(link, text)
must_have(link)
local pipe = ""
text = trimmed(text)
text = L.trimmed(text)
if text and text ~= "" then pipe = "|" .. text end
return "[[" .. link .. pipe .. "]]"
@ -54,11 +75,11 @@ function L.create(anchor, text, style)
style = style or o.zettel().link_style
if style == "markdown" then
local link = (a.prepend(anchor, L.urlify(text)))
return L.style_markdown(L.append_extension(link), text)
local link = (a.prepend(anchor, L.urlify(L.trimmed(text))))
return parsers.markdown.style_func(link, text, o.zettel().extension)
elseif style == "wiki" then
return L.style_wiki(anchor, text)
return parsers.wiki.style_func(anchor, text)
end
error("Link creation failed.")
end
@ -71,4 +92,36 @@ function L.new(text, style)
return L.create(anchor, text, style)
end
return L
-- 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 L.extract_all(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
return {
new = L.new,
create = L.create,
style_wiki = L.style_wiki,
style_markdown = L.style_markdown,
append_extension = L.append_extension,
urlify = L.urlify,
extract_all = L.extract_all
}

View file

@ -27,40 +27,6 @@ describe("append_extension", function()
end)
end)
describe("style_markdown", function()
it("should correctly apply transformations to link and text", function()
assert.same("[My AWESOME Link](1910291645_my-awesome-link.md)",
link.style_markdown("1910291645_my-awesome-link.md",
"My AWESOME Link"))
end)
it("should trim whitespace for the text area", function()
assert.same("[](1910291645_my-awesome-link.md)",
link.style_markdown("1910291645_my-awesome-link.md", " "))
assert.same("[hi](1910291645_my-awesome-link.md)", link.style_markdown(
"1910291645_my-awesome-link.md", " hi "))
end)
it("should error if no link provided", function()
assert.is_error(function() link.style_markdown("", "mytext") end)
assert.is_error(function() link.style_markdown(nil, "mytext") end)
end)
end)
describe("style_wiki", function()
it("should error if no link provided", function()
assert.is_error(function() link.style_wiki("", "mytext") end)
assert.is_error(function() link.style_wiki(nil, "mytext") end)
end)
it("should correctly apply transformations to link and text", function()
assert.same("[[1910291645|My AWESOME Link]]",
link.style_wiki("1910291645", "My AWESOME Link"))
end)
it("should trim whitespace for the text area", function()
assert.same("[[1910291645]]", link.style_wiki("1910291645", " "))
assert.same("[[1910291645|hi]]",
link.style_wiki("1910291645", " hi "))
end)
end)
describe("create", function()
before_each(function()
vim.g.zettel_extension = ".md"
@ -82,6 +48,46 @@ describe("create", function()
vim.g.zettel_link_style = "wiki"
assert.same("[[1910291645]]", link.create("1910291645"))
end)
describe("wiki link styling", function()
it("should error if no link provided", function()
assert.is_error(function() link.style_wiki("", "mytext") end)
assert.is_error(function() link.style_wiki(nil, "mytext") end)
end)
it("should correctly apply transformations to link and text", function()
assert.same("[[1910291645|My AWESOME Link]]",
link.create("1910291645", "My AWESOME Link", "wiki"))
end)
it("should trim whitespace for the text area", function()
assert.same("[[1910291645]]",
link.create("1910291645", " ", "wiki"))
assert.same("[[1910291645|hi]]",
link.create("1910291645", " hi ", "wiki"))
end)
describe("markdown link styling", function()
it("should correctly apply transformations to link and text",
function()
assert.same("[My AWESOME Link](1910291645_my-awesome-link.md)",
link.create("1910291645", "My AWESOME Link",
"markdown"))
end)
it("should trim whitespace for the text area", function()
assert.same("[](1910291645.md)",
link.create("1910291645", " ", "markdown"))
assert.same("[hi](1910291645_hi.md)",
link.create("1910291645", " hi ", "markdown"))
end)
it("should error if no link provided", function()
assert.is_error(function()
link.style_markdown("", "mytext")
end)
assert.is_error(function()
link.style_markdown(nil, "mytext")
end)
end)
end)
end)
end)
describe("new", function()