I would like to create a parameterized page template and I’m wondering how to do it. My use case is that I have a daily note and I’d like to store the date in the title of the note. I want to be able to create tomorrow’s note today as well as today’s note.
This is what I did so far:
Create a page template with a command name, i.e. `command: “Journal: Create Daily Note”
The template includes this content # ${os.date("%y%m%d")} and more
Create a custom command via command.define that binds a key and calls editor.invokeCommand to create a new page via the template command.
With this setup, I can easily create today’s note. However, I can’t create tomorrow’s note, today. I would like to create another custom command that passes tomorrow’s timestamp parameter when the page get created from the template. This is where I don’t know how to continue.
editor.invokeCommand is able to pass parameters to the command, however the template function doesn’t seem to pass the parameter. Before I investigate further, I’d very much appreciate your feedback on the approach and whether it’s worth advancing further in this direction. In some other post, I read about leveraging the event mechanism to create pages from templates. Maybe this is a better approach.
As a workaround, I created two template pages - one for today, another for tomorrow, together with two custom commands. This works, however it’s not a generic solution and it increases the maintenance burden because I have to maintain two almost identical templates.
maybe i didn’t fully understand what you are trying to exactly, or what that template really looks like, but here is an idea:
so you want to use only one template and generate two different notes: one using today’s date, and a second one using the same template but with tomorrows date?
correct?
my first idea would be to use one template only without any date on it, and the date you add later using a function.
my second one is, if the template is not so complicated and doesn’t have that many content, use a template directly in the function and based on the passed parameter the function creates the page for today or tomorrow:
local function createNote(forDay)
template = [==[ ...]==]
-- here you put your magic code to create the page content using the forDay as variable for the day
space.writePage(page, template_incl_the_correct_date)
end
command.define {
name = "Note for today"
key =...
run function()
createNote("today")
end
}
command.define {
name = "Note for tomorrow"
key =...
run function()
createNote("tomorrow")
end
}
or you can create one comand with a selection/option box: editor.filterBox() which asks for which day you want the not to be created. and based on the option you chose which day the createNote(day) is executed.
The template is fairly long, so I’d love to use an existing page as a template. However, I do like your idea of putting everything in a function. This is very much straight forward and definitely solves the issue. I’d also be able to get rid of the duplicate command: one for the template page, another for the key binding.
Regarding your first suggestion of not including a date: how would I add the date later - simple string replace before calling space.writePage?
The fitlerBox I don’t like that much because it is error prone, e.g. when tomorrow is the first day of the following month, the user would have to manually adjust multiple digits.
First create the page normally using your template without date:
then
local content = space.readPage("welcome") --read page
local content_with_date = date .. content -- add date to the top of the page
space.writePage(name, content_with_date) --write contets with applied date to your file
if the date must go somewhere in the document, then choose a unique easily identifiable placeholder in the template let’s call it: variableDate, do a string replace for that variable with your desired date everywhere in your text using string.gsub from
then write the text to the page like mentioned above.
Thank you for the suggestions. This is what I ended up with:
The main function openDailyNote reimplements and extends the templating function that ships with silverbullet. If the page exists, it gets opened otherwise the page is created from the _template file in the respective directory. The current timestamp is inserted into the template by replacing ever occurrence of __FILE__ with the timestamp, which is equal to the file’s name.
-- Open daily note
function openDailyNote(timestamp, directory, filename)
local timestamp = timestamp or os.time()
local directory = directory or "daily"
local filename = filename or os.date("%y%m%d", timestamp)
local pageName = directory .. "/" .. filename
if space.pageExists(pageName) then
editor.navigate(pageName)
else
if editor.confirm("Create page: " .. pageName) then
local templatePage = directory .. "/" .. "_template"
local tpl, fm = template.fromPage(templatePage)
local initialText = ""
if fm.frontmatter then
initialText = "---\n"
.. string.trim(template.new(string.gsub(fm.frontmatter, "__FILE__", filename))())
.. "\n---\n"
end
-- Write an empty page to start
space.writePage(pageName, initialText)
editor.navigate(pageName)
-- Insert there, supporting |^| cursor placeholder
local text = string.gsub(tpl(), "__FILE__", filename)
editor.insertAtPos(text, #initialText, true)
end
end
end
-- Open tomorrow's daily note
function openTomorrowsDailyNote()
openDailyNote(os.time() + 24 * 60 * 60)
end
-- Register commands that execute the respective functions.
command.define {
name = "Open: Daily Note",
description = "Open daily notes page",
key = "Alt-n",
run = function()
openDailyNote()
end,
}
command.define {
name = "Open: Tomorrow's Daily Note",
description = "Open tomorrow's daily notes page",
key = "Ctrl-Alt-n",
run = function()
openTomorrowsDailyNote()
end,
}