Emacs: Denote version 3.0.0
Denote aims to be a simple-to-use, focused-in-scope, and effective note-taking and file-naming tool for Emacs.
Denote is based on the idea that files should follow a predictable and descriptive file-naming scheme. The file name must offer a clear indication of what the contents are about, without reference to any other metadata. Denote basically streamlines the creation of such files or file names while providing facilities to link between them (where those files are editable).
Denote’s file-naming scheme is not limited to “notes”. It can be used for all types of file, including those that are not editable in Emacs, such as videos. Naming files in a constistent way makes their filtering and retrieval considerably easier. Denote provides relevant facilities to rename files, regardless of file type.
- Package name (GNU ELPA):
denote
- Official manual: https://protesilaos.com/emacs/denote
- Change log: https://protesilaos.com/emacs/denote-changelog
- Git repositories:
- Video demo: https://protesilaos.com/codelog/2022-06-18-denote-demo/
- Backronyms: Denote Everything Neatly; Omit The Excesses. Don’t Ever Note Only The Epiphenomenal.
Below are the release notes.
Version 3.0.0 on 2024-06-30
This major release comes about two years after the first version of Denote, which was published on 2022-06-27. A lot of technicalities have changed in the meantime, though the core idea remains the same. In fact, the original video presentation I did is still relevant, especially for those looking to get started with Denote (but remember to consult the latest documentation for up-to-date information—and ask me if you have any questions).
Version 3 iterates on refinements that we made over the life cycle of version 2. Existing users will find that their workflow remains the same, though they now have even more options at their disposal.
As usual, my release notes are detailed. Please take your time to read them: they are here for you.
Special thanks to Jean-Philippe Gagné Guay, a long-time contributor to the project, for working on some of the items covered herein. I am not covering everything, as many important changes are not user-facing. Please consult the Git log for further details.
File name components can be written in any order
[ Relevant blog post: https://protesilaos.com/codelog/2024-05-19-emacs-denote-reorder-file-name-components/.]
Users can now change the variable denote-file-name-components-order
to affect how Denote file names are constructed. By default, file
names are written using this scheme (consult the manual for the
details):
IDENTIFIER--TITLE__KEYWORDS.EXT
An optional SIGNATURE
field can be added, thus:
IDENTIFIER==SIGNATURE--TITLE__KEYWORDS.EXT
By modifying the denote-file-name-components-order
, users can
produce file names like these:
--TITLE__KEYWORDS@@IDENTIFIER.EXT
__SIGNATURE--TITLE__KEYWORDS@@IDENTIFIER.EXT
__SIGNATURE--TITLE@@IDENTIFIER__KEYWORDS.EXT
Note that when the DATE
is not the first component, it gets the @@
prefix to (i) remain unambiguous and (ii) make it easy to target it
directly for search purposes.
Thanks to Jean-Philippe Gagné Guay for the contribution in pull request 360: https://github.com/protesilaos/denote/pull/360.
We discussed the possible delimiters for the IDENTIFIER
in issue
332: https://github.com/protesilaos/denote/issues/332. Thanks to
Jean-Philippe, Nick Bell, Maikol Solis, and mentalisttraceur for their
insights. Our concern was to use characters that are stylistically
fine, while they are not special symbol in regular expressions (as
those make searching a bit less convenient).
Please remember that the file-naming scheme is the cornerstone of Denote. If you do change how your notes are named, make sure to be consistent throughout, otherwise you will likely make it harder for yourself to find what you need.
Exclude certain files from all prompts
Sometimes users keep files in their denote-directory
that they do
not want to interactive with. These can, for example, be what Org
produces when exporting to another file format or when archiving a
heading.
The user option denote-excluded-files-regexp
makes is possible to
omit all those files from the relevant Denote prompts.
This is in response to requests for such a user option done by Samuel W. Flint and zadca123 in issues 376 and 384, respectively:
[ Please let me know if you need this feature but do not know how to write a regular expression. I can include concrete examples in the manual, though I need to know about them first. ]
Links in plain text and Markdown files are buttonised differently
Before we were using the function denote-link-buttonize-buffer
,
which would create “buttons” for all the denote:
links it would.
Users probably had something like this in their configuration:
;; DEPRECATED method
(add-hook 'text-mode-hook #'denote-link-buttonize-buffer)
We now provide an approach that is technically better by using Emacs’ fontification mechanism. All the user needs is to add this to their configuration:
(add-hook 'text-mode-hook #'denote-fontify-links-mode-maybe)
The notion of “maybe” in the symbol of that function is because this will take care to be activated only in the right context.
Thanks to Abdul-Lateef Haji-Ali for the contribution in pull request 344 (further changes by me): https://github.com/protesilaos/denote/pull/344.
Abdul-Lateef has assigned copyright to the Free Software Foundation.
How to make Org export work in a Denote silo
[ Relevant blog post: https://protesilaos.com/codelog/2024-06-18-emacs-denote-silos-org-export/. ]
This is not a change in Denote per se, though I have added the
relevant details in the manual. Basically, the Org export machinery
dismisses directory-local variables, thus breaking how Denote silos
work. We can work around this by having an extra #+bind
directive in
the front matter of each file. The manual, or the aforementioned blog
post, describe the technicalities.
Org headings can have their own backlinks
[ Relevant blog: https://protesilaos.com/codelog/2024-04-21-emacs-denote-heading-backlinks/. ]
Denote could already link to an Org heading directly. Now it can also
generate a backlinks buffer for the current heading, using the
command denote-org-extras-backlinks-for-heading
.
This is part of the optional extension denote-org-extras.el
(it is
part of the Denote package, but not loaded by default if you use
something like (require 'denote)
).
I am providing this as an option for those who absolutely need it, though in my opinion it is better to have atomic notes, such that each file contains information that is relevant as a whole. In this workflow, individual headings can be added or removed, but the big picture idea of the file remain intact.
At any rate, this change is possible due to the requisite refactoring of the code that handles the backlinks. We can technically produce backlinks to any pattern in files, though this may be more of interest to developers rather than foreshadow future features in core Denote.
Finer control over confirmations while renaming
The denote-rename-no-confirm
is deprecated and superseded by the
more flexible user option denote-rename-confirmations
.
The command denote-rename-file
(and others like it) prompts for
confirmation before changing the name of a file and updating its front
matter. The user option denote-rename-confirmations
controls what
the user is prompted for, if anything. Please consult its
documentation for the technicalities.
Thanks to Jean-Philippe Gagné Guay for the contribution in pull request 324: https://github.com/protesilaos/denote/pull/324.
The user option denote-save-buffer-after-creation
is renamed to denote-save-buffers
Please update your configuration accordingly, if you were using the old name.
The commands denote-keywords-add
and denote-keywords-remove
are replaced by denote-rename-file-keywords
The new command can add or remove keywords. It does this by
prepopulating the minibuffer prompt with the existing keywords. Users
can then use the crm-separator
(normally a comma), to write new
keywords or edit what is in the prompt to rewrite them accordingly. An
empty input means to remove all keywords.
[ NOTE: Please check with your minibuffer user interface how to
provide an empty input. The Emacs default setup accepts the empty
minibuffer contents as they are, though popular packages like
vertico
use the first available completion candidate instead. For
vertico
, the user must either move one up to select the prompt and
then type RET
there with empty contents, or use the command
vertico-exit-input
with empty contents. That Vertico command is
bound to M-RET
as of this writing on 2024-06-30 10:37 +0300. ]
Technically, denote-rename-file-keywords
is a wrapper for
denote-rename-file
, doing all the things that does.
The commands denote-rename-file-title
and denote-rename-file-signature
These are like the denote-rename-file-keywords
we just covered.
There are wrappers of the denote-rename-file
command, which are used
to change on the file name component they reference.
If that component exists, its text is included in the minibuffer. The user can then modify it accordingly. If there is no text, the user is adding a new one. An empty input means to remove the title/signature from the file altogether (again, check your minibuffer for how to provide an empty input).
More commands to add/remove keywords in bulk from Dired
Two new specialised commands are available to help users add or remove keywords from many files at once. These are:
denote-dired-rename-marked-files-add-keywords
denote-dired-rename-marked-files-remove-keywords
.
They complement the denote-dired-rename-marked-files-with-keywords
,
which we have had for a long time already, and which rewrites all the
keywords (instead of only adding/removing from the list).
All three of those commands operate only on the KEYWORDS
component
of the file name, leaving everything else as-is (while respecting the
aforementioned denote-file-name-components-order
).
Thanks to Vedang Manerikar for the contribution in pull request 316: https://github.com/protesilaos/denote/pull/316. Vedang has already assigned copyright to the Free Software Foundation.
The denote-org-extras-convert-links-to-file-type
can return relative paths
The previous implementation would always return an absolute file path,
ignoring the Org user option org-link-file-path-type
. Whereas now it
will return a relative path if that user option is set to a value of
either 'adaptive
or 'relative
.
Thanks to Alexandre Rousseau for the contribution in pull request 325: https://github.com/protesilaos/denote/pull/325. The change is small, meaning that Alexandre does not need to assign copyright to the Free Software Foundation.
For developers or advanced users
The denote-add-prompts
is made public
This is used to let
bind any additional prompts that should be used
by the denote
command. Check the source code for how we are using
this function.
The denote-select-linked-file-prompt
is now public
This is used internally but the commands denote-find-link
,
denote-find-backlink
. Refer to the implementation of those commands
to get an idea of how to use this prompt.
The denote-retrieve-title-or-filename
is just a wrapper
It simply calls the denote-retrieve-front-matter-title-value
or
denote-retrieve-filename-title
. We do not want it to return the
file-name-base
, as it used to, because this will duplicate the text
of the file name when there is no TITLE
component, as demonstrated by
duli in issue 347: https://github.com/protesilaos/denote/issues/347.
The denote-file-prompt
is more robust
We have made this function show relative file paths for the convenience of the user, but we take care to internally return and store the full file path (which is unambiguous). Thanks to Alan Schmitt for noting that the history was not working properly. This was done in issue 339: https://github.com/protesilaos/denote/issues/339. A series of commits dealt with the implementation details, including a contribution by Jean-Philippe Gagné Guay in pull request 342: https://github.com/protesilaos/denote/pull/342. Also read 353 for a further set of tweaks from my side: https://github.com/protesilaos/denote/discussions/353.
As part of these changes, the denote-file-prompt
now takes a
NO-REQUIRE-MATCH
argument. It also respects the aforementioned user
option of denote-excluded-files-regexp
.
Relevant functions conform with the denote-rename-confirmations
These include the denote-rename-file-prompt
and
denote-rewrite-front-matter
, as well as the new
denote-add-front-matter-prompt
.
This has the meaning of what I mentioned above. Commands that need to
deviate from the user option denote-rename-confirmations
can let
bind it accordingly: we even do this for some commands in denote.el
,
because certain prompts do not make sense there.
All file name components can be let
bound
We define a new series of variables which can be set to a lexically
scoped value to control what the denote
function parses. These are:
denote-use-date
denote-use-directory
denote-use-file-type
denote-use-keywords
denote-use-signature
denote-use-template
denote-use-title
Employ those for custom extensions you may have.
Thanks to Jean-Philippe Gagné Guay for adding those in pull request 365: https://github.com/protesilaos/denote/pull/365.
Miscellaneous
-
All the Org dynamic blocks defined by Denote in the optional
denote-org-extras.el
are now autoloaded. This means that evaluating such a code block will work even if the user has not explicitly used something like(require 'denote-org-extras)
. Thanks to Julian Hoch for asking for a relevant clarification in issue 337: https://github.com/protesilaos/denote/issues/337. Thanks to Kolmas for reporting some missing autoloads in issue 371: https://github.com/protesilaos/denote/issues/371. -
The value of the user option
denote-link-backlinks-display-buffer-action
is slightly modified to (i) make the buffer dedicated to its window and (ii) try to preserve its size during automatic recombinations of the frame’s layout. -
There was a regression in version
2.3.0
relative to2.2.0
where thedenote-link
command would fail in Org capture buffers. Thanks to Sven Seebeck for reporting this bug in issue 298: https://github.com/protesilaos/denote/issues/298. -
The
denote-filetype-heuristics
function no longer chokes if it gets a nil value (such as in Org capture buffers). -
The
denote-journal-extras-directory
(part of the optionaldenote-journal-extras
file) falls back todenote-directory
if its value is nil. This is what the user optiondenote-journal-extras-directory
promises in its doc string. -
All prompts should have their scope of application in all capital letters, such as
Select TEMPLATE key
. The idea is to make it easier for the user to quickly spot for the prompt is about. -
The user option
denote-link-description-function
is documented in the manual. Thanks to Sven Seebeck for noticing that we did not document this for the2.3.0
release. Thanks to Jean-Philippe Gagné Guay for helping me refine the code. This was all done in issue 298: https://github.com/protesilaos/denote/issues/298. -
As part of internal changes to how our various “rename” commands work, Kolmas reported a regression with wrongly assigned file extensions. This was done in issue 343: https://github.com/protesilaos/denote/issues/343.
-
In the
denote-org-extras.el
we now always jump to the correct Org heading line, instead of missing it by 1 under certain conditions. Thanks to kilesduli for bringing this matter to my attention in issue 354: https://github.com/protesilaos/denote/issues/354.
Policy for the aftermath of this release
The next few days or weeks are reserved for bug fixes. We first want to make sure that the current code base is rock solid, before making any further changes. Any bugs will be addressed outright and new point releases will be published (though those are not accompanied by a change log entry).
Git commits
Just an overview of what we did. Thanks again to everyone involved.
~/Git/Projects/denote $ git shortlog 2.3.0..3.0.0 --summary --numbered
169 Protesilaos Stavrou
52 Jean-Philippe Gagné Guay
3 Al Haji-Ali
2 Alan Schmitt
1 Alexandre Rousseau
1 Jianwei Hou
1 Vedang Manerikar