Move anchor prepend function to anchor module

This commit is contained in:
Marty Oehme 2020-10-31 11:01:53 +01:00
parent 1742b74d5a
commit 320007e14b
Signed by: Marty
GPG key ID: B7538B8F50A1C800
8 changed files with 83 additions and 67 deletions

View file

@ -4,12 +4,12 @@ To develop / debug:
start neovim with `nvim --cmd "set rtp+=$(pwd)" .` to automatically load the files in project dir as if they were on path start neovim with `nvim --cmd "set rtp+=$(pwd)" .` to automatically load the files in project dir as if they were on path
## TODO: feature wishlist ## TODO: needed functionality
* [ ] note creation (new anchor) * [ ] note creation (new anchor)
* [x] create anchor * [x] create anchor
* [ ] *unique* anchor creation * [ ] *unique* anchor creation
* [ ] create link (md / wiki) * [x] create link (md / wiki)
* [ ] note listing (anchors / titles, no anchor) * [ ] note listing (anchors / titles, no anchor)
* [ ] list anchors * [ ] list anchors
* [ ] list filenames * [ ] list filenames
@ -25,19 +25,24 @@ start neovim with `nvim --cmd "set rtp+=$(pwd)" .` to automatically load the fi
* [ ] options * [ ] options
* [x] zettel anchor separator * [x] zettel anchor separator
* [x] zettel extension * [x] zettel extension
* [ ] link style (wiki/markdown) custom? * [x] link style (wiki/markdown)
* [ ] recursive lookup for zettel * [ ] custom link style?
* [ ] recursive dir lookup for zettel
* [ ] zettel anchor regex * [ ] zettel anchor regex
* [ ] backlinks (via rg for filename anchor?)
* [ ] keep tree of notes cached? ## TODO: nice-to-haves
* [ ] completion engine (e.g. for `completion-nvim`, look in completion_buffers/completion-tags for reference) * [ ] completion engine (e.g. for `completion-nvim`, look in completion_buffers/completion-tags for reference)
* [ ] zettel caching for big directories * [ ] zettel caching for big directories
* [ ] backlinks (via rg for filename anchor?)
* [ ] keep tree of notes cached?
* [ ] zettel maintenance * [ ] zettel maintenance
* [ ] fix malformed anchors * [ ] fix malformed anchors
* [ ] add missing anchors * [ ] add missing anchors
* [ ] 'rename' anchor (goes against stability?) * [ ] 'rename' anchor (goes against stability?)
* [ ] recognize duplicate anchors (in directory, when listing, etc) * [ ] recognize duplicate anchors (in directory, when listing, etc)
* [ ] provide option to rename and automatically change backlinks * [ ] provide option to rename and automatically change backlinks
* [ ] zettel 'lens' (preview first headline + content of linked zettel through floating window etc, on keypress)
* anchor creation * anchor creation
* *must* be unique * *must* be unique

View file

@ -1,12 +1,14 @@
local A = {} local A = {}
local o = require 'zettelkasten.options'
-- Return a valid zettelkasten anchor, -- Return a valid zettelkasten anchor,
-- composed of yymmddHHMM. -- composed of yymmddHHMM.
-- --
-- date can be passed in as a table containing a year, a month, a day, an hour, -- date can be passed in as a table containing a year, a month, a day, an hour,
-- and a minute key. Returns nil if the date passed in is invalid. -- and a minute key. Returns nil if the date passed in is invalid.
-- If no date is passed in, returns Zettel anchor for current moment. -- If no date is passed in, returns Zettel anchor for current moment.
function A.create_anchor(date) function A.create(date)
local timestamp local timestamp
if pcall(function() timestamp = os.time(date) end) then if pcall(function() timestamp = os.time(date) end) then
return os.date('%y%m%d%H%M', timestamp) return os.date('%y%m%d%H%M', timestamp)
@ -15,4 +17,13 @@ function A.create_anchor(date)
end end
end end
-- TODO think about making clean/anchor/extension function module private
-- Returns the text passed in with the anchor passed in prepended.
function A.prepend(anchor, text)
if not text or text == "" then return anchor end
text = anchor .. o.anchor().separator .. text
return text
end
return A return A

View file

