A set of lightweight Emacs functionalities augmenting the org-mode
note-taking and note management experience in a non-invasive manner.
A successor to zettel-mode but different enough to warrant being a separate project.
zettel2
focuses on providing a consistent naming scheme, links
resistant to file renaming and a graph showing the relationship
between the notes. All this while avoiding putting artificial
restrains such as limiting its use to a single directory.
zettel2
strives to be modular and not impose unnecessary
functionality upon the user. It contains the following modules:
zettel2
contains the base commands and the functions to work with the note IDs.zettel2-mode
provides a mode with a keymap exposing most of thezettel2
functionality.zettel2-link
provides a customorg-mode
link type (its format beingzettel:ID
) that behaves roughly like thefile:
links but contain only the note ID allowing to freely rename the file without breaking the link. The link is additionally decorated to make it clear it's an internal link between two notes and not to an external resource.zettel2-graph
visualizes the relationship between notes using GraphViz. Tracks both the specialzettel:
links and the standardfile:
links.
This system needs to work with any vanilla org-mode
file, no
special metadata needed. zettel2
shouldn't be bound to any specific
directory, its functionality shouldn't assume anything about where the
files are being kept or how many distinct sets of notes we own.
The only hard requirements concern the filename, not the file contents. Namely I've borrowed the excellent naming scheme from Denote by Protesilaos Stavrou et al. Please refer to its documentation for the details.
Due to how non-invasive it is, zettel2
composes very well with
various other packages, for example:
denote-dired-mode
can be used to decorate thedired
note listingsdeft
can be used to search and browse the notes
Some functionalities assume a flat directory structure, i.e. all the
notes in a given set exist in the same directory.
Subdirectories won't break anything per se, though the zettel:
links
cannot be used between directories (they always look for a given note
ID in the same directory) and the reference graph may be incomplete
(only the current directory is searched for links between the notes).
The note integrity must be preserved through almost any possible operation. As it stands, the only harmful operation is changing/removal of the note ID (file creation timestamp) from the filename as it's used for all the linking.
This is achieved first and foremost by not duplicating any information that doesn't absolutely need to be duplicated.
The filename contains:
- the note ID
- the machine-readable note title
- tags
The file contents contain:
- the human-readable note title
- the IDs of the linked notes (inside the links)
- optionally: the note ID; this one is actually duplicated from the
filename but they are immutable anyway and it could be handy in case
of data recovery or for compatibility with the vanilla
org-mode
The file contents specifically don't contain:
- the full file names of the linked notes (would break in case of a rename or retag)
- the note tags (would be duplicated with the filename and could become inconsistent with it)
zettel2-mode
exposes the following keymap (on top of the regular
org-mode
one):
- C-c C-n (
zettel2-create-note
) prompts for a title and tags for a new note and creates it according to the naming convention. - C-c C-M-r (
zettel2-graph
) calculate and display the graph of relationships between notes. - C-c C-r (
zettel2-backrefs
) show the notes linking to the current note usinggrep
. - M-n (
org-next-link
) - M-p (
org-previous-link
)
To install zettel2
mode using straight.el
, use the following code:
(use-package zettel2
:straight (:host github :repo "vifon/zettel2"
:files (:defaults "graph.pl"))
:after org
:hook (org-mode . zettel2-enable)
:init (defun zettel2-enable ()
(when (and buffer-file-name
(or (string-match-p "/\\.deft/[^/]+\\.org\\'" buffer-file-name)
(string-match-p "/zettels?/[^/]+\\.org\\'" buffer-file-name)))
(zettel2-minor-mode)))
:config (progn
(require 'zettel2-link)
(setq zettel2-graph-format "png")))
This specific configuration associates zettel2-minor-mode
with all
the *.org
files inside any directory named .deft
, zettel
or
zettels
. It also activates the custom link type and sets the
dependency graph format to "png". This is just an example (that the
author happens to use) and it's perfectly fine to customize it.
Another way would be to put the following into a .dir-locals.el
file
which would enable zettel2-minor-mode
whenever org-mode
is enabled
in this directory.
((org-mode . ((eval . (zettel2-minor-mode)))))
Installation with package.el
wasn't tested.