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

Conversation

Dynge
Copy link
Contributor

@Dynge Dynge commented Oct 25, 2023

This PR closes #1126. I did not want to deprecate any existing functionality so I've made new functions to write_metadata with potential new values instead of defaults.

Challenges

I am unsure if there is still is any need to use fs_open() to create the file, now that I instead create a new tab if no_open is true. My reasoning for creating a new tab is that in order to inject_metadata i need to have a buffer number, so I always open the new file in a new buffer. With tabs i can easily close the new tab without needing to worry about what else was open at the time.

Additional notes

I noticed that there does not seem to be an easy way to add categories into the metadata as it seems the metadata fields need to return a single string.
I thought about added functionality to allow tables of strings as well such that you could have a method return a collection of categories (e.g. { "[", " cat1", " cat2", "]" })

This method can be used to add custom metadata into file instead of
defaults. If table is empty of nil then simply uses default like
inject_metadata
@max397574
Copy link
Contributor

Tbh I don't like the way you do this. The whole things with the vim commands (:e, :tabnew etc)
Metagen just needs a bufnr and doesn't require the file to be open.
There are api functions to load a file to get a usable bufnr. I could send you those later.

@max397574
Copy link
Contributor

max397574 commented Oct 25, 2023

Here is an example where this was done
nvim-neorg/neorg-telescope@34a41e8#diff-38d33560722aa6a06ec8b1cd99066184484042c5302b0fdf0718d0afad1c7029R72-R93
not sure if you need to load the buffer or not for metagen. If not you can just use the function from dirman which's used there
or see how it's done there and just inline it

edit: realized you are in the dirman module so it should be really easy to use the function

@Dynge
Copy link
Contributor Author

Dynge commented Oct 25, 2023

Ah perfect. Thanks for the pointers @max397574

Ill edit the file to use that instead.

Any other thoughts on the function names and usage?

Also is there somewhere else i should write dokumentation for the usage?

@max397574
Copy link
Contributor

you can just write docs right above the function and inside the comment at the top of the file

@Dynge
Copy link
Contributor Author

Dynge commented Oct 25, 2023

I've changed the code to use dirman.get_file_bufnr instead - making it much cleaner.

Also tried to add some more documentation to describe the change.

Seems to work great - the only thing I am a little unhappy about is the implementation of categories that does not work so great in this.

It would be nice if categories could be a table and then it would insert them correctly on separate lines - like this:

dirman.create_file("note", "notes", { metadata = { categories = { "work", "programming" } } })

However that does not work in the current implementation because metadata is expected to be simply a string or a function that returns a string - not a table.
Its a special case because categories have a special syntax rule for multiline.
This may expand the scope of this pull request - unless there exists a very easy fix for that, that i am not aware of :)

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.

@@ -271,6 +284,9 @@ module.public = {
---@param opts? table additional options
Copy link
Contributor

Choose a reason for hiding this comment

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

normally people these days use classes for annotations in cases like this
e.g.

---@class neorg.dirman.new_note_opts
---@field no_open bool

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not aware of how to do that.
Can you point me to an example?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I see this
https://github.com/LuaLS/lua-language-server/wiki/Annotations#class

Should i just create an empty unused table in the top of the file and annotate that?

Is that the way to do it? 😄

Im quite new to lua 😅

Copy link
Contributor

Choose a reason for hiding this comment

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

you can just write the "class comments" as in my example above somewhere above the function. It would just be a comment block without any "real" code where you define the class with the fields (see this example https://github.com/LuaLS/lua-language-server/wiki/Annotations#field). And then you just use that class as the type of the parameter opts.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@max397574 I added @Class documentation now :)

@max397574
Copy link
Contributor

haven't tested the functionality but code lgtm

@Dynge
Copy link
Contributor Author

Dynge commented Oct 26, 2023

Just realize there may be a bug.

I do not think its possible to create a file without metadata if metagen is installed anymore.

We need to check if theres auto metagen setting enabled as well. However om not sure how it should work if auto metagen is off and you provide a non-empty table...

Any thoughts?

@max397574
Copy link
Contributor

I think if there is a table it should add metadata. Just set the default to nil and I think it should work as expected.

@Dynge
Copy link
Contributor Author

Dynge commented Oct 26, 2023

Alright. Ill test it out and later today 👍

Added class annotations to better describe the input options for
create_file and create_metadata.
@@ -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 :))

@Dynge
Copy link
Contributor Author

Dynge commented Oct 26, 2023

I think if there is a table it should add metadata. Just set the default to nil and I think it should work as expected.

Tested it with core.esupports.type = "none" and it works (it does not add metadata unless table is not nil) :)

Updated naming of @Class annotations to better align with the naming
used in the rest of the project.
Comment on lines 334 to 338
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. 😄

Dirman now broadcasts an event on file creation that metagen listen to.
Metagen then injects desired metadata if present.
@Dynge
Copy link
Contributor Author

Dynge commented Nov 7, 2023

Ive moved metagen creation into something that is executed on an event upon file creation instead.
This way dirman does not know what metagen decides to do with the data and it is properly separated. (Thanks for the tip @vhyrro)

I've also removed duplicated functions that I made previously in this pull request because i did not know that you can call functions just with without all input values :)

I've tested that i can create notes with metagen creation set to "auto" and "never" and it works as expected.

@vhyrro
Copy link
Member

vhyrro commented Nov 8, 2023

Ah I'm super sorry for not providing any help. Always ping me a few times so you can be sure I got the message haha.

Now the code looks good to me. Thank you for all the work put into this PR! 💜

@vhyrro vhyrro changed the title Option to inject specific metadata instead of defaults feat: option to inject specific metadata instead of defaults Nov 8, 2023
@vhyrro vhyrro merged commit 5509079 into nvim-neorg:main Nov 8, 2023
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Create note with differing filename and metadata title
3 participants