From 7e77b616ea1bb5891fadb7212749b2295e026fb3 Mon Sep 17 00:00:00 2001 From: Marty Oehme Date: Thu, 29 Oct 2020 12:18:19 +0100 Subject: [PATCH] Add simple anchor listing functionality --- lua/zettelkasten/init.lua | 32 +++++++++ lua/zettelkasten/zettelkasten_spec.lua | 91 ++++++++++++++++++++++++-- 2 files changed, 119 insertions(+), 4 deletions(-) diff --git a/lua/zettelkasten/init.lua b/lua/zettelkasten/init.lua index 1b03ae2..51cdfb5 100644 --- a/lua/zettelkasten/init.lua +++ b/lua/zettelkasten/init.lua @@ -16,6 +16,7 @@ function ZK.init(vimapi) vim = vimapi or vim anchor_separator = vim.g["zettel_anchor_separator"] or vim.b["zettel_anchor_separator"] or "_" zettel_extension = vim.g["zettel_extension"] or vim.b["zettel_extension"] or ".md" + zettel_root = vim.g["zettel_extension"] or vim.b["zettel_extension"] or ".md" end -- entrypoint for pressing the zettel key when the cursor @@ -55,9 +56,40 @@ function ZK.create_link(text, date) return text .. (zettel_extension or ".md") end +local function _get_anchors_and_paths(path, recursive) + -- TODO check for duplicates and warn user + local zettel = {} + local anchorreg = '^.*/?([%d][%d][%d][%d][%d][%d][%d][%d][%d][%d])[^/]*.md$' + + local handle = vim.loop.fs_scandir(path) + while handle do + local name, ftype = vim.loop.fs_scandir_next(handle) + if not name then break end + + if ftype == 'directory' and recursive then + local subdir = _get_anchors_and_paths(path .. "/" .. name, true) + end + + local anchor = string.match(name, anchorreg) + if anchor then + zettel[tostring(anchor)] = name + end + end + return zettel +end + +-- Returns all zettel in path as a +-- { "anchor" = "path/to/zettel/anchor filename.md" } +-- table. +-- Recurses into subdirectories if recursive argument is true. +function ZK.get_zettel_list(path, recursive) + return _get_anchors_and_paths(path, recursive or false) +end + return { init = ZK.init, zettel_link_create = ZK.zettel_link_create, create_anchor = ZK.create_anchor, create_link = ZK.create_link, + get_zettel_list = ZK.get_zettel_list, } diff --git a/lua/zettelkasten/zettelkasten_spec.lua b/lua/zettelkasten/zettelkasten_spec.lua index 312dfbc..ebcded8 100644 --- a/lua/zettelkasten/zettelkasten_spec.lua +++ b/lua/zettelkasten/zettelkasten_spec.lua @@ -1,7 +1,11 @@ -ZK = require'init' +ZK = require'lua.zettelkasten.init' Test_date={ year=2019, month=10, day=29, hour=16, min=45 } describe("Zettelkasten", function() + before_each(function() + ZK.init({ g={}, b={} }) + end) + describe("anchor creation", function() it("should return zettel anchor from time passed in", function() assert.same("1910291645", ZK.create_anchor(Test_date)) @@ -15,6 +19,7 @@ describe("Zettelkasten", function() assert.is_nil(ZK.create_anchor("My grandmother is lovely.")) end) end) + describe("link creation", function() it("should return a markdown link with only zettel anchor on no text passed in", function() assert.same("1910291645.md", ZK.create_link(nil, Test_date)) @@ -43,7 +48,85 @@ describe("Zettelkasten", function() ZK.init(vim) assert.same("1910291645_theworld.something", ZK.create_link("theworld", Test_date)) end) - - end) -end) + + -- these tests, I suppose, only work on unix due to the file structure + describe("zettel listing", function() + before_each(function() + get_api_mock = function(files) + return { + g = {}, + b = {}, + loop = { + fs_scandir = function() + if #files == 0 then + return false + else + return true + end + end, + fs_scandir_next = function() return table.remove(files) end + } + } + end + end) + + it("should return anchor-keyed table pointing to filename of zettel", function() + local file_list = { "1910291645 this-is-a-testfile.md" } + ZK.init(get_api_mock(file_list)) + + local expected = { ["1910291645"] = "1910291645 this-is-a-testfile.md", } + assert.same(expected, ZK.get_zettel_list("someDir")) + end) + + it("should ignore any malformed files", function() + local file_list = { + "2010261208 this-should-be-picked-up.md", + "1910291645 this-is-a-testfile.md", + "this-is-not-a-testfile.md", + "1910271456 this-is-wrong-extension.txt", + "1812 this-is-ignored.md", + } + ZK.init(get_api_mock(file_list)) + + local expected = { + ["1910291645"] = "1910291645 this-is-a-testfile.md", + ["2010261208"] = "2010261208 this-should-be-picked-up.md", + } + assert.same(expected, ZK.get_zettel_list("someDir")) + end) + + it("should recurse into directories if recursive argument passed in ", function() + local files = { + { "1910271456 testfile.md", "file" }, + { "more-notes-here", "directory" }, + { "2010261208 another-testfile.md", "file" }, + } + local vim_api_mock = { + g = {}, + b = {}, + loop = mock({ + fs_scandir = function() + if #files == 0 then + return false + else + return true + end + end, + fs_scandir_next = function() + if #files == 0 then return nil end + local fname, ftype = unpack(table.remove(files)) + return fname, ftype + end + }) + } + ZK.init(vim_api_mock) + + ZK.get_zettel_list("path/to/startingdir", true) + + assert.spy(vim_api_mock.loop.fs_scandir).was_called(2) + assert.spy(vim_api_mock.loop.fs_scandir).was_called_with("path/to/startingdir/more-notes-here") + end) + + end) + end)