Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic values for journal templates #714

Open
1 task done
cosmicboots opened this issue Jan 16, 2023 · 11 comments
Open
1 task done

Dynamic values for journal templates #714

cosmicboots opened this issue Jan 16, 2023 · 11 comments
Labels
feature Issues related to feature proposals. Please attach a module.

Comments

@cosmicboots
Copy link
Contributor

Issues

  • I have checked existing issues and there are no existing ones with the same request.

Feature description

It would be nice to be able to have the journal template contain special values that get replaced when the new daily journal files are created.

Below would be and example showing a possible date substitution.

image

I really like the journal feature, and I think adding this (or something close to it) would greatly improve the template functionality.

I have an oversimplified concept working here: cosmicboots@e510d1e

Help

Yes

Implementation help

Past configuring my editor, I'm fairly new to Lua.

I would also like some guidance on how this feature should be structured from a high level, so it fits in with the rest of the code base.

@cosmicboots cosmicboots added the feature Issues related to feature proposals. Please attach a module. label Jan 16, 2023
@d-r-a-b d-r-a-b moved this to needs-guidance in sorting neorg issue tracker Apr 30, 2023
@pysan3
Copy link
Contributor

pysan3 commented Apr 30, 2023

Hi @cosmicboots

Not a solution directly implemented in this plugin but I have made an external module to create templates for norg file with dynamic values via LuaSnip.

https://github.com/pysan3/neorg-templates

@gegnew
Copy link

gegnew commented May 17, 2023

Is there a good way to hook pysan3/neorg-templates into the :Neorg journal ... commands, so that the template is used automatically?

Edit:

I'm using an autocmd:

    vim.api.nvim_create_autocmd("BufNewFile", {
        command = "Neorg templates journal",
        pattern = { neorg_dir .. "journal/*.norg" },
    })

@pysan3
Copy link
Contributor

pysan3 commented May 17, 2023

Thanks for trying it out @gegnew !

Added your comment to the README. Thanks for the tip ;)

https://github.com/pysan3/neorg-templates#autoload-with-neorg-journal

@theherk
Copy link

theherk commented Jun 14, 2023

Would be super if you could use a template of this nature:

* YYYY-MM-DD - Report
  {:YYYY/MM/DD:* YYYY-MM-[DD-1]}[←] | {:YYYY/MM/DD:* YYYY-MM-[DD+1]}[→]
** Did
** Doing
** Blockers

It seems you could do this with your templates @pysan3 if they included YESTERDAY and TOMORROW. Even still, would be good it this were build directly into the journal module.

@pysan3
Copy link
Contributor

pysan3 commented Jun 14, 2023

The current builtin method has no dynamic value substitution mechanism and it simply copies the content of the template file into the created journal file as you can see here.

vim.cmd("0read " .. workspace_path .. "/" .. folder_name .. "/" .. template_name .. "| w")

On the other hand, my module uses the LuaSnip snippet engine and dynamically loads values as well as asks for user input on the fly. This method has a huge possibility of extensibility which makes it easy to have YESTERDAY and other keywords, but requires a very complicated implementation, at least a completion engine in order to work properly.

would be good it this were build directly into the journal module.

It would be nice if my module could be ported into the core repo, but since it depends on LuaSnip, people using different snippet engines (e.g. UltiSnips) cannot benefit from this approach and I think it would never happen.

Have you tried my module? If you have any problems using my module, feel free to open an issue over there ;)
If you want to automatically load your journal template after running :Neorg journal command, follow this section. https://github.com/pysan3/neorg-templates#autoload-with-neorg-journal

@edlandm
Copy link

edlandm commented Aug 11, 2023

I just found a solution that works for me using Neorg's builtin template system.
It appears that when creating a new journal entry, Neorg creates the file, opens it in a buffer, and then reads the template into the file. This was preventing me from applying substitutions with an autocommand on the BufNewFile event (because the file already exists by the time we open it).
But I kept playing with it and realized that the FileReadPost event is indeed triggered, so I am able to apply my substitutions with autocommands for that event.
I plopped this in my ftplugin/norg.vim file and it works!

