obsidian.nvim
obsidian.nvim copied to clipboard
Enable users to create custom commands opening new notes with templates
🚀 The feature, motivation and pitch
I wanted to create a note template which acts as my journaling template, since the command available for a daily note is ObsidianToday, which is the only command that creates a note with todays date as title, i was wondering if it is possible to create commands like lets call it "OpenNewJournalEntry", that offers the same feature as ObsidianToday, but enables adding of custom tags, and a custom template
Alternatives
I was able to create a command in lua as keymap, but it doesnt work with obsidian.nvim together (especially opening the note like ObsidianNew or ObsidianToday does, in the obsidian vault working directory), this is the function i came up with, but i would love a connection with obsidian.nvim, to open it up in the correct folder after creating it.
vim.api.nvim_create_user_command("OpenDailyNote", function()
local date_format = "%Y-%m-%d"
local obsidian_vault_dir = "~/Documents/second-brain/"
local daily_folder = obsidian_vault_dir .. "NOTES/JOURNAL"
local template_path = obsidian_vault_dir .. "Templates/JournalTemplate.md"
local date = os.date(date_format)
local note_path = vim.fn.expand(daily_folder .. "/" .. date .. ".md")
local id = tostring(os.time())
if vim.fn.filereadable(note_path) == 0 then
vim.fn.mkdir(vim.fn.expand(daily_folder), "p")
local front_matter = table.concat({
"---",
"id: " .. id,
"title: " .. date,
"tags: [journaling]",
"---",
"",
}, "\n")
local file = io.open(note_path, "w")
file:write(front_matter)
if template_path and #template_path > 0 then
local template = io.open(template_path, "r")
if template then
local content = template:read("*all")
file:write(content)
template:close()
end
end
file:close()
end
end, {}),
Additional context
No response
Hey @escapingSamsara, I would like to expand the template functionality at some point to also handle frontmatter, but in the meantime you could probably accomplish this elegantly using obsidian.nvim's Lua API. As an example, I have similar use case where I programmatically create notes corresponding to research papers. This the command I wrote to do that:
vim.api.nvim_create_user_command("NewPaper", function(ev)
local obsidian = require "obsidian"
---@type obsidian.Client
local client = obsidian.get_client()
local corpus_id = assert(tonumber(ev.args))
-- Get paper metadata.
local data = get_paper_metadata(corpus_id)
local note_title = data.title .. " (paper)"
-- Create new note and add metadata.
local note = client:new_note(note_title)
note:add_tag "paper"
note:add_alias(data.title .. " (paper)")
note:add_field("corpus_id", data.corpus_id)
note:add_field("url", data.url)
note:add_field("tldr", data.tldr.text)
note:save()
-- Insert link to the note.
insert_text(client:format_link(note, { label = note_title }))
end, { nargs = 1 })
------ Util functions ------
local get_paper_metadata = function(corpus_id)
local curl = require "plenary.curl"
local response = curl.get {
url = string.format("https://api.semanticscholar.org/graph/v1/paper/CorpusId:%s?fields=tldr,title,url", corpus_id),
accept = "application/json",
}
assert(response.status == 200)
local data = vim.json.decode(response.body)
data.corpus_id = corpus_id
return data
end
local insert_text = function(text)
local curpos = vim.fn.getcurpos()
local line_num, line_col = curpos[2], curpos[3]
-- Convert text to lines table so we can handle multi-line strings.
local lines = {}
for line in text:gmatch "[^\r\n]+" do
lines[#lines + 1] = line
end
vim.api.nvim_buf_set_text(0, line_num - 1, line_col, line_num - 1, line_col, lines)
end
hey @epwalsh thanks so much for your quick response ! that surely would be awesome !
I was tweaking around a little bit more and used your provided snippet as template (thanks for sharing it!)
i implemented this now in my keymaps.lua file. the function gets called and a new note gets created in my obsidian-vault directory. whats weird tho (and i hope you might know whats going on here) is, i created a Template/JournalTemplate.md file... when i use the cmd "JournalEntry" now, a new note gets created in my vault exactly how i want it, BUT:
- it doesnt redirect me (focus) to the obsidian-vault and the note, it just creates it
- and secondly, whats absolutely something i cant explain (although something i actually would want), it uses the template file... but why ? it isnt declared anywhere in the snippet.
here is the function i came up with:
---------------------------------------------------------
vim.api.nvim_create_user_command("JournalEntry", function()
local date_format = "%Y-%m-%d"
local obsidian = require("obsidian")
local date = os.date(date_format)
---@type obsidian.Client
local client = obsidian.get_client()
--get metadata
local note_title = tostring(date)
--create new note and add metadata
local note = client:new_note(note_title)
note:add_tag("journaling")
note:add_alias(note_title .. " journal entry")
note:save()
end, {})
--------------------------------------------------------------------
do you know why it uses the template stored in my templates dir and also if there is a way to open up the note like it does with the built-in functions like "ObsidianNew" when using the cmd anywhere in a neovim file/directory
@escapingSamsara I just added a method on main for easily opening a note in a buffer. Update to the latest commit and then add this to the end of your command:
client:open_note(note)
something i cant explain (although something i actually would want), it uses the template file... but why ? it isnt declared anywhere in the snippet.
I'm guessing you have the template set to daily_notes.template in your obsidian.nvim config?
hi !
adding : client:open_note(note) works perfectly ! thanks for adding that in :)
i do have my daily_notes template set to this, but i did not assume that the command uses the ObsidianToday functionality under the hood, which is used by daily_notes i thought. i was thinking the created command would use an empty default note
would you mind explaining why this is different ?
It recognizes that the note title is in your specified date format for daily notes, so treats it as a daily.
It recognizes that the note title is in your specified date format for daily notes, so treats it as a daily.
alright !! that makes a ton of sense, thanks for the explanation :) i am quite new to lua so i was unsure what might have caused this .
thanks again for the help and the little push for the client command. i really appreciate it. and also: thanks so much for providing such an awesome plugin !