From 2a3e213ac80a071ab0ed5e3418d49a9b11ac1396 Mon Sep 17 00:00:00 2001 From: Marty Oehme Date: Wed, 4 Nov 2020 22:04:31 +0100 Subject: [PATCH] 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. --- lua/zettelkasten/action.lua | 36 ++--------------- lua/zettelkasten/link.lua | 67 ++++++++++++++++++++++++++---- lua/zettelkasten/link_spec.lua | 74 ++++++++++++++++++---------------- 3 files changed, 104 insertions(+), 73 deletions(-) diff --git a/lua/zettelkasten/action.lua b/lua/zettelkasten/action.lua index 1c60076..a7a5c22 100644 --- a/lua/zettelkasten/action.lua +++ b/lua/zettelkasten/action.lua @@ -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 diff --git a/lua/zettelkasten/link.lua b/lua/zettelkasten/link.lua index 6100310..35e1aed 100644 --- a/lua/zettelkasten/link.lua +++ b/lua/zettelkasten/link.lua @@ -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 +} diff --git a/lua/zettelkasten/link_spec.lua b/lua/zettelkasten/link_spec.lua index be39a44..03a8475 100644 --- a/lua/zettelkasten/link_spec.lua +++ b/lua/zettelkasten/link_spec.lua @@ -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()