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

feat: option to inject specific metadata instead of defaults #1128

Merged
merged 12 commits into from
Nov 8, 2023
47 changes: 34 additions & 13 deletions lua/neorg/modules/core/dirman/module.lua
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,19 @@ To query the current workspace, run `:Neorg workspace`. To set the workspace, ru
### Changing the Current Working Directory
After a recent update `core.dirman` will no longer change the current working directory after switching
workspace. To get the best experience it's recommended to set the `autochdir` Neovim option.


### Create a new note
You can use dirman to create new notes in your workspaces.

```lua
local dirman = require('neorg').modules.get_module("core.dirman")
dirman.create_file("my_file", "my_ws", {
no_open = false, -- open file after creation?
force = false, -- overwrite file if exists
metadata = {} -- key-value table for metadata fields
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what happens when you pass an empty table there? will just default metadata be generated?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes.
It overrides default if there's a match in the key names. Otherwise it does nothing.

})
```
--]]

local neorg = require("neorg.core")
Expand Down Expand Up @@ -265,12 +278,16 @@ module.public = {
})
end)
end,

---@class create_file_opts
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

classes are kinda global so you might want to use e.g. neorg.create_file_opts afaict this is common-practice.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it go even deeper then and name it neorg.dirman.create_file_opts then?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

up to you
you could search through neorg rq (just telescope live grep for ---@class (perhaps with space after ---)) and see how it's done in other parts of the codebase

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated names to match the apparent naming convention used in the rest of the codebase (as far as i can tell :))

---@field no_open? boolean do not open the file after creation?
---@field force? boolean overwrite file if it already exists?
---@field metadata? metadata metadata fields, if provided inserts metadata - an empty table uses default values

--- Takes in a path (can include directories) and creates a .norg file from that path
---@param path string a path to place the .norg file in
---@param workspace? string workspace name
---@param opts? table additional options
--- - opts.no_open (bool) if true, will not open the file in neovim after creating it
--- - opts.force (bool) if true, will overwrite existing file content
---@param opts? create_file_opts additional options
create_file = function(path, workspace, opts)
opts = opts or {}

Expand Down Expand Up @@ -308,20 +325,24 @@ module.public = {
fname = fname .. ".norg"
end

if opts.no_open then
-- Create the file
local fd = vim.loop.fs_open(fname, opts.force and "w" or "a", 438)

if fd then
vim.loop.fs_close(fd)
end
-- Create the file
local fd = vim.loop.fs_open(fname, opts.force and "w" or "a", 438)
if fd then
vim.loop.fs_close(fd)
end

return
local metagen = neorg.modules.get_module("core.esupports.metagen")
if opts.metadata and metagen then
local bufnr = module.public.get_file_bufnr(fname)
metagen.write_metadata(bufnr, true, opts.metadata)
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of the code looks good to me apart from this bit. This intertwines the dirman and metagen modules more than it should and doesn't extend to other modules which might also want to do something special when a file is created. Maybe it would be best to create a core.dirman.file_created event whose content is all of the parameters ({ metadata, force, no_open })? That way any module (including metagen) can listen for this event and do the metadata generation on its own without the two modules ever knowing about each other :)

If you're unsure about how to go around implementing it, feel free to ask!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the detailed reply. That sounds like a good solution. I am a little unsure how to implement an event.

I would appreciate any help you can give. 😄


-- Begin editing that newly created file
vim.cmd("e " .. fname .. " | w")
if not opts.no_open then
-- Begin editing that newly created file
vim.cmd("e " .. fname .. "| w")
end
end,

--- Takes in a workspace name and a path for a file and opens it
---@param workspace_name string #The name of the workspace to use
---@param path string #A path to open the file (e.g directory/filename.norg)
Expand Down
33 changes: 31 additions & 2 deletions lua/neorg/modules/core/esupports/metagen/module.lua
Original file line number Diff line number Diff line change
Expand Up @@ -185,10 +185,27 @@ module.public = {
}
end,

--- Creates the metadata contents from the configuration's template.
--- Constructs the metadata contents from the configuration's template.
---@param buf number #The buffer to query potential data from
---@return table #A table of strings that can be directly piped to `nvim_buf_set_lines`
construct_metadata = function(buf)
return module.public.create_metadata(buf, {})
end,

---@class metadata
---@field title? function|string the title of the note
---@field description? function|string the description of the note
---@field authors? function|string the authors of the note
---@field categories? function|string the categories of the note
---@field created? function|string a timestamp of creation time for the note
---@field updated? function|string a timestamp of last time the note was updated
---@field version? function|string the neorg version

--- Creates the metadata contents from the provided metadata table (defaulting to the configuration's template).
---@param buf number #The buffer to query potential data from
---@param metadata? metadata #Table of metadata, overrides defaults if present
---@return table #A table of strings that can be directly piped to `nvim_buf_set_lines`
create_metadata = function(buf, metadata)
local template = module.config.public.template
local whitespace = type(module.config.public.tab) == "function" and module.config.public.tab()
or module.config.public.tab
Expand All @@ -200,6 +217,10 @@ module.public = {
}

for _, data in ipairs(template) do
if metadata and metadata[data[1]] then
-- override with data from metadata table
data = { data[1], metadata[data[1]] }
end
table.insert(
result,
whitespace .. data[1] .. delimiter .. tostring(type(data[2]) == "function" and data[2]() or data[2])
Expand All @@ -219,10 +240,18 @@ module.public = {
---@param buf number #The number of the buffer to inject the metadata into
---@param force? boolean #Whether to forcefully override existing metadata
inject_metadata = function(buf, force)
module.public.write_metadata(buf, force, {})
end,

--- Inject the metadata into a buffer
---@param buf number #The number of the buffer to inject the metadata into
---@param force? boolean #Whether to forcefully override existing metadata
---@param metadata? table #Table of metadata data, overrides defaults if present
write_metadata = function(buf, force, metadata)
local present, data = module.public.is_metadata_present(buf)

if force or not present then
local constructed_metadata = module.public.construct_metadata(buf)
local constructed_metadata = module.public.create_metadata(buf, metadata)
vim.api.nvim_buf_set_lines(buf, data.range[1], data.range[2], false, constructed_metadata)
end
end,
Expand Down