obsidian.nvim icon indicating copy to clipboard operation
obsidian.nvim copied to clipboard

Notes creation from templates

Open ekropotin opened this issue 1 year ago â€ĸ 8 comments

🚀 The feature, motivation and pitch

Current support of templates seems to only allow inserting template-based text in already created note. It would be super nice to be able to create new notes from templates as well. The flow I have in mind is something like this:

  1. :ObisidianNewFromTemplate [title]
  2. The list of available templates shows up
  3. Upon selection, a new note is created, based on the selected template

That also requires templates to support substitutions from values that are only available at the note creation time, for example, an id, generated by note_id_func.

Alternatives

Custom command:

vim.api.nvim_create_user_command("ObsidianNewFromTemplate", function()
    vim.cmd("ObsidianNew")
    vim.cmd("normal! G") -- go to end of file
    vim.cmd("ObsidianTemplate")
end, {})

as suggested by @sotte

Additional context

No response

ekropotin avatar Mar 05 '24 17:03 ekropotin

I have a custom user command for this. I adjusted it a bit so it fits your requirements a bit more:

vim.api.nvim_create_user_command("ObsidianNewFromTemplate", function()
    vim.cmd("ObsidianNew")
    vim.cmd("normal! G") -- go to end of file
    vim.cmd("ObsidianTemplate")
end, {})

And I agree with you. Something like that would be helpful.

sotte avatar Mar 06 '24 09:03 sotte

Thank you @sotte very much for the proposed workaround! Unfortunately, it doesn't fully meet my needs. For example, In template I want to have an access to an id of the note, that is being generated by note_id_func at the note creation time.

ekropotin avatar Mar 06 '24 17:03 ekropotin

I think in general it would be nice to have access to way more variables for templates. This includes the note ID (and the front matter).

sotte avatar Mar 07 '24 06:03 sotte

Agreed, the template functionality was half-baked. The template functions should really have access to the obsidian.Note object directly. I'm open to PRs for improvements here.

epwalsh avatar Mar 07 '24 17:03 epwalsh

+1 for this; Plus, it would be great if we could also specify a template that all newly created notes would use and insert at note creation time (with support for the usual variable substitutions).

This would save a couple keystrokes to insert my template to a new note, and do a bit of dupe clean up.

tgallacher avatar Apr 02 '24 18:04 tgallacher

+1 for this; Plus, it would be great if we could also specify a template that all newly created notes would use and insert at note creation time (with support for the usual variable substitutions).

This would save a couple keystrokes to insert my template to a new note, and do a bit of dupe clean up.

Had a quick look around the codebase and managed to come up with a workaround, which I think will work for me, for now until this feature is supported natively by the plugin. Adding here in case anyone else finds it useful:

The outcome of the below solution is that now, when I'm in my Obsidian vault, I can use the keymap <leader>nn and I will be prompted for a title for my new note. Once entered, a new note is then created in my vault with the content of the new note taken from my "default-note" template, with the relevant substitutions made.

This should save me a few keystrokes đŸ’Ē 🎉

â„šī¸ Context re this solution:

  • the below example uses the Lazy plugin manager;
  • my default-note.md template includes it's own frontmatter, which requires a bit more effort to prevent it fighting with Obsidian.nvim's frontmatter injection;
  • If I want a new note with a different template (edge case for me), I can use the Obsidian.nvim commands as normal;
  • this is a very rough solution; might not cater to all edge cases;
local function createNoteWithDefaultTemplate()
  local TEMPLATE_FILENAME = "default-note"
  local obsidian = require("obsidian").get_client()
  local utils = require("obsidian.util")

  -- prevent Obsidian.nvim from injecting it's own frontmatter table
  obsidian.opts.disable_frontmatter = true

  -- prompt for note title
  -- @see: borrowed from obsidian.command.new
  local note
  local title = utils.input("Enter title or path (optional): ")
  if not title then
    return
  elseif title == "" then
    title = nil
  end

  note = obsidian:create_note({ title = title, no_write = true })

  if not note then
    return
  end
  -- open new note in a buffer
  obsidian:open_note(note, { sync = true })
  -- NOTE: make sure the template folder is configured in Obsidian.nvim opts
  obsidian:write_note_to_buffer(note, { template = TEMPLATE_FILENAME })
  -- hack: delete empty lines before frontmatter; template seems to be injected at line 2
  vim.api.nvim_buf_set_lines(0, 0, 1, false, {})
end

-- returning a LazyVim plugin spec
return {
    "epwalsh/obsidian.nvim",
    version = "*", -- latest release instead of commit
    lazy = true,
    ft = "markdown",
    dependencies = {
      "nvim-lua/plenary.nvim",
    },
    init = function()
      vim.opt.conceallevel = 2

      vim.keymap.set("n", "<leader>nn", createNoteWithDefaultTemplate, { desc = "[N]ew Obsidian [N]ote" })
    end,
}

tgallacher avatar Apr 02 '24 22:04 tgallacher

thinking about it, it probably wouldn't take too much to amend the above to meet the flow you outlined @ekropotin

tgallacher avatar Apr 02 '24 22:04 tgallacher

Thank you, @tgallacher. It's exactly what I needed!

ekropotin avatar Apr 03 '24 04:04 ekropotin