diff --git a/README.md b/README.md index 3b04f718..8a1547e9 100644 --- a/README.md +++ b/README.md @@ -326,6 +326,12 @@ require("obsidian").setup { template = nil, -- Optional, if you want `Obsidian yesterday` to return the last work day or `Obsidian tomorrow` to return the next work day. workdays_only = true, + -- Optional, a function for more complex customization. + -- If defined, it is called with datetime (integer) as its only argument. + -- The return value must be a tuple (string, string|nil) which represents note path and alias where alias is optional. + -- The note path must be relative and is treated as a sub path of the vault! Don't forget to add ".md" at the end if desired. + -- If this function is defined, it's returned values are used instead of folder, date_format and alias_format. + func = nil, }, -- Optional, completion of wiki links, local markdown links, and tags using nvim-cmp. diff --git a/lua/obsidian/client.lua b/lua/obsidian/client.lua index faf43d21..d1333738 100644 --- a/lua/obsidian/client.lua +++ b/lua/obsidian/client.lua @@ -117,7 +117,7 @@ Client.set_workspace = function(self, workspace, opts) notes_subdir:mkdir { parents = true, exists_ok = true } end - if self.opts.daily_notes.folder ~= nil then + if self.opts.daily_notes.func == nil and self.opts.daily_notes.folder ~= nil then local daily_notes_subdir = self.dir / self.opts.daily_notes.folder daily_notes_subdir:mkdir { parents = true, exists_ok = true } end @@ -643,6 +643,8 @@ Client.resolve_note_async = function(self, query, callback, opts) paths_to_check[#paths_to_check + 1] = self.dir / self.opts.notes_subdir / fname end + -- TODO: Check the notes created by custom daily notes func... + if self.opts.daily_notes.folder ~= nil then paths_to_check[#paths_to_check + 1] = self.dir / self.opts.daily_notes.folder / fname end @@ -1717,6 +1719,7 @@ Client.parse_title_id_path = function(self, title, id, dir) -- note is actually in the workspace. and self.dir:is_parent_of(bufpath) -- note is not in dailies folder + -- TODO: handle custom daily notes function and (self.opts.daily_notes.folder == nil or not (self.dir / self.opts.daily_notes.folder):is_parent_of(bufpath)) then base_dir = self.buf_dir or assert(bufpath:parent()) @@ -1966,11 +1969,30 @@ end Client._daily = function(self, datetime, opts) opts = opts or {} - local path, id = self:daily_note_path(datetime) + ---@type string|?, string|? + local custom_path, custom_alias + if self.opts.daily_notes.func ~= nil then + custom_path, custom_alias = self.opts.daily_notes.func(datetime) + if custom_path == nil then + error "Custom daily notes function must return non-nil path" + end + end + + ---@type obsidian.Path|?, string|number + local path, id + if custom_path ~= nil then + path = Path:new(self.dir) / custom_path + path:parent():mkdir { parents = true, exists_ok = true } + id = path.stem + else + path, id = self:daily_note_path(datetime) + end ---@type string|? local alias - if self.opts.daily_notes.alias_format ~= nil then + if custom_alias ~= nil then + alias = custom_alias + elseif self.opts.daily_notes.alias_format ~= nil then alias = tostring(os.date(self.opts.daily_notes.alias_format, datetime)) end diff --git a/lua/obsidian/commands/dailies.lua b/lua/obsidian/commands/dailies.lua index 0a01ca4a..5c04a3a0 100644 --- a/lua/obsidian/commands/dailies.lua +++ b/lua/obsidian/commands/dailies.lua @@ -1,4 +1,5 @@ local log = require "obsidian.log" +local Path = require "obsidian.path" ---@param arg string ---@return number @@ -46,8 +47,32 @@ return function(client, data) local dailies = {} for offset = offset_end, offset_start, -1 do local datetime = os.time() + (offset * 3600 * 24) - local daily_note_path = client:daily_note_path(datetime) - local daily_note_alias = tostring(os.date(client.opts.daily_notes.alias_format or "%A %B %-d, %Y", datetime)) + + ---@type string|?, string|? + local custom_path, custom_alias + if client.opts.daily_notes.func ~= nil then + custom_path, custom_alias = client.opts.daily_notes.func(datetime) + if custom_path == nil then + error "Custom daily notes function must return non-nil path" + end + end + + ---@type obsidian.Path|? + local daily_note_path + if custom_path ~= nil then + daily_note_path = Path:new(client.dir) / custom_path + else + daily_note_path = client:daily_note_path(datetime) + end + + ---@type string|? + local daily_note_alias + if custom_alias ~= nil then + daily_note_alias = custom_alias + else + daily_note_alias = tostring(os.date(client.opts.daily_notes.alias_format or "%A %B %-d, %Y", datetime)) + end + if offset == 0 then daily_note_alias = daily_note_alias .. " @today" elseif offset == -1 then diff --git a/lua/obsidian/config.lua b/lua/obsidian/config.lua index 882bb0ac..e91612ea 100644 --- a/lua/obsidian/config.lua +++ b/lua/obsidian/config.lua @@ -431,6 +431,7 @@ end ---@field template string|? ---@field default_tags string[]|? ---@field workdays_only boolean +---@field func? fun(datetime: integer): (string, string|?) default to nil config.DailyNotesOpts = {} --- Get defaults. @@ -443,6 +444,7 @@ config.DailyNotesOpts.default = function() alias_format = nil, default_tags = { "daily-notes" }, workdays_only = true, + func = nil, } end diff --git a/tests/test_client.lua b/tests/test_client.lua index 954b6ab2..9a760e88 100644 --- a/tests/test_client.lua +++ b/tests/test_client.lua @@ -40,6 +40,18 @@ describe("Client", function() end) end) + it("should be able to initialize a daily note with custom func", function() + with_tmp_client(function(client) + client.opts.daily_notes.func = function(datetime) + local note = os.date("%Y/%m-%B/%Y-%m-%d", datetime) + return "journal/" .. note .. ".md" + end + local note = client:today() + MiniTest.expect.equality(true, note.path ~= nil) + MiniTest.expect.equality(true, note:exists()) + end) + end) + it("should not add frontmatter for today when disabled", function() with_tmp_client(function(client) client.opts.disable_frontmatter = true