@ -4,15 +4,38 @@ Test_date = {year = 2019, month = 10, day = 29, hour = 16, min = 45}
before_each(function() _G.vim = {g = {}, b = {}} end) before_each(function() _G.vim = {g = {}, b = {}} end)
after_each(function() _G.vim = nil end) after_each(function() _G.vim = nil end)
describe("anchor creation", function() describe("create", function()
it("should return zettel anchor from time passed in", it("should return zettel anchor from time passed in",
function() assert.same("1910291645", A.create_anchor(Test_date)) end) function() assert.same("1910291645", A.create(Test_date)) end)
it( it(
"should return zettel anchor from current moment if no argument passed in", "should return zettel anchor from current moment if no argument passed in",
function() assert.same(os.date('%y%m%d%H%M'), A.create_anchor()) end) function() assert.same(os.date('%y%m%d%H%M'), A.create()) end)
it("should return nil if argument passed in is invalid", function() it("should return nil if argument passed in is invalid",
assert.is_nil(A.create_anchor("My grandmother is lovely.")) function() assert.is_nil(A.create("My grandmother is lovely.")) end)
end)
describe("prepend", function()
it("should append text to anchor", function()
assert.same("1910291645_isappended",
A.prepend("1910291645", "isappended"))
end)
it("should not add a separator if no text appended",
function() assert.same("1910291645", A.prepend("1910291645", "")) end)
it("should return solely the anchor if no text is passed in",
function() assert.same("1910291645", A.prepend("1910291645", nil)) end)
it("should return solely the anchor if empty text is passed in",
function() assert.same("1910291645", A.prepend("1910291645", "")) end)
it("should add contents of g:zettel_anchor_separator variable to text",
function()
vim.g.zettel_anchor_separator = "SEP"
assert.same("1910291645SEParated", A.prepend("1910291645", "arated"))
end)
it("should add contents of b:zettel_anchor_separator variable to text",
function()
vim.b.zettel_anchor_separator = "---"
assert.same("1910291645---arated", A.prepend("1910291645", "arated"))
end) end)
end) end)

View file