augroup NORG_JOURNAL
  au!
  au FileReadPost */journal/*.norg 1s/DATE$/\=system("date +'%Y.%m.%d'|tr -d $'\n'")/e
augroup END

@theherk
Copy link

theherk commented Sep 14, 2023

@pysan3, I finally got around to giving this a spin, and your plugin works superb. Highly recommend to anybody stumbling upon this.

@maxdiebold
Copy link

maxdiebold commented Dec 1, 2023

I had issues with both of the suggestions noted above (but thank you for the direction!). This is the implementation that ended up working for me:

local file_exists_and_is_empty = function(filepath)
  local file = io.open(filepath, "r") -- Open the file in read mode
  if file ~= nil then
    local content = file:read("*all") -- Read the entire content of the file
    file:close() -- Close the file
    return content == "" -- Check if the content is empty
  else
    return false
  end
end

vim.api.nvim_create_autocmd({ "BufNew", "BufNewFile" }, {
  callback = function(args)
    local toc = "index.norg"
    vim.schedule(function()
      if vim.fn.fnamemodify(args.file, ":t") == toc then
        return
      end
      if
        args.event == "BufNewFile"
        or (args.event == "BufNew" and file_exists_and_is_empty(args.file))
      then
        vim.api.nvim_cmd({ cmd = "Neorg", args = { "templates", "fload", "journal" } }, {})
      end
    end)
  end,
  desc = "Load new workspace entries with a Neorg template",
  group = vim.api.nvim_create_augroup(augroup, { clear = true }),
  pattern = dir .. "/*.norg",

Edited due to problems with lingering buffers after file deletion.

@gegnew
Copy link

gegnew commented Dec 17, 2023

A recent update broke my BufNewFile solution; anyone have a simple solution? I'd love something less verbose, but in the meantime, @maxdiebold 's solution, but edited so that it runs (thanks for this!)

    local file_exists_and_is_empty = function(filepath)
        local file = io.open(filepath, "r")   -- Open the file in read mode
        if file ~= nil then
            local content = file:read("*all") -- Read the entire content of the file
            file:close()                      -- Close the file
            return content == ""              -- Check if the content is empty
        else
            return false
        end
    end

    vim.api.nvim_create_autocmd({ "BufNew", "BufNewFile" }, {
        callback = function(args)
            local toc = "index.norg"

            vim.schedule(function()
                if vim.fn.fnamemodify(args.file, ":t") == toc then
                    return
                end
                if
                    args.event == "BufNewFile"
                    or (args.event == "BufNew" and file_exists_and_is_empty(args.file))
                then
                    vim.api.nvim_cmd({ cmd = "Neorg", args = { "templates", "fload", "journal" } }, {})
                end
            end)
        end,
        desc = "Load new workspace entries with a Neorg template",
        pattern = neorg_dir .. "/diary/*.norg",
    })

@skbolton
Copy link

skbolton commented Dec 25, 2023

What if template_name option could be a string like it is today or a callback function. Neorg could call the function and pass parameters into it. The function would then return the template text for neorg to write to the buffer.

Easy extension point for 3rd party plugins or users.

@Stimim
Copy link

Stimim commented Feb 8, 2024

Unfortunately, after some research, my previous comment doesn't work.

  1. Neorg don't always call core.dirman.create_file to create new files. For example, following a link to open the file doesn't call create_file.
  2. create_file would fire an event file_created, however, the buffer in the event object might be wrong.
    • Maybe this is why create_file is called twice in journal?
  3. Because create_file would create a file in the background, and then open it. So we can only receive BufNew event, but not BufNewFile.
  4. On the other hand, if I open a new file by following a link in a norg file, then this doesn't call create_file. In this case, both BufNewFile and BufNew event will be fired.

So.. I went back to gegnew's snippet.
But I only check if the current buffer is empty.

local function setup_loading_template_on_new_file()
  local group = vim.api.nvim_create_augroup(
    'NeorgLoadTemplateGroup',
    { clear = true }
  )

  local is_buffer_empty = function(buffer)
    local content = vim.api.nvim_buf_get_lines(buffer, 0, -1, false)
    return not (#content > 1 or content[1] ~= '')
  end

  local callback = function(args)
    vim.schedule(function()
      if not is_buffer_empty(args.buf) then
        return
      end

      if string.find(args.file, '/journal/') then
        debug('loading template "journal" ' .. args.event)
        vim.api.nvim_cmd({ cmd = 'Neorg', args = { 'templates', 'fload', 'journal' } }, {})
      else
        debug('add metadata ' .. args.event)
        vim.api.nvim_cmd({ cmd = 'Neorg', args = { 'inject-metadata' } }, {})
      end
    end)
  end

  vim.api.nvim_create_autocmd(
    { 'BufNewFile', 'BufNew', },
    {
      desc = 'Load template on new norg files',
      pattern = '*.norg',
      callback = callback,
      group = group,
    }
  )
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Issues related to feature proposals. Please attach a module.
Projects
None yet
Development

No branches or pull requests

8 participants