From eaa7b589d2ac89de7370f7f90e5a5bd914151ffc Mon Sep 17 00:00:00 2001 From: Marty Oehme Date: Tue, 4 May 2021 17:51:32 +0200 Subject: [PATCH] Add anchor duplicate checking before creation --- lua/zettelkasten/anchor.lua | 28 +++++++++++++++++-- lua/zettelkasten/anchor_spec.lua | 46 ++++++++++++++++++++++++++++++++ lua/zettelkasten/files.lua | 1 + lua/zettelkasten/link.lua | 3 ++- lua/zettelkasten/link_spec.lua | 8 +++++- lua/zettelkasten/text.lua | 4 ++- 6 files changed, 85 insertions(+), 5 deletions(-) diff --git a/lua/zettelkasten/anchor.lua b/lua/zettelkasten/anchor.lua index cedb6d6..944dc94 100644 --- a/lua/zettelkasten/anchor.lua +++ b/lua/zettelkasten/anchor.lua @@ -2,16 +2,23 @@ local A = {} local o = require 'zettelkasten.options' +local function deduplicate(anchor, anchorfct) + while A.is_duplicate(anchor, anchorfct) do anchor = anchor - 1 end + return anchor +end + -- Return a valid zettelkasten anchor, -- composed of yymmddHHMM. -- -- 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. -- If no date is passed in, returns Zettel anchor for current moment. -function A.create(date) +function A.create(date, anchorfct) local timestamp if pcall(function() timestamp = os.time(date) end) then - return os.date('%y%m%d%H%M', timestamp) + local anchor = os.date('%y%m%d%H%M', timestamp) + if anchorfct then anchor = deduplicate(anchor, anchorfct) end + return tostring(anchor) else return nil end @@ -37,4 +44,21 @@ function A.extract(input, regex) return input:match(regex) end +-- Returns a set of all anchors created by the function passed in +-- (if argument is set) or all anchors currently in zettel root dir +-- (if no argument passed). +function A.list(anchor_function) + if not anchor_function then return {} end + return anchor_function() +end + +-- Returns true if anchor passed in already exists, false otherwise. +-- Takes an optional set of anchors to compare against, will +-- compare against all anchors in zettel root dir otherwise. +function A.is_duplicate(anchor, anchor_function) + local all_anchors = A.list(anchor_function) + if all_anchors[anchor] ~= nil then return true end + return false +end + return A diff --git a/lua/zettelkasten/anchor_spec.lua b/lua/zettelkasten/anchor_spec.lua index 6ab084c..5faafc7 100644 --- a/lua/zettelkasten/anchor_spec.lua +++ b/lua/zettelkasten/anchor_spec.lua @@ -14,6 +14,22 @@ describe("create", function() it("should return nil if argument passed in is invalid", function() assert.is_nil(A.create("My grandmother is lovely.")) end) + + it( + "should lower timestamps until the first non-duplicated one if valid anchor gathering function passed", + function() + Anchor_fct = function() + return { + ["2010261208"] = "/path/to/my/anchor.md", + ["1910291645"] = "/path/to/my/other_anchor.md" + } + end + assert.same("1910291644", A.create(Test_date, Anchor_fct)) + end) + + it( + "should ignore duplicate timestamps if no anchor gathering function passed", + function() assert.same("1910291645", A.create(Test_date)) end) end) describe("prepend", function() @@ -61,3 +77,33 @@ describe("extract", function() "[%l][%u][%d][%d][%d][%u]")) end) end) + +describe("list", function() + it("should return a set of anchors", function() + local anchor_fct = function() + return { + ["2010261208"] = "/path/to/my/anchor.md", + ["2001011212"] = "/path/to/my/other_anchor.md" + } + end + assert.same({ + ["2010261208"] = "/path/to/my/anchor.md", + ["2001011212"] = '/path/to/my/other_anchor.md' + }, A.list(anchor_fct)) + end) +end) + +describe("check_anchor_exists", function() + before_each(function() + Anchor_fct = function() + return { + ["2010261208"] = "/path/to/my/anchor.md", + ["2001011212"] = "/path/to/my/other_anchor.md" + } + end + end) + it("returns true if anchor in existing set", + function() assert.is_true(A.is_duplicate('2001011212', Anchor_fct)) end) + it("returns false if anchor not in existing set", + function() assert.is_false(A.is_duplicate('2001011210', Anchor_fct)) end) +end) diff --git a/lua/zettelkasten/files.lua b/lua/zettelkasten/files.lua index 4870545..ed970f3 100644 --- a/lua/zettelkasten/files.lua +++ b/lua/zettelkasten/files.lua @@ -24,6 +24,7 @@ end -- TODO transform paths: -- * to ensure / at the end (or no /) gets taken into account function ls.get_anchors_and_paths(fileset) + fileset = fileset or ls.get_all_files(o.zettel().rootdir, true) -- TODO check for duplicates and warn user local zettel = {} local anchorreg = '^.*/?(' .. o.anchor().regex .. ')[^/]*%' .. diff --git a/lua/zettelkasten/link.lua b/lua/zettelkasten/link.lua index 0ef5d77..07c0092 100644 --- a/lua/zettelkasten/link.lua +++ b/lua/zettelkasten/link.lua @@ -2,6 +2,7 @@ local L = {} local o = require 'zettelkasten.options' local a = require 'zettelkasten.anchor' +local f = require 'zettelkasten.files' local parsers = { markdown = { @@ -58,7 +59,7 @@ end -- Takes an optional link text which will be added to the link. -- Takes an optional style according to which the link will be transformed. function L.new(text, style) - local anchor = a.create() + local anchor = a.create(nil, f.get_anchors_and_paths) return L.create(anchor, text, style) end diff --git a/lua/zettelkasten/link_spec.lua b/lua/zettelkasten/link_spec.lua index 73e3d6c..f0e43dc 100644 --- a/lua/zettelkasten/link_spec.lua +++ b/lua/zettelkasten/link_spec.lua @@ -1,4 +1,4 @@ -link = require 'zettelkasten.link' +local link = require 'zettelkasten.link' Test_date = {year = 2019, month = 10, day = 29, hour = 16, min = 45} before_each(function() _G.vim = {g = {}, b = {}} end) @@ -79,6 +79,12 @@ describe("create", function() end) describe("new", function() + before_each(function() + vim.loop = { + fs_scandir = function(_) return false end, + fs_scandir_next = function(_) end + } + end) it("should create a link out of only text input", function() local result = link.new("My FILE NAME") assert.is_not_nil(result:match( diff --git a/lua/zettelkasten/text.lua b/lua/zettelkasten/text.lua index a9a8092..02a09dc 100644 --- a/lua/zettelkasten/text.lua +++ b/lua/zettelkasten/text.lua @@ -90,7 +90,9 @@ end --- @param linenr number --- @return string function T.get_line(linenr) - if linenr then return vim.api.nvim_buf_get_lines(0, linenr - 1, linenr, false)[1] end + if linenr then + return vim.api.nvim_buf_get_lines(0, linenr - 1, linenr, false)[1] + end return vim.api.nvim_get_current_line() end