@ -12,6 +12,9 @@ function ZK.get_zettel_list(path, recursive)
return ls.get_anchors_and_paths(path, recursive or false, ZK.options) return ls.get_anchors_and_paths(path, recursive or false, ZK.options)
end end
-- Return a valid zettelkasten anchor for the current time,
-- composed of yymmddHHMM.
function ZK.create_anchor() return a.create() end
return { return {
get_zettel_list = ZK.get_zettel_list get_zettel_list = ZK.get_zettel_list

View file

@ -1,5 +1,7 @@
ZK = require 'zettelkasten.init' ZK = require 'zettelkasten.init'
describe("Zettelkasten", function() describe("Zettelkasten", function()
it("should create an anchor for the current datetime",
function() assert.same(os.date('%y%m%d%H%M'), ZK.create_anchor()) end)
end) end)

View file

@ -3,19 +3,9 @@ local L = {}
local o = require 'zettelkasten.options' local o = require 'zettelkasten.options'
local a = require 'zettelkasten.anchor' local a = require 'zettelkasten.anchor'
-- TODO split up into clean/anchor/style functions, make private
-- Returns a link to a markdown file with the anchor replaced with a zettel anchor,
-- Returns the text passed in with the anchor passed in prepended,
function L.prepend_anchor(anchor, text)
if not text or text == "" then return anchor end
text = anchor .. o.anchor().separator .. text
return text
end
-- Returns the text cleaned up to be more useful in a link. -- Returns the text cleaned up to be more useful in a link.
-- Spaces are replaced by dashes and everything is lowercased. -- Spaces are replaced by dashes and everything is lowercased.
function L.clean(text) function L.urlify(text)
text = text or "" text = text or ""
return text:lower():gsub(" ", "-") return text:lower():gsub(" ", "-")
end end
@ -24,10 +14,14 @@ end
-- at the end. -- at the end.
function L.append_extension(text) return text .. o.zettel().extension end function L.append_extension(text) return text .. o.zettel().extension end
local function check_link_empty(link) local function must_have(content)
if not link or link == "" then error("Link is not allowed to be empty.") end if not content or content == "" then
error("Link is not allowed to be empty.")
end
end end
-- Returns text with surrounding whitespace trimmed. Returns empty string
-- if only whitespace.
local function trimmed(text) local function trimmed(text)
return text:match '^()%s*$' and '' or text:match '^%s*(.*%S)' return text:match '^()%s*$' and '' or text:match '^%s*(.*%S)'
end end
@ -35,7 +29,7 @@ end
-- Returns a markdown-compatible transformation of the link and text combination -- Returns a markdown-compatible transformation of the link and text combination
-- passed in. -- passed in.
function L.style_markdown(link, text) function L.style_markdown(link, text)
check_link_empty(link) must_have(link)
return "[" .. trimmed(text) .. "](" .. link .. ")" return "[" .. trimmed(text) .. "](" .. link .. ")"
end end
@ -43,7 +37,7 @@ end
-- Returns a wikilink-compatible transformation of the link and text combination -- Returns a wikilink-compatible transformation of the link and text combination
-- passed in, adding the text as a pipe if it exists. -- passed in, adding the text as a pipe if it exists.
function L.style_wiki(link, text) function L.style_wiki(link, text)
check_link_empty(link) must_have(link)
local pipe = "" local pipe = ""
text = trimmed(text) text = trimmed(text)
@ -51,16 +45,15 @@ function L.style_wiki(link, text)
return "[[" .. link .. pipe .. "]]" return "[[" .. link .. pipe .. "]]"
end end
-- Returns the correctly formatted link to a zettel with the anchor passed in. -- Returns a correctly formatted link to a new zettel.
-- Takes an optional link text which will be added to the link. -- Takes an optional link text which will be added to the link.
-- Takes an optional style according to which the link will be transformed. -- Takes an optional style according to which the link will be transformed.
function L.create(anchor, text, style) function L.create(anchor, text, style)
local link = L.clean(text)
style = style or o.zettel().link_style style = style or o.zettel().link_style
if style == "markdown" then if style == "markdown" then
link = L.append_extension(L.prepend_anchor(anchor, link)) local link = (a.prepend(anchor, L.urlify(text)))
return L.style_markdown(link, text) return L.style_markdown(L.append_extension(link), text)
elseif style == "wiki" then elseif style == "wiki" then
return L.style_wiki(anchor, text) return L.style_wiki(anchor, text)

View file

@ -4,42 +4,13 @@ Test_date = {year = 2019, month = 10, day = 29, hour = 16, min = 45}
before_each(function() _G.vim = {g = {}, b = {}} end) before_each(function() _G.vim = {g = {}, b = {}} end)
after_each(function() _G.vim = nil end) after_each(function() _G.vim = nil end)
describe("prepend_anchor", function() describe("urlify", function()
it("should append text to link", function()
assert.same("1910291645_isappended",
link.prepend_anchor("1910291645", "isappended"))
end)
it("should not add a separator if no text appended", function()
assert.same("1910291645", link.prepend_anchor("1910291645", ""))
end)
it("should return solely the anchor if no text is passed in", function()
assert.same("1910291645", link.prepend_anchor("1910291645", nil))
end)
it("should return solely the anchor if empty text is passed in", function()
assert.same("1910291645", link.prepend_anchor("1910291645", ""))
end)
it("should add contents of g:zettel_anchor_separator variable to link",
function()
vim.g.zettel_anchor_separator = "SEP"
assert.same("1910291645SEParated",
link.prepend_anchor("1910291645", "arated"))
end)
it("should add contents of b:zettel_anchor_separator variable to link",
function()
vim.b.zettel_anchor_separator = "---"
assert.same("1910291645---arated",
link.prepend_anchor("1910291645", "arated"))
end)
end)
describe("clean", function()
it("should return lowercased link text", function() it("should return lowercased link text", function()
assert.same("yesiamshouting", link.clean("YESIAMSHOUTING")) assert.same("yesiamshouting", link.urlify("YESIAMSHOUTING"))
end) end)
it("should return spaces in text replaced with dashes", function() it("should return spaces in text replaced with dashes", function()
assert.same("yes-indeed-a-space", link.clean("yes indeed a space")) assert.same("yes-indeed-a-space", link.urlify("yes indeed a space"))
end) end)
end) end)

View file

@ -1,7 +1,11 @@
" for DEBUGGING ONLY: reloads the whole lua plugin " TODO remove after debugging
if exists('g:loaded_zettelkasten')
finish
endif
" TODO for DEBUGGING ONLY: reloads the whole lua plugin
fun! ZKReload() fun! ZKReload()
lua for k in pairs(package.loaded) do if k:match("^zettelkasten") then package.loaded[k] = nil end end lua for k in pairs(package.loaded) do if k:match("^zettelkasten") then package.loaded[k] = nil end end
lua require 'zettelkasten'.init() lua require 'zettelkasten'
endfun endfun
nnoremap <leader>R :call ZKReload()<cr> nnoremap <leader>R :call ZKReload()<cr>
@ -9,7 +13,11 @@ augroup Zettelkasten
autocmd! autocmd!
augroup END augroup END
" example plug mappings
" nnoremap <Plug>Zettel_Link :call zettelkasten#zettel_link()<cr> " nnoremap <Plug>Zettel_Link :call zettelkasten#zettel_link()<cr>
nnoremap <Plug>zettel_link_create :lua require 'zettelkasten'.zettel_link_create()<cr> nnoremap <Plug>zettel_link_create :lua require 'zettelkasten'.create_zettel()<cr>
vnoremap <Plug>zettel_link_create :lua require 'zettelkasten'.create_zettel()<cr>
nmap <leader>i <Plug>zettel_link_create
vmap <leader>i <Plug>zettel_link_create
nmap <leader>n <Plug>zettel_link_create let g:loaded_zettelkasten = 1