2429 lines
101 KiB
Org Mode
2429 lines
101 KiB
Org Mode
#+title: denote: Simple notes with an efficient file-naming scheme
|
||
#+author: Protesilaos Stavrou
|
||
#+email: info@protesilaos.com
|
||
#+language: en
|
||
#+options: ':t toc:nil author:t email:t num:t
|
||
#+startup: content
|
||
|
||
#+macro: stable-version 0.1.0
|
||
#+macro: release-date 2022-06-27
|
||
#+macro: development-version 0.2.0-dev
|
||
#+macro: file @@texinfo:@file{@@$1@@texinfo:}@@
|
||
#+macro: space @@texinfo:@: @@
|
||
#+macro: kbd @@texinfo:@kbd{@@$1@@texinfo:}@@
|
||
|
||
#+export_file_name: denote.texi
|
||
|
||
#+texinfo_filename: denote.info
|
||
#+texinfo_dir_category: Emacs misc features
|
||
#+texinfo_dir_title: Denote: (denote)
|
||
#+texinfo_dir_desc: Simple notes with an efficient file-naming scheme
|
||
#+texinfo_header: @set MAINTAINERSITE @uref{https://protesilaos.com,maintainer webpage}
|
||
#+texinfo_header: @set MAINTAINER Protesilaos Stavrou
|
||
#+texinfo_header: @set MAINTAINEREMAIL @email{info@protesilaos.com}
|
||
#+texinfo_header: @set MAINTAINERCONTACT @uref{mailto:info@protesilaos.com,contact the maintainer}
|
||
|
||
#+texinfo: @insertcopying
|
||
|
||
This manual, written by Protesilaos Stavrou, describes the customization
|
||
options for the Emacs package called =denote= (or =denote.el=), and
|
||
provides every other piece of information pertinent to it.
|
||
|
||
The documentation furnished herein corresponds to stable version
|
||
{{{stable-version}}}, released on {{{release-date}}}. Any reference to
|
||
a newer feature which does not yet form part of the latest tagged
|
||
commit, is explicitly marked as such.
|
||
|
||
Current development target is {{{development-version}}}.
|
||
|
||
+ Package name (GNU ELPA): =denote=
|
||
+ Official manual: <https://protesilaos.com/emacs/denote>
|
||
+ Change log: <https://protesilaos.com/emacs/denote-changelog>
|
||
+ Git repo on SourceHut: <https://git.sr.ht/~protesilaos/denote>
|
||
- Mirrors:
|
||
+ GitHub: <https://github.com/protesilaos/denote>
|
||
+ GitLab: <https://gitlab.com/protesilaos/denote>
|
||
+ Mailing list: <https://lists.sr.ht/~protesilaos/denote>
|
||
|
||
If you are viewing the README.org version of this file, please note that
|
||
the GNU ELPA machinery automatically generates an Info manual out of it.
|
||
|
||
#+toc: headlines 8 insert TOC here, with eight headline levels
|
||
|
||
* COPYING
|
||
:PROPERTIES:
|
||
:COPYING: t
|
||
:CUSTOM_ID: h:40b18bb2-4dc1-4202-bd0b-6fab535b2a0f
|
||
:END:
|
||
|
||
Copyright (C) 2022 Free Software Foundation, Inc.
|
||
|
||
#+begin_quote
|
||
Permission is granted to copy, distribute and/or modify this document
|
||
under the terms of the GNU Free Documentation License, Version 1.3 or
|
||
any later version published by the Free Software Foundation; with no
|
||
Invariant Sections, with the Front-Cover Texts being “A GNU Manual,” and
|
||
with the Back-Cover Texts as in (a) below. A copy of the license is
|
||
included in the section entitled “GNU Free Documentation License.”
|
||
|
||
(a) The FSF’s Back-Cover Text is: “You have the freedom to copy and
|
||
modify this GNU manual.”
|
||
#+end_quote
|
||
|
||
* Overview
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:a09b70a2-ae0b-4855-ac14-1dddfc8e3241
|
||
:END:
|
||
|
||
Denote aims to be a simple-to-use, focused-in-scope, and effective
|
||
note-taking tool for Emacs. It is based on the following core design
|
||
principles:
|
||
|
||
+ Predictability :: File names must follow a consistent and descriptive
|
||
naming convention ([[#h:4e9c7512-84dc-4dfb-9fa9-e15d51178e5d][The file-naming scheme]]). The file name alone
|
||
should offer a clear indication of what the contents are, without
|
||
reference to any other metadatum. This convention is not specific to
|
||
note-taking, as it is pertinent to any form of file that is part of
|
||
the user's long-term storage ([[#h:532e8e2a-9b7d-41c0-8f4b-3c5cbb7d4dca][Renaming files]]).
|
||
|
||
+ Composability :: Be a good Emacs citizen, by integrating with other
|
||
packages or built-in functionality instead of re-inventing functions
|
||
such as for filtering or greping. The author of Denote (Protesilaos,
|
||
aka "Prot") writes ordinary notes in plain text (=.txt=), switching on
|
||
demand to an Org file only when its expanded set of functionality is
|
||
required for the task at hand ([[#h:17896c8c-d97a-4faa-abf6-31df99746ca6][Points of entry]]).
|
||
|
||
+ Portability :: Notes are plain text and should remain portable. The
|
||
way Denote writes file names, the front matter it includes in the
|
||
note's header, and the links it establishes must all be adequately
|
||
usable with standard Unix tools. No need for a database or some
|
||
specialised software. As Denote develops and this manual is fully
|
||
fleshed out, there will be concrete examples on how to do the
|
||
Denote-equivalent on the command-line.
|
||
|
||
+ Flexibility :: Do not assume the user's preference for a note-taking
|
||
methodology. Denote is conceptually similar to the Zettelkasten
|
||
Method, which you can learn more about in this detailed introduction:
|
||
<https://zettelkasten.de/introduction/>. Notes are atomic (one file
|
||
per note) and have a unique identifier. However, Denote does not
|
||
enforce a particular methodology for knowledge management, such as a
|
||
restricted vocabulary or mutually exclusive sets of keywords. Denote
|
||
also does not check if the user writes thematically atomic notes. It
|
||
is up to the user to apply the requisite rigor and/or creativity in
|
||
pursuit of their preferred workflow ([[#h:6060a7e6-f179-4d42-a9de-a9968aaebecc][Writing metanotes]]).
|
||
|
||
+ Hackability :: Denote's code base consists of small and reusable
|
||
functions. They all have documentation strings. The idea is to make
|
||
it easier for users of varying levels of expertise to understand what
|
||
is going on and make surgical interventions where necessary (e.g. to
|
||
tweak some formatting). In this manual, we provide concrete examples
|
||
on such user-level configurations ([[#h:4a6d92dd-19eb-4fcc-a7b5-05ce04da3a92][Keep a journal or diary]]).
|
||
|
||
Now the important part... "Denote" is the familiar word, though it also
|
||
is a play on the "note" concept. Plus, we can come up with acronyms,
|
||
recursive or otherwise, of increasingly dubious utility like:
|
||
|
||
+ Don't Ever Note Only The Epiphenomenal
|
||
+ Denote Everything Neatly; Omit The Excesses
|
||
|
||
But we'll let you get back to work. Don't Eschew or Neglect your
|
||
Obligations, Tasks, and Engagements.
|
||
|
||
* The file-naming scheme
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:4e9c7512-84dc-4dfb-9fa9-e15d51178e5d
|
||
:END:
|
||
|
||
#+vindex: denote-directory
|
||
Notes are stored as a flat list in the ~denote-directory~ (i.e. no
|
||
subdirectories). The default path is =~/Documents/notes=.
|
||
|
||
Every note produced by Denote follows this pattern ([[#h:17896c8c-d97a-4faa-abf6-31df99746ca6][Points of entry]]):
|
||
|
||
: DATE--TITLE__KEYWORDS.EXTENSION
|
||
|
||
The =DATE= field represents the date in year-month-day format followed
|
||
by the capital letter =T= (for "time") and the current time in
|
||
hour-minute-second notation. The presentation is compact:
|
||
=20220531T091625=. The =DATE= serves as the unique identifier of each
|
||
note.
|
||
|
||
The =TITLE= field is the title of the note, as provided by the user. It
|
||
automatically gets downcased and hyphenated. An entry about "Economics
|
||
in the Euro Area" produces an =economics-in-the-euro-area= string for
|
||
the =TITLE= of the file name.
|
||
|
||
#+vindex: denote-allow-multi-word-keywords
|
||
The =KEYWORDS= field consists of one or more entries demarcated by an
|
||
underscore (the separator is inserted automatically). Each keyword is a
|
||
string provided by the user at the relevant prompt which broadly
|
||
describes the contents of the entry. Keywords that need to be more than
|
||
one-word-long must be written with hyphens: any other character, such as
|
||
spaces or the plus sign is automatically converted into a hyphen. So
|
||
when =emacs_library= appears in a file name, it is interpreted as two
|
||
distinct keywords, whereas =emacs-library= is one keyword. This is
|
||
reflected in how the keywords are recorded in the note ([[#h:13218826-56a5-482a-9b91-5b6de4f14261][Front matter]]).
|
||
While Denote supports multi-word keywords by default, the user option
|
||
~denote-allow-multi-word-keywords~ can be set to nil to forcibly join
|
||
all words into one, meaning that an input of =word1 word2= will be
|
||
written as =word1word2=.
|
||
|
||
#+vindex: denote-file-type
|
||
The =EXTENSION= is the file type. By default, it is =.org= (~org-mode~)
|
||
though the user option ~denote-file-type~ provides support for Markdown
|
||
with YAML or TOML variants (=.md= which runs ~markdown-mode~) and plain
|
||
text (=.txt= via ~text-mode~). Consult its doc string for the minutia.
|
||
While files end in the =.org= extension by default, the Denote code base
|
||
does not actually depend on org.el and/or its accoutrements.
|
||
|
||
Examples:
|
||
|
||
: 20220610T043241--initial-thoughts-on-the-zettelkasten-method__notetaking.org
|
||
: 20220610T062201--define-custom-org-hyperlink-type__denote_emacs_package.md
|
||
: 20220610T162327--on-hierarchy-and-taxis__notetaking_philosophy.txt
|
||
|
||
The different field separators, namely =--= and =__= introduce an
|
||
efficient way to anchor searches (such as with Emacs commands like
|
||
~isearch~ or from the command-line with ~find~ and related). A query
|
||
for =_word= always matches a keyword, while a regexp in the form of,
|
||
say, ="\\([0-9T]+?\\)--\\(.*?\\)_"= captures the date in group =\1= and
|
||
the title in =\2= (test any regular expression in the current buffer by
|
||
invoking =M-x re-builder=).
|
||
|
||
[[#h:1a953736-86c2-420b-b566-fb22c97df197][Features of the file-naming scheme for searching or filtering]].
|
||
|
||
While Denote is an Emacs package, notes should work long-term and not
|
||
depend on the functionality of a specific program. The file-naming
|
||
scheme we apply guarantees that a listing is readable in a variety of
|
||
contexts.
|
||
|
||
** Sluggified title and keywords
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:ae8b19a1-7f67-4258-96b3-370a72c43f4e
|
||
:END:
|
||
|
||
Denote has to be highly opinionated about which characters can be used
|
||
in file names and the file's front matter in order to enforce its
|
||
file-naming scheme. The private variable ~denote--punctuation-regexp~
|
||
holds the relevant value. In simple terms:
|
||
|
||
+ What we count as "illegal characters" are converted into hyphens.
|
||
|
||
+ Input for a file title is hyphenated and downcased. The original
|
||
value is preserved in the note's contents ([[#h:13218826-56a5-482a-9b91-5b6de4f14261][Front matter]]).
|
||
|
||
+ Keywords should not have spaces or other delimiters. If they do, they
|
||
are converted into hyphens. Keywords are always downcased.
|
||
|
||
** Features of the file-naming scheme for searching or filtering
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:1a953736-86c2-420b-b566-fb22c97df197
|
||
:END:
|
||
|
||
File names have three fields and two sets of field delimiters between
|
||
them:
|
||
|
||
: DATE--TITLE__KEYWORDS.EXTENSION
|
||
|
||
The first field delimiter is the double hyphen, while the second is the
|
||
double underscore. These practically serve as anchors for easier
|
||
searching. Consider this example:
|
||
|
||
: 20220621T062327--introduction-to-denote__denote_emacs.txt
|
||
|
||
You will notice that there are two matches for the word =denote=: one in
|
||
the title field and another in the keywords' field. Because of the
|
||
distinct field delimiters, if we search for =-denote= we only match the
|
||
first instance while =_denote= targets the second one. When sorting
|
||
through your notes, this kind of specificity is invaluable---and you get
|
||
it for free from the file names alone!
|
||
|
||
Users can get a lot of value out of this simple arrangement, even if
|
||
they have no knowledge of regular expressions. One thing to consider,
|
||
for maximum effect, is to avoid using multi-word keywords as those get
|
||
hyphenated like the title and will thus interfere with the above: either
|
||
set the user option ~denote-allow-multi-word-keywords~ to nil or simply
|
||
insert single words at the relevant prompts.
|
||
|
||
* Points of entry
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:17896c8c-d97a-4faa-abf6-31df99746ca6
|
||
:END:
|
||
|
||
#+findex: denote
|
||
#+findex: denote-type
|
||
#+findex: denote-org-capture
|
||
#+findex: denote-date
|
||
There are four ways to write a note with Denote: invoke the ~denote~,
|
||
~denote-type~, ~denote-date~ commands, or leverage the
|
||
~org-capture-templates~ by setting up a template which calls the
|
||
function ~denote-org-capture~.
|
||
|
||
In the first case, all that is needed is to run ~denote~. It will
|
||
prompt for a title. Once it is supplied, the command will ask for
|
||
keywords. The resulting note will have a file name as already explained
|
||
([[#h:4e9c7512-84dc-4dfb-9fa9-e15d51178e5d][The file naming scheme]]).
|
||
|
||
#+vindex: denote-known-keywords
|
||
#+vindex: denote-infer-keywords
|
||
The keyword prompt supports minibuffer completion. Available candidates
|
||
are those defined in the user option ~denote-known-keywords~. More
|
||
candidates can be inferred from the names of existing notes, by setting
|
||
~denote-infer-keywords~ to non-nil (which is the case by default).
|
||
|
||
#+vindex: denote-sort-keywords
|
||
Multiple keywords can be inserted by separating them with a comma (or
|
||
whatever the value of the ~crm-indicator~ is---which should be a comma).
|
||
When the user option ~denote-sort-keywords~ is non-nil (the default),
|
||
keywords are sorted alphabetically (technically, the sorting is done
|
||
with ~string-lessp~).
|
||
|
||
The ~denote~ command can also be called from Lisp, in which case it
|
||
expects the =TITLE= and =KEYWORDS= arguments. The former is a string,
|
||
the latter a list of strings.
|
||
|
||
The ~denote-type~ command is like ~denote~ except it also prompts for a
|
||
file type to use as a local value for ~denote-file-type~. In practical
|
||
terms, this lets you produce, say, a note in Markdown even though you
|
||
normally write in Org ([[#h:f34b172b-3440-446c-aec1-bf818d0aabfe][Notes in multiple file types]]).
|
||
|
||
Similarly, the ~denote-date~ command accepts the same =TITLE= and
|
||
=KEYWORDS= arguments, though it starts by asking for a date. Normally,
|
||
Denote use the current date and time to construct an identifier, but
|
||
~denote-date~ allows the user to specify any date+time combination. The
|
||
input for the =DATE= argument is like =2022-06-16= or =2022-06-16
|
||
14:30=. When the time is omitted, it is interpreted as =00:00=.
|
||
|
||
Since the ability to insert a date may result in duplicate identifiers,
|
||
Denote takes care to abort the operation if such an identity is
|
||
established (e.g. when you use ~denote-date~ with =2022-06-16= twice, it
|
||
will generate the same identifier of =20220616T000000=). The user must
|
||
thus call the ~denote-date~ command again and provide a unique value.
|
||
|
||
For integration with ~org-capture~, the user must first add the relevant
|
||
template. Such as:
|
||
|
||
#+begin_src emacs-lisp
|
||
(with-eval-after-load 'org-capture
|
||
(require 'denote-org-capture)
|
||
(add-to-list 'org-capture-templates
|
||
'("n" "New note (with Denote)" plain
|
||
(file denote-last-path)
|
||
#'denote-org-capture
|
||
:no-save t
|
||
:immediate-finish nil
|
||
:kill-buffer t
|
||
:jump-to-captured t)))
|
||
#+end_src
|
||
|
||
[ In the future, we might develop Denote in ways which do not require such
|
||
manual intervention. ]
|
||
|
||
Once the template is added, it is accessed from the specified key. If,
|
||
for instance, ~org-capture~ is bound to =C-c c=, then the note creation
|
||
is initiated with =C-c c n=. After that, the process is the same as
|
||
with invoking ~denote~ directly, namely: a prompt for a title followed
|
||
by a prompt for keywords.
|
||
|
||
#+vindex: denote-org-capture-specifiers
|
||
Users may prefer to leverage ~org-capture~ in order to extend file
|
||
creation with the specifiers described in the ~org-capture-templates~
|
||
documentation (such as to capture the active region and/or create a
|
||
hyperlink pointing to the given context). Due to the particular
|
||
file-naming scheme of Denote, such specifiers cannot be written directly
|
||
in the template. Instead, they have to be assigned to the user option
|
||
~denote-org-capture-specifiers~, which is interpreted by the function
|
||
~denote-org-capture~. Example with our default value:
|
||
|
||
#+begin_src emacs-lisp
|
||
(setq denote-org-capture-specifiers "%l\n%i\n%?")
|
||
#+end_src
|
||
|
||
Note that ~denote-org-capture~ ignores the ~denote-file-type~: it always
|
||
sets the Org file extension for the created note to ensure that the
|
||
capture process works as intended, especially for the desired output of
|
||
the ~denote-org-capture-specifiers~.
|
||
|
||
#+findex: denote-create-note
|
||
#+findex: denote-create-note-using-type
|
||
#+findex: denote-create-note-using-date
|
||
For convencience, the ~denote~ command has a ~denote-create-note~ alias.
|
||
Same for ~denote-type~ which is ~denote-create-note-using-type~ and
|
||
~denote-date~ that has ~denote-create-note-using-date~. The purpose of
|
||
these aliases is to provide alternative, more descriptive names of
|
||
select commands to aid with discoverability.
|
||
|
||
* Renaming files
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:532e8e2a-9b7d-41c0-8f4b-3c5cbb7d4dca
|
||
:END:
|
||
|
||
Denote's file-naming scheme is not specific to notes or text files: it
|
||
is useful for all sorts of files, such as multimedia and PDFs that form
|
||
part of the user's longer-term storage ([[#h:4e9c7512-84dc-4dfb-9fa9-e15d51178e5d][The file-naming scheme]]). While
|
||
Denote does not manage such files, it already has all the mechanisms to
|
||
facilitate the task of renaming them.
|
||
|
||
#+findex: denote-dired-rename-file
|
||
To this end, we provide the ~denote-dired-rename-file~ command. It has
|
||
a two-fold purpose: (i) to change the name of an existing file while
|
||
retaining its identifier and (ii) to write a Denote-compliant file name
|
||
for an item that was not created by ~denote~ or related commands (such
|
||
as an image or PDF).
|
||
|
||
The ~denote-dired-rename-file~ command will target the file at point if
|
||
it finds one in the current Dired buffer. Otherwise it prompts with
|
||
minibuffer completion for a file name. It then uses the familiar
|
||
prompts for a =TITLE= and =KEYWORDS= the same way the ~denote~ command
|
||
does ([[#h:17896c8c-d97a-4faa-abf6-31df99746ca6][Points of entry]]). As a final step, it asks for confirmation
|
||
before renaming the file at point, showing a message like:
|
||
|
||
#+begin_example
|
||
Rename sample.pdf to 20220612T052900--my-sample-title__testing.pdf? (y or n)
|
||
#+end_example
|
||
|
||
#+vindex: denote-dired-rename-expert
|
||
However, if the user option ~denote-dired-rename-expert~ is non-nil,
|
||
conduct the renaming operation outright---no questions asked.
|
||
|
||
When operating on a file that has no identifier, such as =sample.pdf=,
|
||
Denote reads the file properties to retrieve its last modification time.
|
||
If the file was from a past date like 2000-11-31 it will get an
|
||
identifier starting with =20001131= followed by the time component (per
|
||
our file-naming scheme).
|
||
|
||
The file type extension (e.g. =.pdf=) is read from the underlying file
|
||
and is preserved through the renaming process. Files that have no
|
||
extension are simply left without one.
|
||
|
||
Renaming only occurs relative to the current directory. Files are not
|
||
moved between directories.
|
||
|
||
#+vindex: denote-dired-post-rename-functions
|
||
#+findex: denote-dired-rewrite-front-matter
|
||
The final step of the ~denote-dired-rename-file~ command is to call the
|
||
special hook ~denote-dired-post-rename-functions~. Functions added to
|
||
that hook must accept three arguments, as explained in its doc string.
|
||
For the time being, the only function we define is the one which updates
|
||
the underlying note's front matter to match the new file name:
|
||
~denote-dired-rewrite-front-matter~. The function takes care to only
|
||
operate on an actual note, instead of arbitrary files.
|
||
|
||
DEVELOPMENT NOTE: the ~denote-dired-rewrite-front-matter~ needs to be
|
||
tested thoroughly. It rewrites file contents so we have to be sure it
|
||
does the right thing. To avoid any trouble, it always asks for
|
||
confirmation before performing the replacement. This confirmation
|
||
ignores ~denote-dired-rename-expert~ for the time being, though we might
|
||
want to lift that restriction once everything works as intended.
|
||
|
||
* Front matter
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:13218826-56a5-482a-9b91-5b6de4f14261
|
||
:END:
|
||
|
||
Notes have their own "front matter". This is a block of data at the top
|
||
of the file, with no empty lines between the entries, which is
|
||
automatically generated at the creation of a new note. The front matter
|
||
includes the title and keywords (aka "tags" or "filetags", depending on
|
||
the file type) which the user specified at the relevant prompt, as well
|
||
as the date and unique identifier which are derived automatically.
|
||
|
||
This is how it looks for Org mode (~denote-file-type~ is nil):
|
||
|
||
#+begin_src org
|
||
:PROPERTIES:
|
||
:ID: 20220610T202537
|
||
:END:
|
||
,#+title: This is a sample note
|
||
,#+date: 2022-06-10
|
||
,#+filetags: denote testing
|
||
#+end_src
|
||
|
||
Org notes use a =PROPERTIES= drawer at the top of the file for maximum
|
||
compatibility with the Org ecosystem, particularly for linking to notes
|
||
and exporting them ([[#h:fc913d54-26c8-4c41-be86-999839e8ad31][Linking notes]]).
|
||
|
||
For Markdown with YAML, the front matter looks like this
|
||
(~denote-file-type~ has the =markdown-yaml= value):
|
||
|
||
#+begin_src md
|
||
---
|
||
title: "This is a sample note"
|
||
date: 2022-06-10
|
||
tags: denote testing
|
||
identifier: "20220610T202021"
|
||
---
|
||
#+end_src
|
||
|
||
For Markdown with TOML, it looks like this (~denote-file-type~ has the
|
||
=markdown-toml= value):
|
||
|
||
#+begin_src md
|
||
+++
|
||
title = "This is a sample note"
|
||
date = 2022-06-10
|
||
tags = ["denote", "testing"]
|
||
identifier = "20220610T201510"
|
||
+++
|
||
#+end_src
|
||
|
||
And for plain text, we have the following (~denote-file-type~ has the
|
||
=text= value):
|
||
|
||
#+begin_example
|
||
title: This is a sample note
|
||
date: 2022-06-10
|
||
tags: denote testing
|
||
identifier: 20220610T202232
|
||
---------------------------
|
||
#+end_example
|
||
|
||
#+vindex: denote-front-matter-date-format
|
||
The format of the date in the front matter is controlled by the user
|
||
option ~denote-front-matter-date-format~:
|
||
|
||
- When the value is nil (the default), the date uses a plain
|
||
=YEAR-MONTH-DAY= notation, like =2022-06-08= (the ISO 8601 standard).
|
||
|
||
- When the value is the =org-timestamp= symbol, the date is recorded as
|
||
an inactive Org timestamp, such as =[2022-06-08 Wed 06:19]=.
|
||
|
||
- An arbitrary string value is interpreted as the argument for the
|
||
function ~format-time-string~. This gives the user maximum control
|
||
over how time is represented in the front matter.
|
||
|
||
When ~denote-file-type~ specifies one of the Markdown flavors, we ignore
|
||
this user option in order to enforce the RFC3339 specification (Markdown
|
||
is typically employed in static site generators as source code for Web
|
||
pages). However, when ~denote-front-matter-date-format~ has a string
|
||
value, this rule is suspended: we use whatever the user wants.
|
||
|
||
** Tweaking the front matter
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:f69371d5-1843-493d-9ff5-c1ab3b43024e
|
||
:END:
|
||
|
||
What follows is for advanced users. When in doubt, only configure
|
||
variables we describe as a "user option": they are declared in the
|
||
source code with the ~defcustom~ keyword.
|
||
|
||
Denote's code base is designed in a composable way, which lets the user
|
||
make precise interventions to affect the output of the relevant
|
||
commands. One such case is to configure the front matter, such as by
|
||
changing the order the keys appear in, renaming them, or adding new
|
||
elements.
|
||
|
||
Some examples are in order, starting with the Org file type. This is
|
||
what we have in =denote.el=:
|
||
|
||
#+begin_src emacs-lisp
|
||
(defvar denote-org-front-matter
|
||
":PROPERTIES:
|
||
:ID: %4$s
|
||
:END:
|
||
#+title: %s
|
||
#+date: %s
|
||
#+filetags: %s
|
||
\n"
|
||
"Org front matter value for `format'.
|
||
The order of the arguments is TITLE, DATE, KEYWORDS, ID. If you
|
||
are an avdanced user who wants to edit this variable to affect
|
||
how front matter is produced, consider using something like %2$s
|
||
to control where Nth argument is placed.")
|
||
#+end_src
|
||
|
||
Notice how we can pass a number to the =%s= specifier for the =:ID:=
|
||
property. This is what allows us to change the placement of the
|
||
provided arguments.
|
||
|
||
The default Org mode front matter is formatted as:
|
||
|
||
#+begin_src org
|
||
:PROPERTIES:
|
||
:ID: 20220610T202537
|
||
:END:
|
||
,#+title: This is a sample note
|
||
,#+date: 2022-06-10
|
||
,#+filetags: denote testing
|
||
#+end_src
|
||
|
||
If the user does not need =org-id= compatible ID property drawer, they
|
||
can do this instead:
|
||
|
||
#+begin_src emacs-lisp
|
||
(setq denote-org-front-matter
|
||
"#+title: %s
|
||
,#+date: %s
|
||
,#+filetags: %s
|
||
,#+identifier: %s
|
||
\n"
|
||
"Org front matter value for `format'.
|
||
The order of the arguments is TITLE, DATE, KEYWORDS, ID. If you
|
||
are an avdanced user who wants to edit this variable to affect
|
||
how front matter is produced, consider using something like %2$s
|
||
to control where Nth argument is placed.")
|
||
#+end_src
|
||
|
||
The output is now formatted thus:
|
||
|
||
#+begin_src org
|
||
,#+title: This is a sample note
|
||
,#+date: 2022-06-10
|
||
,#+filetags: denote testing
|
||
,#+identifier: 20220610T202537
|
||
#+end_src
|
||
|
||
For another example, we will use the plain text variant, as it differs a
|
||
bit from the above. By default it is formatted this way:
|
||
|
||
#+begin_example
|
||
title: This is a sample note
|
||
date: 2022-06-10
|
||
tags: denote testing
|
||
identifier: 20220610T202232
|
||
---------------------------
|
||
#+end_example
|
||
|
||
The line with the hyphens is the product of the fifth format specifier,
|
||
as documented in ~denote-text-front-matter~. Its value is stored in
|
||
~denote-text-front-matter-delimiter~. Say we want to have a delimiter
|
||
both at the top and bottom:
|
||
|
||
#+begin_src emacs-lisp
|
||
(setq denote-text-front-matter
|
||
"%5$s
|
||
title: %1$s
|
||
date: %2$s
|
||
tags: %3$s
|
||
identifier: %4$s
|
||
%5$s\n\n")
|
||
#+end_src
|
||
|
||
Which gives us:
|
||
|
||
#+begin_example
|
||
---------------------------
|
||
title: This is a sample note
|
||
date: 2022-06-11
|
||
tags: denote testing
|
||
identifier: 20220611T093252
|
||
---------------------------
|
||
#+end_example
|
||
|
||
Or we would rather use another character instead of hyphens, such as the
|
||
equals sign:
|
||
|
||
#+begin_src emacs-lisp
|
||
(setq denote-text-front-matter-delimiter (make-string 27 ?=))
|
||
#+end_src
|
||
|
||
Remember that this is for advanced users. If you want to see changes
|
||
done on this front, you are welcome to share your thoughts and/or
|
||
participate in the development of Denote.
|
||
|
||
* Linking notes
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:fc913d54-26c8-4c41-be86-999839e8ad31
|
||
:END:
|
||
|
||
#+findex: denote-link
|
||
The ~denote-link~ command inserts a link at point to an entry specified
|
||
at the minibuffer prompt. Links are formatted depending on the file
|
||
type of current note. In Org and plain text buffers, links are
|
||
formatted thus: =[[denote:IDENTIFIER][TITLE]]=. While in Markdown they
|
||
are expressed as =[TITLE](denote:IDENTIFIER)=.
|
||
|
||
When ~denote-link~ is called with a prefix argument (=C-u= by default)
|
||
it formats links like =[[denote:IDENTIFIER]]=. The user might prefer
|
||
its simplicity.
|
||
|
||
#+vindex: denote-link-use-org-id
|
||
When the user option ~denote-link-use-org-id~ is set to non-nil (default
|
||
is nil), inserted links in Org notes that target other Org notes will
|
||
use the standard =id:= type so the format is =[[id:IDENTIFIER][TITLE]]=
|
||
(the title is omitted is ~denote-link~ is called with a prefix argument,
|
||
as explained above). When, however, an Org note links to a note in
|
||
another file, the link with use our own =denote:= type as there is no
|
||
standard for this case.
|
||
|
||
Inserted links are automatically buttonized and remain active for as
|
||
long as the buffer is available. In Org this is handled automatically
|
||
as Denote either uses the standard =id:= link type or creates its own
|
||
custom hyperlink: the =denote:= type which works exactly like the
|
||
=file:=. In Markdown and plain text, Denote handles the buttonization
|
||
of those links.
|
||
|
||
To buttonize links in existing files while visiting them, the user must
|
||
add this snippet to their setup:
|
||
|
||
#+findex: denote-link-buttonize-buffer
|
||
#+begin_src emacs-lisp
|
||
(add-hook 'find-file-hook #'denote-link-buttonize-buffer)
|
||
#+end_src
|
||
|
||
#+findex: denote-link-find-file
|
||
Denote has a major-mode-agnostic mechanism to collect all linked file
|
||
references in the current buffer and return them as an appropriately
|
||
formatted list. This list can then be used in interactive commands.
|
||
The ~denote-link-find-file~ is such a command. It uses minibuffer
|
||
completion to visit a file that is linked to from the current note. The
|
||
candidates have the correct metadata, which is ideal for integration
|
||
with other standards-compliant tools ([[#h:8ed2bb6f-b5be-4711-82e9-8bee5bb06ece][Extending Denote]]). For instance,
|
||
a package such as =marginalia= will display accurate annotations, while
|
||
the =embark= package will be able to work its magic such as in exporting
|
||
the list into a filtered Dired buffer (i.e. a familiar Dired listing
|
||
with only the files of the current minibuffer session).
|
||
|
||
#+findex: denote-link-backlinks
|
||
The command ~denote-link-backlinks~ produces a bespoke buffer which
|
||
displays the file name of all notes linking to the current one. Each
|
||
file name appears on its own line and is buttonized so that it performs
|
||
the action of visiting the referenced file. The backlinks' buffer looks
|
||
like this:
|
||
|
||
#+begin_example
|
||
Backlinks to "On being honest" (20220614T130812)
|
||
------------------------------------------------
|
||
|
||
20220614T145606--let-this-glance-become-a-stare__journal.txt
|
||
20220616T182958--not-feeling-butterflies-in-your-stomach__journal.txt
|
||
#+end_example
|
||
|
||
#+vindex: denote-link-fontify-backlinks
|
||
The backlinks' buffer is fontified by default, though the user has
|
||
access to the ~denote-link-fontify-backlinks~ option to disable this
|
||
effect by setting its value to nil.
|
||
|
||
#+vindex: denote-link-backlinks-display-buffer-action
|
||
The placement of the backlinks' buffer is subject to the user option
|
||
~denote-link-backlinks-display-buffer-action~. Due to the nature of the
|
||
underlying ~display-buffer~ mechanism, this inevitably is an advanced
|
||
feature. By default, the backlinks' buffer is displayed below the
|
||
current window. The doc string of our user option includes a
|
||
configuration that places the buffer in a left side window instead.
|
||
Reproducing it here for your convenience:
|
||
|
||
#+begin_src emacs-lisp
|
||
(setq denote-link-backlinks-display-buffer-action
|
||
'((display-buffer-reuse-window
|
||
display-buffer-in-side-window)
|
||
(side . left)
|
||
(slot . 99)
|
||
(window-width . 0.3)))
|
||
#+end_src
|
||
|
||
#+findex: denote-link-add-links
|
||
The command ~denote-link-add-links~ adds links at point matching a
|
||
regular expression or plain string. The links are inserted as a
|
||
typographic list, such as:
|
||
|
||
#+begin_example
|
||
- link1
|
||
- link2
|
||
- link3
|
||
#+end_example
|
||
|
||
Each link is formatted according to the file type of the current note,
|
||
as explained further above about the ~denote-link~ command. The current
|
||
note is excluded from the matching entries (adding a link to itself is
|
||
pointless).
|
||
|
||
When called with a prefix argument (=C-u=) ~denote-link-add-links~ will
|
||
format all links as =[[TYPE:IDENTIFIER]]=, hence a typographic list:
|
||
|
||
#+begin_example
|
||
- [[TYPE:IDENTIFIER-1]]
|
||
- [[TYPE:IDENTIFIER-2]]
|
||
- [[TYPE:IDENTIFIER-3]]
|
||
#+end_example
|
||
|
||
The =TYPE= is either =denote:= or =id:=, exactly as we explained above
|
||
for the ~denote-link~ command.
|
||
|
||
Same examples of a regular expression that can be used with this
|
||
command:
|
||
|
||
- =journal= match all files which include =journal= anywhere in their
|
||
name.
|
||
|
||
- =_journal= match all files which include =journal= as a keyword.
|
||
|
||
- =^2022.*_journal= match all file names starting with =2022= and
|
||
including the keyword =journal=.
|
||
|
||
- =\.txt= match all files including =.txt=. In practical terms, this
|
||
only applies to the file extension, as Denote automatically removes
|
||
dots (and other characters) from the base file name.
|
||
|
||
If files are created with ~denote-sort-keywords~ as non-nil (the
|
||
default), then it is easy to write a regexp that includes multiple
|
||
keywords in alphabetic order:
|
||
|
||
- =_denote.*_package= match all files that include both the =denote= and
|
||
=package= keywords, in this order.
|
||
|
||
- =\(.*denote.*package.*\)\|\(.*package.*denote.*\)= is the same as
|
||
above, but out-of-order.
|
||
|
||
Remember that regexp constructs only need to be escaped once (like =\|=)
|
||
when done interactively but twice when called from Lisp. What we show
|
||
above is for interactive usage.
|
||
|
||
#+findex: denote-link-insert-link
|
||
#+findex: denote-link-show-backlinks-buffer
|
||
#+findex: denote-link-insert-links-matching-regexp
|
||
For convenience, the ~denote-link~ command has an alias called
|
||
~denote-link-insert-link~. The ~denote-link-backlinks~ can also be used
|
||
as ~denote-link-show-backlinks-buffer~. While ~denote-link-add-links~
|
||
is aliased ~denote-link-insert-links-matching-regexp~. The purpose of
|
||
these aliases is to offer alternative, more descriptive names of select
|
||
commands.
|
||
|
||
** Writing metanotes
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:6060a7e6-f179-4d42-a9de-a9968aaebecc
|
||
:END:
|
||
|
||
A "metanote" is an entry that describes other entries who have something
|
||
in common. Writing metanotes can be part of a workflow where the user
|
||
periodically reviews their work in search of patterns and deeper
|
||
insights. For example, you might want to read your journal entries from
|
||
the past year to reflect on your experiences, evolution as a person, and
|
||
the like.
|
||
|
||
The command ~denote-link-add-links~, which we covered extensively in the
|
||
previous section, is suited for this task ([[#h:fc913d54-26c8-4c41-be86-999839e8ad31][Linking notes]]). You will
|
||
create your metanote the way you use Denote ordinarily (metanotes may
|
||
have the =metanote= keyword), write an introduction or however you want
|
||
to go about it, invoke ~denote-link-add-links~ to cite the notes that
|
||
match the given regexp, and continue writing.
|
||
|
||
Metanotes can serve as entry points to groupings of individual notes.
|
||
They are not the same as a filtered list of files, i.e. what you would
|
||
do in Dired or the minibuffer where you narrow the list of notes to a
|
||
given query. Metanotes contain the filtered list plus your thoughts
|
||
about it. The act of purposefully grouping notes together and
|
||
contemplating on their shared patterns is what adds value.
|
||
|
||
Your future self will appreciate metanotes for the function they serve
|
||
in encapsulating knowledge, while current you will be equipped with the
|
||
knowledge derived from the deliberate self-reflection.
|
||
|
||
* Fontification in Dired
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:337f9cf0-9f66-45af-b73f-f6370472fb51
|
||
:END:
|
||
|
||
#+findex: denote-dired-mode
|
||
One of the upsides of Denote's file-naming scheme is the predictable
|
||
pattern it establishes, which appears as a near-tabular presentation in
|
||
a listing of notes (i.e. in Dired). The ~denote-dired-mode~ can help
|
||
enhance this impression, by fontifying the components of the file name
|
||
to make the date (identifier) and keywords stand out.
|
||
|
||
There are two ways to set the mode. Either use it for all directories,
|
||
which probably is not needed:
|
||
|
||
#+begin_src emacs-lisp
|
||
(require 'denote-dired)
|
||
(add-hook 'dired-mode-hook #'denote-dired-mode)
|
||
#+end_src
|
||
|
||
#+vindex: denote-dired-directories
|
||
#+findex: denote-dired-mode-in-directories
|
||
Or configure the user option ~denote-dired-directories~ and then set up
|
||
the function ~denote-dired-mode-in-directories~:
|
||
|
||
#+begin_src emacs-lisp
|
||
(require 'denote-dired)
|
||
|
||
;; We use different ways to specify a path for demo purposes.
|
||
(setq denote-dired-directories
|
||
(list denote-directory
|
||
(thread-last denote-directory (expand-file-name "attachments"))
|
||
(expand-file-name "~/Documents/vlog")))
|
||
|
||
(add-hook 'dired-mode-hook #'denote-dired-mode-in-directories)
|
||
#+end_src
|
||
|
||
The faces we define are:
|
||
|
||
#+vindex: denote-dired-field-date
|
||
#+vindex: denote-dired-field-delimiter
|
||
#+vindex: denote-dired-field-extension
|
||
#+vindex: denote-dired-field-keywords
|
||
#+vindex: denote-dired-field-time
|
||
#+vindex: denote-dired-field-title
|
||
+ ~denote-dired-field-date~
|
||
+ ~denote-dired-field-delimiter~
|
||
+ ~denote-dired-field-extension~
|
||
+ ~denote-dired-field-keywords~
|
||
+ ~denote-dired-field-time~
|
||
+ ~denote-dired-field-title~
|
||
|
||
For the time being, the =diredfl= package is not compatible with this
|
||
facility.
|
||
|
||
The ~denote-dired-mode~ does not only fontify note files that were
|
||
created by Denote: it covers every file name that follows our naming
|
||
conventions ([[#h:4e9c7512-84dc-4dfb-9fa9-e15d51178e5d][The file-naming scheme]]). This is particularly useful for
|
||
scenaria where, say, one wants to organise their collection of PDFs and
|
||
multimedia in a systematic way (and, perhaps, use them as attachments
|
||
for the notes Denote produces).
|
||
|
||
* Minibuffer histories
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:82dc1203-d689-44b2-9a6c-b37776209651
|
||
:END:
|
||
|
||
Denote has a dedicated minibuffer history for each one of its prompts.
|
||
This practically means that using =M-p= (~previous-history-element~) and
|
||
=M-n= (~next-history-element~) will only cycle through the relevant
|
||
record of inputs, such as your latest titles in the =TITLE= prompt, and
|
||
keywords in the =KEYWORDS= prompt.
|
||
|
||
The built-in =savehist= library saves minibuffer histories. Sample
|
||
configuration:
|
||
|
||
#+begin_src emacs-lisp
|
||
(require 'savehist)
|
||
(setq savehist-file (locate-user-emacs-file "savehist"))
|
||
(setq history-length 10000)
|
||
(setq history-delete-duplicates t)
|
||
(setq savehist-save-minibuffer-history t)
|
||
(add-hook 'after-init-hook #'savehist-mode)
|
||
#+end_src
|
||
|
||
* Notes in multiple file types
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:f34b172b-3440-446c-aec1-bf818d0aabfe
|
||
:END:
|
||
|
||
As noted before, Denote does not have a particular preference on the
|
||
workflow the user wishes to follow nor does it expect a specific file
|
||
type. It is entirely possible to store notes in a variety of formats
|
||
across multiple directories and Denote will still be able to work with
|
||
them, provided they follow the file-naming scheme and have an identifier
|
||
in their front matter, where relevant. Here we show how to create new
|
||
notes that take the example of the ~denote-type~ command and take it one
|
||
step further.
|
||
|
||
Suppose you want to use the ~denote~ command to store some notes in
|
||
Markdown, others in Org, and others still in plain text. Maybe you also
|
||
want to place each of those in its own directory. Using the
|
||
~denote-type~ command is not sufficient, as it only operates on the
|
||
value of the user option ~denote-directory~. You need some small
|
||
wrapper functions.
|
||
|
||
For example:
|
||
|
||
+ =~/Documents/notes/= is your default and contains Org files.
|
||
+ =~/Documents/blog/= holds the files of your blog.
|
||
+ =~/Documents/random/= is where you scribble thoughts in plain text.
|
||
|
||
Why would you do that? It does not matter. This is for didactic
|
||
purposes. All you need to do is write functions that ~let~ bind the
|
||
~denote-directory~ and to the desired value.
|
||
|
||
#+begin_src emacs-lisp
|
||
(defun my-denote-markdown-toml ()
|
||
"Create Markdown+TOML note in ~/Documents/blog/."
|
||
(interactive)
|
||
(let ((denote-file-type 'markdown-toml)
|
||
(denote-directory "~/Documents/blog/"))
|
||
(call-interactively #'denote)))
|
||
|
||
(defun my-denote-plain-text ()
|
||
"Create plain text note in ~/Documents/random/."
|
||
(interactive)
|
||
(let ((denote-file-type 'text)
|
||
(denote-directory "~/Documents/random/"))
|
||
(call-interactively #'denote)))
|
||
#+end_src
|
||
|
||
You do not need a third command for the Org files, as those would be the
|
||
default used by regular ~denote~.
|
||
|
||
Given Denote's composable code, you can tweak the output however you
|
||
like, including the contents of the file ([[#h:f69371d5-1843-493d-9ff5-c1ab3b43024e][Tweaking the front matter]]).
|
||
|
||
If you do place different types of notes in their own directories, you
|
||
must introduce directory-local variables to keep things working
|
||
seamlessly. Otherwise you cannot create notes, retrieve backlinks, and
|
||
so on. To that end, the ~denote-directory~ variable considers the
|
||
symbols =default-directory= or =local= as safe local variables. Write a
|
||
=.dir-locals.el= file in each of your non-default notes directories with
|
||
the following contents (replacing =default-directory= with =local=, if
|
||
you prefer):
|
||
|
||
#+begin_src emacs-lisp
|
||
;;; Directory Local Variables
|
||
;;; For more information see (info "(emacs) Directory Variables")
|
||
|
||
((nil . ((denote-directory . default-directory))))
|
||
#+end_src
|
||
|
||
This will allow things to work smoothly (e.g. ~denote-infer-keywords~).
|
||
|
||
Your default ~denote-directory~ does not need this, as it already is the
|
||
normal target that Denote uses.
|
||
|
||
Want to automate aspects of note creation ([[#h:4a6d92dd-19eb-4fcc-a7b5-05ce04da3a92][Keep a journal or diary]])?
|
||
Have more ideas? Something does not work quite right? Areas you wish
|
||
were more abstract in the code? Please participate in the development
|
||
process.
|
||
|
||
** Keep a journal or diary
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:4a6d92dd-19eb-4fcc-a7b5-05ce04da3a92
|
||
:END:
|
||
|
||
While there are subtle technical differences between a journal and a
|
||
diary, we will consider those equivalent in the interest of brevity:
|
||
they both describe a personal space that holds a record of your thoughts
|
||
about your experiences and/or view of events in the world.
|
||
|
||
Suppose you are committed to writing an entry every day. Unlike what we
|
||
demonstrated before, your writing will follow a regular naming pattern
|
||
([[#h:f34b172b-3440-446c-aec1-bf818d0aabfe][Notes in multiple file types]]). You know that the title of the new note
|
||
must always look like =Tuesday 14 June 2022= and the keyword has to be
|
||
=journal= or =diary=. As such, you want to automate the task instead of
|
||
being prompted each time, as is the norm with ~denote~ and the relevant
|
||
commands ([[#h:17896c8c-d97a-4faa-abf6-31df99746ca6][Points of entry]]). This is easy to accomplish because ~denote~
|
||
can be called from Lisp and given the required arguments of =TITLE= and
|
||
=KEYWORDS= directly. All you need is a simple wrapper function:
|
||
|
||
#+begin_src emacs-lisp
|
||
(defun my-denote-journal ()
|
||
"Create an entry tagged 'journal' with the date as its title."
|
||
(interactive)
|
||
(denote
|
||
(format-time-string "%A %e %B %Y") ; format like Tuesday 14 June 2022
|
||
"journal")) ; multiple keywords are a list of strings: '("one" "two")
|
||
#+end_src
|
||
|
||
By invoking ~my-denote-journal~ you will go straight into the newly
|
||
created note and commit to your writing outright.
|
||
|
||
Of course, you can always set up the function so that it asks for a
|
||
=TITLE= but still automatically applies the =journal= tag:
|
||
|
||
#+begin_src emacs-lisp
|
||
(defun denote-journal-with-title ()
|
||
"Create an entry tagged 'journal', while prompting for a title."
|
||
(interactive)
|
||
(denote
|
||
(denote--title-prompt) ; ask for title, instead of using human-readable date
|
||
"journal"))
|
||
#+end_src
|
||
|
||
Sometimes journaling is done with the intent to hone one's writing
|
||
skills. Perhaps you are learning a new language or wish to communicate
|
||
your ideas with greater clarity and precision. As with everything that
|
||
requires a degree of sophistication, you have to work for it---write,
|
||
write, write!
|
||
|
||
One way to test your progress is to set a timer. It helps you gauge
|
||
your output and its quality. To use a timer with Emacs, consider the
|
||
=tmr= package:
|
||
|
||
#+begin_src emacs-lisp
|
||
(defun my-denote-journal-with-tmr ()
|
||
"Like `my-denote-journal', but also set a 10-minute timer.
|
||
The `tmr' command is part of the `tmr' package."
|
||
(interactive)
|
||
(denote
|
||
(format-time-string "%A %e %B %Y")
|
||
"journal")
|
||
(tmr 10 "Practice writing in my journal")) ; set 10 minute timer with a description
|
||
#+end_src
|
||
|
||
Once the timer elapses, stop writing and review your performance.
|
||
Practice makes perfect!
|
||
|
||
[ As Denote matures, we may add hooks to control what happens before or
|
||
after the creation of a new note. We shall also document more
|
||
examples of tasks that can be accomplished with this package. ]
|
||
|
||
Sources for =tmr=:
|
||
|
||
+ Package name (GNU ELPA): =tmr=
|
||
+ Official manual: <https://protesilaos.com/emacs/tmr>
|
||
+ Change log: <https://protesilaos.com/emacs/denote-changelog>
|
||
+ Git repo on SourceHut: <https://git.sr.ht/~protesilaos/tmr>
|
||
- Mirrors:
|
||
+ GitHub: <https://github.com/protesilaos/tmr>
|
||
+ GitLab: <https://gitlab.com/protesilaos/tmr>
|
||
+ Mailing list: <https://lists.sr.ht/~protesilaos/tmr>
|
||
|
||
Recall what we discussed elsewhere in the manual about changing the file
|
||
type and target directory ([[#h:f34b172b-3440-446c-aec1-bf818d0aabfe][Notes in multiple file types]]). You basically
|
||
~let~ bind the relevant variables. Such bindings are specific to the
|
||
function: they do not affect anything outside of it, so you can keep the
|
||
defaults for your regular notes and use something different for your
|
||
journaling. For example, the following snippet is like the previous
|
||
sample of writing a journal entry and setting a timer, but it also uses
|
||
a plain text file type and adds the new note to the
|
||
=~/Documents/journal/= directory:
|
||
|
||
#+begin_src emacs-lisp
|
||
(defun my-denote-journal-with-tmr-and-custom-type-and-dir ()
|
||
"Like `my-denote-journal-with-tmr' with custom type and directory."
|
||
(interactive)
|
||
(let ((denote-file-type 'text) ; it supports other file types as well: read its doc string
|
||
(denote-directory "~/Documents/journal/"))
|
||
(denote
|
||
(format-time-string "%A %e %B %Y")
|
||
"journal")
|
||
(tmr 10 "Practice writing in my journal")))
|
||
#+end_src
|
||
|
||
Finally, we can incorporate the idea of the ~denote-date~ command into
|
||
our journaling workflow. Unlike regular ~denote~, this command has a
|
||
slightly different structure. Below are variants of the aforementioned
|
||
ideas. If you pick more than one, just give them a unique name (the
|
||
text right after ~defun~):
|
||
|
||
#+begin_src emacs-lisp
|
||
(defun my-denote-journal-with-date (date title)
|
||
"Ask for DATE and TITLE to write a journal entry.
|
||
|
||
Read the doc string of `denote-date' on what a valid DATE is."
|
||
(interactive
|
||
(list
|
||
(denote--date-prompt)
|
||
(denote--title-prompt)))
|
||
(when-let ((d (denote--valid-date date))
|
||
(id (format-time-string denote--id-format d))
|
||
((denote--barf-duplicate-id id)))
|
||
(denote--prepare-note title "journal" nil d id)))
|
||
|
||
(defun my-denote-journal-with-date (date)
|
||
"Ask for DATE to write a journal entry.
|
||
|
||
Read the doc string of `denote-date' on what a valid DATE input is.
|
||
|
||
The title of the note is something like Tuesday 17 June 2020,
|
||
though you can modify the `format-time-string' specifiers as
|
||
described in its doc string."
|
||
(interactive (list (denote--date-prompt)))
|
||
(when-let ((d (denote--valid-date date))
|
||
(id (format-time-string denote--id-format d))
|
||
((denote--barf-duplicate-id id)))
|
||
(denote--prepare-note
|
||
(format-time-string "%A %e %B %Y" d)
|
||
"journal" nil d id)))
|
||
|
||
(defun my-denote-journal-with-date (date)
|
||
"Ask for DATE to write a journal entry.
|
||
|
||
Journal entries are stored in ~/Documents/journal/ and use plain
|
||
text for their `denote-file-type'.
|
||
|
||
Read the doc string of `denote-date' on what a valid DATE input is.
|
||
|
||
The title of the note is something like Tuesday 17 June 2020,
|
||
though you can modify the `format-time-string' specifiers as
|
||
described in its doc string."
|
||
(interactive (list (denote--date-prompt)))
|
||
(when-let ((d (denote--valid-date date))
|
||
(id (format-time-string denote--id-format d))
|
||
((denote--barf-duplicate-id id))
|
||
(denote-file-type 'text) ; it supports other file types as well: read its doc string
|
||
(denote-directory "~/Documents/journal/"))
|
||
(denote--prepare-note
|
||
(format-time-string "%A %e %B %Y" d)
|
||
"journal" nil d id)))
|
||
|
||
(defun my-denote-journal-with-date (date)
|
||
"Ask for DATE to write a journal entry and start a 10-minute tmr.
|
||
|
||
Journal entries are stored in ~/Documents/journal/ and use plain
|
||
text for their `denote-file-type'. The `tmr' command comes from
|
||
the package of the same name (same dev as Denote's).
|
||
|
||
Read the doc string of `denote-date' on what a valid DATE input is.
|
||
|
||
The title of the note is something like Tuesday 17 June 2020,
|
||
though you can modify the `format-time-string' specifiers as
|
||
described in its doc string."
|
||
(interactive (list (denote--date-prompt)))
|
||
(when-let ((d (denote--valid-date date))
|
||
(id (format-time-string denote--id-format d))
|
||
((denote--barf-duplicate-id id))
|
||
(denote-file-type 'text) ; it supports other file types as well: read its doc string
|
||
(denote-directory "~/Documents/journal/"))
|
||
(denote--prepare-note
|
||
(format-time-string "%A %e %B %Y" d)
|
||
"journal" nil d id)
|
||
(tmr 10 "Practice writing in my journal")))
|
||
#+end_src
|
||
|
||
* Extending Denote
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:8ed2bb6f-b5be-4711-82e9-8bee5bb06ece
|
||
:END:
|
||
|
||
Denote is a tool with a narrow scope: create notes and link between
|
||
them, based on the aforementioned file-naming scheme. For other common
|
||
operations the user is advised to rely on standard Emacs facilities or
|
||
specialised third-party packages. This section covers the details.
|
||
|
||
** Narrow the list of files in Dired
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:ea173a01-69ef-4574-89a7-6e60ede02f13
|
||
:END:
|
||
|
||
Emacs' standard file manager (or directory editor) can read a regular
|
||
expression to mark the matching files. This is the command
|
||
~dired-mark-files-regexp~, which is bound to =% m= by default. For
|
||
example, =% m _denote= will match all files that have the =denote=
|
||
keyword ([[#h:1a953736-86c2-420b-b566-fb22c97df197][Features of the file-naming scheme for searching or filtering]]).
|
||
|
||
Once the files are matched, the user has to options: (i) narrow the list
|
||
to the matching items or (ii) exclude the matching items from the list.
|
||
|
||
For the former, we want to toggle the marks by typing =t= (calls the
|
||
command ~dired-toggle-marks~ by default) and then hit the letter =k=
|
||
(for ~dired-do-kill-lines~). The remaining files are those that match
|
||
the regexp that was provided earlier.
|
||
|
||
For the latter approach of filtering out the matching items, simply
|
||
involves the use of the =k= command (~dired-do-kill-lines~) to omit the
|
||
marked files from the list.
|
||
|
||
These sequences can be combined to incrementally narrow the list. Note
|
||
that ~dired-do-kill-lines~ does not delete files: it simply hides them
|
||
from the current view.
|
||
|
||
Revert to the original listing with =g= (~revert-buffer~).
|
||
|
||
For a convenient wrapper, consider this example:
|
||
|
||
#+begin_src emacs-lisp
|
||
(defvar prot-dired--limit-hist '()
|
||
"Minibuffer history for `prot-dired-limit-regexp'.")
|
||
|
||
;;;###autoload
|
||
(defun prot-dired-limit-regexp (regexp omit)
|
||
"Limit Dired to keep files matching REGEXP.
|
||
|
||
With optional OMIT argument as a prefix (\\[universal-argument]),
|
||
exclude files matching REGEXP.
|
||
|
||
Restore the buffer with \\<dired-mode-map>`\\[revert-buffer]'."
|
||
(interactive
|
||
(list
|
||
(read-regexp
|
||
(concat "Files "
|
||
(when current-prefix-arg
|
||
(propertize "NOT " 'face 'warning))
|
||
"matching PATTERN: ")
|
||
nil 'prot-dired--limit-hist)
|
||
current-prefix-arg))
|
||
(dired-mark-files-regexp regexp)
|
||
(unless omit (dired-toggle-marks))
|
||
(dired-do-kill-lines))
|
||
#+end_src
|
||
|
||
** Use Embark to collect minibuffer candidates
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:edf9b651-86eb-4d5f-bade-3c9e270082f0
|
||
:END:
|
||
|
||
=embark= is a remarkable package that lets you perform relevant,
|
||
context-dependent actions using a prefix key (simplifying in the
|
||
interest of brevity).
|
||
|
||
For our purposes, Embark can be used to produce a Dired listing directly
|
||
from the minibuffer. Suppose the current note has links to three other
|
||
notes. You might use the ~denote-link-find-file~ command to pick one
|
||
via the minibuffer. But why not turn those three links into their own
|
||
Dired listing? While in the minibuffer, invoke ~embark-act~ which you
|
||
may have already bound to =C-.= and then follow it up with =E= (for the
|
||
~embark-export~ command).
|
||
|
||
This pattern can be repeated with any list of candidates, meaning that
|
||
you can narrow the list by providing some input before eventually
|
||
exporting the results with Embark.
|
||
|
||
Overall, this is very powerful and you might prefer it over doing the
|
||
same thing directly in Dired, since you also benefit from all the power
|
||
of the minibuffer ([[#h:ea173a01-69ef-4574-89a7-6e60ede02f13][Narrow the list of files in Dired]]).
|
||
|
||
** Search file contents
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:76198fab-d6d2-4c67-9ccb-7a08cc883952
|
||
:END:
|
||
|
||
Emacs provides built-in commands which are wrappers of standard Unix
|
||
tools: =M-x grep= lets the user input the flags of a ~grep~ call and
|
||
pass a regular expression to the =-e= flag.
|
||
|
||
The author of Denote uses this thin wrapper instead:
|
||
|
||
#+begin_src emacs-lisp
|
||
(defvar prot-search--grep-hist '()
|
||
"Input history of grep searches.")
|
||
|
||
;;;###autoload
|
||
(defun prot-search-grep (regexp &optional recursive)
|
||
"Run grep for REGEXP.
|
||
|
||
Search in the current directory using `lgrep'. With optional
|
||
prefix argument (\\[universal-argument]) for RECURSIVE, run a
|
||
search starting from the current directory with `rgrep'."
|
||
(interactive
|
||
(list
|
||
(read-from-minibuffer (concat (if current-prefix-arg
|
||
(propertize "Recursive" 'face 'warning)
|
||
"Local")
|
||
" grep for PATTERN: ")
|
||
nil nil nil 'prot-search--grep-hist)
|
||
current-prefix-arg))
|
||
(unless grep-command
|
||
(grep-compute-defaults))
|
||
(if recursive
|
||
(rgrep regexp "*" default-directory)
|
||
(lgrep regexp "*" default-directory)))
|
||
#+end_src
|
||
|
||
Rather than maintain custom code, consider using the excellent =consult=
|
||
package: it provides commands such as ~consult-grep~ and ~consult-find~
|
||
which provide live results and are generally easier to use than the
|
||
built-in commands.
|
||
|
||
** Bookmark the directory with the notes
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:1bba4c1e-6812-4749-948f-57df4fd49b36
|
||
:END:
|
||
|
||
Part of the reason Denote does not reinvent existing functionality is to
|
||
encourage you to learn more about Emacs. You do not need a bespoke
|
||
"jump to my notes" directory because such commands do not scale well.
|
||
Will you have a "jump to my downloads" then another for multimedia and
|
||
so on? No.
|
||
|
||
Emacs has a built-in framework for recording persistent markers to
|
||
locations. Visit the ~denote-directory~ (or any dir/file for that
|
||
matter) and invoke the ~bookmark-set~ command (bound to =C-x r m= by
|
||
default). It lets you create a bookmark.
|
||
|
||
The list of bookmarks can be reviewed with the ~bookmark-bmenu-list~
|
||
command (bound to =C-x r l= by default). A minibuffer interface is
|
||
available with ~bookmark-jump~ (=C-x r b=).
|
||
|
||
If you use the =consult= package, its default ~consult-buffer~ command
|
||
has the means to group together buffers, recent files, and bookmarks.
|
||
Each of those types can be narrowed to with a prefix key. The package
|
||
=consult-dir= is an extension to =consult= which provides useful extras
|
||
for working with directories, including bookmarks.
|
||
|
||
** Use the consult-notes package
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:8907f4bc-992a-45bc-a60e-267ed1ce9c2d
|
||
:END:
|
||
|
||
If you are already using =consult= (which is a brilliant package), you
|
||
will probably like its =consult-notes= extension. It uses the familiar
|
||
mechanisms of Consult to filter searches via a prefix key. For example:
|
||
|
||
#+begin_src emacs-lisp
|
||
(setq consult-notes-data-dirs
|
||
`(("Notes" ?n ,denote-directory)
|
||
("Books" ?b "~/Documents/books")))
|
||
#+end_src
|
||
|
||
With the above, =M-x consult-notes= will list the files in those two
|
||
directories. If you type =n= and space, it narrows the list to just the
|
||
notes, while =b= does the same for books.
|
||
|
||
Note that =consult-notes= is in its early stages of development. Expect
|
||
improvements in the near future (written on 2022-06-22 16:48 +0300).
|
||
|
||
** Treat your notes as a project
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:fad3eb08-ddc7-43e4-ba28-210d89668037
|
||
:END:
|
||
|
||
Emacs a built-in library for treating a directory tree as a "project".
|
||
This means that the contents of this tree are seen as part of the same
|
||
set, so commands like ~project-switch-to-buffer~ (=C-x p b= by default)
|
||
will only consider buffers in the current project (e.g. three notes that
|
||
are currently being visited).
|
||
|
||
Normally, a "project" is a directory tree whose root is under version
|
||
control. For our purposes, all you need is to navigate to the
|
||
~denote-directory~ (for the shell or via Dired) and use the command-line
|
||
to run this (requires the =git= executable):
|
||
|
||
: git init
|
||
|
||
From Dired, you can type =M-!= which invokes ~dired-smart-shell-command~
|
||
and then run the git call there.
|
||
|
||
The project can then be registered by invoking any project-related
|
||
command inside of it, such as ~project-find-file~ (=C-x p f=).
|
||
|
||
It is a good idea to keep your notes under version control, as that
|
||
gives you a history of changes for each file. We shall not delve into
|
||
the technicalities here, though suffice to note that Emacs' built-in
|
||
version control framework or the exceptionally well-crafted =magit=
|
||
package will get the job done (VC can work with other backends besides
|
||
Git).
|
||
|
||
* Installation
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:f3bdac2c-4704-4a51-948c-a789a2589790
|
||
:END:
|
||
#+cindex: Installation instructions
|
||
|
||
** GNU ELPA package
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:42953f87-82bd-43ec-ab99-22b1e22955e7
|
||
:END:
|
||
|
||
The package is available as =denote=. Simply do:
|
||
|
||
: M-x package-refresh-contents
|
||
: M-x package-install
|
||
|
||
And search for it.
|
||
|
||
GNU ELPA provides the latest stable release. Those who prefer to follow
|
||
the development process in order to report bugs or suggest changes, can
|
||
use the version of the package from the GNU-devel ELPA archive. Read:
|
||
https://protesilaos.com/codelog/2022-05-13-emacs-elpa-devel/.
|
||
|
||
** Manual installation
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:d397712c-c8c0-4cfa-ad1a-ef28cf78d1f0
|
||
:END:
|
||
|
||
Assuming your Emacs files are found in =~/.emacs.d/=, execute the
|
||
following commands in a shell prompt:
|
||
|
||
#+begin_src sh
|
||
cd ~/.emacs.d
|
||
|
||
# Create a directory for manually-installed packages
|
||
mkdir manual-packages
|
||
|
||
# Go to the new directory
|
||
cd manual-packages
|
||
|
||
# Clone this repo, naming it "denote"
|
||
git clone https://git.sr.ht/~protesilaos/denote denote
|
||
#+end_src
|
||
|
||
Finally, in your =init.el= (or equivalent) evaluate this:
|
||
|
||
#+begin_src emacs-lisp
|
||
;; Make Elisp files in that directory available to the user.
|
||
(add-to-list 'load-path "~/.emacs.d/manual-packages/denote")
|
||
#+end_src
|
||
|
||
Everything is in place to set up the package.
|
||
|
||
* Sample configuration
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:5d16932d-4f7b-493d-8e6a-e5c396b15fd6
|
||
:END:
|
||
#+cindex: Package configuration
|
||
|
||
#+begin_src emacs-lisp
|
||
(require 'denote)
|
||
|
||
;; Remember to check the doc strings of those variables.
|
||
(setq denote-directory (expand-file-name "~/Documents/notes/"))
|
||
(setq denote-known-keywords
|
||
'("emacs" "philosophy" "politics" "economics"))
|
||
(setq denote-infer-keywords t)
|
||
(setq denote-sort-keywords t)
|
||
(setq denote-file-type nil) ; Org is the default, set others here
|
||
|
||
;; We allow multi-word keywords by default. The author's personal
|
||
;; preference is for single-word keywords for a more rigid workflow.
|
||
(setq denote-allow-multi-word-keywords t)
|
||
|
||
(setq denote-front-matter-date-format nil) ; change this to `org-timestamp' or custom string
|
||
|
||
;; You will not need to `require' all those individually once the
|
||
;; package is available.
|
||
(require 'denote-retrieve)
|
||
(require 'denote-link)
|
||
|
||
;; If you want links to and from Org notes to use the standard 'id:'
|
||
;; link type instead of 'denote:'.
|
||
(setq denote-link-use-org-id t)
|
||
|
||
;; By default, we fontify backlinks in their bespoke buffer.
|
||
(setq denote-link-fontify-backlinks t)
|
||
|
||
;; Also see `denote-link-backlinks-display-buffer-action' which is a bit
|
||
;; advanced.
|
||
|
||
;; If you use Markdown or plain text files (Org renders links as buttons
|
||
;; right away)
|
||
(add-hook 'find-file-hook #'denote-link-buttonize-buffer)
|
||
|
||
(require 'denote-dired)
|
||
(setq denote-dired-rename-expert nil)
|
||
|
||
;; We use different ways to specify a path for demo purposes.
|
||
(setq denote-dired-directories
|
||
(list denote-directory
|
||
(thread-last denote-directory (expand-file-name "attachments"))
|
||
(expand-file-name "~/Documents/books")))
|
||
|
||
;; Generic (great if you rename files Denote-style in lots of places):
|
||
;; (add-hook 'dired-mode-hook #'denote-dired-mode)
|
||
;;
|
||
;; OR if only want it in `denote-dired-directories':
|
||
(add-hook 'dired-mode-hook #'denote-dired-mode-in-directories)
|
||
|
||
;; Here is a custom, user-level command from one of the examples we
|
||
;; showed in this manual. We define it here and add it to a key binding
|
||
;; below.
|
||
(defun my-denote-journal ()
|
||
"Create an entry tagged 'journal', while prompting for a title."
|
||
(interactive)
|
||
(denote
|
||
(denote--title-prompt)
|
||
"journal"))
|
||
|
||
;; Denote does not define any key bindings. This is for the user to
|
||
;; decide. For example:
|
||
(let ((map global-map))
|
||
(define-key map (kbd "C-c n j") #'my-denote-journal) ; our custom command
|
||
(define-key map (kbd "C-c n n") #'denote)
|
||
(define-key map (kbd "C-c n N") #'denote-type)
|
||
(define-key map (kbd "C-c n d") #'denote-date)
|
||
;; If you intend to use Denote with a variety of file types, it is
|
||
;; easier to bind the link-related commands to the `global-map', as
|
||
;; shown here. Otherwise follow the same pattern for `org-mode-map',
|
||
;; `markdown-mode-map', and/or `text-mode-map'.
|
||
(define-key map (kbd "C-c n i") #'denote-link) ; "insert" mnemonic
|
||
(define-key map (kbd "C-c n I") #'denote-link-add-links)
|
||
(define-key map (kbd "C-c n l") #'denote-link-find-file) ; "list" links
|
||
(define-key map (kbd "C-c n b") #'denote-link-backlinks)
|
||
;; Note that `denote-dired-rename-file' can work from any context, not
|
||
;; just Dired bufffers. That is why we bind it here to the
|
||
;; `global-map'.
|
||
(define-key map (kbd "C-c n r") #'denote-dired-rename-file))
|
||
|
||
(with-eval-after-load 'org-capture
|
||
(require 'denote-org-capture)
|
||
(setq denote-org-capture-specifiers "%l\n%i\n%?")
|
||
(add-to-list 'org-capture-templates
|
||
'("n" "New note (with denote.el)" plain
|
||
(file denote-last-path)
|
||
#'denote-org-capture
|
||
:no-save t
|
||
:immediate-finish nil
|
||
:kill-buffer t
|
||
:jump-to-captured t)))
|
||
#+end_src
|
||
|
||
* Contributing
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:1ebe4865-c001-4747-a6f2-0fe45aad71cd
|
||
:END:
|
||
|
||
Denote is a GNU ELPA package. As such, any significant change to the
|
||
code requires copyright assignment to the Free Software Foundation (more
|
||
below).
|
||
|
||
You do not need to be a programmer to contribute to this package.
|
||
Sharing an idea or describing a workflow is equally helpful, as it
|
||
teaches us something we may not know and might be able to cover either
|
||
by extending Denote or expanding this manual ([[#h:044a6a0f-e382-4013-8279-8bf4e64e73c0][Things to do]]). If you
|
||
prefer to write a blog post, make sure you share it with us: we can add
|
||
a section herein referencing all such articles. Everyone gets
|
||
acknowledged ([[#h:f8126820-3b59-49fa-bcc2-73bd60132bb9][Acknowledgements]]). There is no such thing as an
|
||
"insignificant contribution"---they all matter.
|
||
|
||
+ Package name (GNU ELPA): =denote=
|
||
+ Official manual: <https://protesilaos.com/emacs/denote>
|
||
+ Change log: <https://protesilaos.com/emacs/denote-changelog>
|
||
+ Git repo on SourceHut: <https://git.sr.ht/~protesilaos/denote>
|
||
- Mirrors:
|
||
+ GitHub: <https://github.com/protesilaos/denote>
|
||
+ GitLab: <https://gitlab.com/protesilaos/denote>
|
||
+ Mailing list: <https://lists.sr.ht/~protesilaos/denote>
|
||
|
||
If our public media are not suitable, you are welcome to contact me
|
||
(Protesilaos) in private: <https://protesilaos.com/contact>.
|
||
|
||
Copyright assignment is a prerequisite to sharing code. It is a simple
|
||
process. Check the request form below (please adapt it accordingly).
|
||
You must write an email to the address mentioned in the form and then
|
||
wait for the FSF to send you a legal agreement. Sign the document and
|
||
file it back to them. This could all happen via email and take about a
|
||
week. You are encouraged to go through this process. You only need to
|
||
do it once. It will allow you to make contributions to Emacs in
|
||
general.
|
||
|
||
#+begin_example text
|
||
Please email the following information to assign@gnu.org, and we
|
||
will send you the assignment form for your past and future changes.
|
||
|
||
Please use your full legal name (in ASCII characters) as the subject
|
||
line of the message.
|
||
|
||
REQUEST: SEND FORM FOR PAST AND FUTURE CHANGES
|
||
|
||
[What is the name of the program or package you're contributing to?]
|
||
|
||
GNU Emacs
|
||
|
||
[Did you copy any files or text written by someone else in these changes?
|
||
Even if that material is free software, we need to know about it.]
|
||
|
||
Copied a few snippets from the same files I edited. Their author,
|
||
Protesilaos Stavrou, has already assigned copyright to the Free Software
|
||
Foundation.
|
||
|
||
[Do you have an employer who might have a basis to claim to own
|
||
your changes? Do you attend a school which might make such a claim?]
|
||
|
||
|
||
[For the copyright registration, what country are you a citizen of?]
|
||
|
||
|
||
[What year were you born?]
|
||
|
||
|
||
[Please write your email address here.]
|
||
|
||
|
||
[Please write your postal address here.]
|
||
|
||
|
||
|
||
|
||
|
||
[Which files have you changed so far, and which new files have you written
|
||
so far?]
|
||
|
||
#+end_example
|
||
|
||
* Things to do
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:044a6a0f-e382-4013-8279-8bf4e64e73c0
|
||
:END:
|
||
|
||
Denote should work well for what is described in this manual. Though we
|
||
can always do better. These are some of the tasks that are planned for
|
||
the future and which you might want to help with ([[#h:1ebe4865-c001-4747-a6f2-0fe45aad71cd][Contributing]]).
|
||
|
||
This is a non-exhaustive list and you are always welcome to either
|
||
report or work on something else.
|
||
|
||
- [X] Buttonize =denote:= links in Markdown and plain text, but not Org.
|
||
- [X] Experiment with switch to =id:= link type instead of =denote:=.
|
||
- [ ] Ensure integration between =denote:= links and Embark.
|
||
- [ ] Add command that expands the identifier in links to a full name.
|
||
- [ ] Add command that rewrites full names in links, if they are invalid.
|
||
- [ ] Consider completion-at-point after =denote:= links.
|
||
- [ ] Support mutually-exclusive sets of tags.
|
||
|
||
These are just ideas. We need to consider the pros and cons in each
|
||
case and act accordingly.
|
||
|
||
* Alternatives to Denote
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:dbb51a1b-90b8-48e8-953c-e2fb3e36981e
|
||
:END:
|
||
|
||
What follows is a list of Emacs packages for note-taking. I
|
||
(Protesilaos) have not used any of them, as I was manually applying my
|
||
file-naming scheme beforehand and by the time those packages were
|
||
available I was already hacking on the predecessor of Denote as a means
|
||
of learning Emacs Lisp (a package which I called "Unassuming Sidenotes
|
||
of Little Significance", aka "USLS" which is pronounced as "U-S-L-S" or
|
||
"useless"). As such, I cannot comment at length on the differences
|
||
between Denote and each of those packages, beside what I gather from
|
||
their documentation.
|
||
|
||
+ [[https://github.com/org-roam/org-roam][org-roam]] :: The de facto standard in the Emacs milieu---and rightly
|
||
so! It has a massive community, is featureful, and should be an
|
||
excellent companion to anyone who is invested in the Org ecosystem
|
||
and/or knows what "Roam" is (I don't). It has been explained to me
|
||
that Org Roam uses a database to store a cache about your notes. It
|
||
otherwise uses standard Org files. The cache helps refer to the same
|
||
node through aliases which can provide lots of options. Personally, I
|
||
follow a single-topic-per-note approach, so anything beyond that is
|
||
overkill. If the database is only for a cache, then maybe that has no
|
||
downside, though I am careful with any kind of specialised program as
|
||
it creates a dependency. If you ask me about database software in
|
||
particular, I have no idea how to use one, let alone debug it or
|
||
retrieve data from it if something goes awry (I could learn, but that
|
||
is beside the point).
|
||
|
||
+ [[https://github.com/localauthor/zk][zk (or zk.el)]] :: Reading its documentation makes me think that this is
|
||
Denote's sibling---the two projects have a lot of things in common,
|
||
including the preference to rely on plain files and standard tools.
|
||
The core difference is that Denote has a strict file-naming scheme.
|
||
Other differences in available features are, in principle, matters of
|
||
style or circumstance: both packages can have them. As its initials
|
||
imply, ZK enables a zettelkasten-like workflow. It does not enforce
|
||
it though, letting the user adapt the method to their needs and
|
||
requirements.
|
||
|
||
+ [[https://github.com/ymherklotz/emacs-zettelkasten][zettelkasten]] :: This is another one of Denote's relatives, at least
|
||
insofar as the goal of simplicity is concerned. The major difference
|
||
is that according to its documentation "the name of the file that is
|
||
created is just a unique ID". This is not consistent with our
|
||
file-naming scheme which is all about making sense of your files by
|
||
their name alone and being able to visually parse a listing of them
|
||
without any kind of specialised tool (e.g. =ls -l= or =ls -C= on the
|
||
command-line from inside the ~denote-directory~ give you a
|
||
human-readable set of files names, while =find * -maxdepth 0 -type f=
|
||
is another approach).
|
||
|
||
+ [[https://github.com/EFLS/zetteldeft][zetteldeft]] :: This is a zettelkasten note-taking system built on top
|
||
of the =deft= package. Deft provides a search interface to a
|
||
directory, in this case the one holding the user's =zetteldeft= notes.
|
||
Denote has no such dependency and is not opinionated about how the
|
||
user prefers to search/access their notes: use Dired, Grep, the
|
||
=consult= package, or whatever else you already have set up for all
|
||
things Emacs, not just your notes.
|
||
|
||
Searching through =M-x list-packages= for "zettel" brings up more
|
||
matches. =zetteldesk= is an extension to Org Roam and, as such, I
|
||
cannot possibly know what Org Roam truly misses and what the added-value
|
||
of this package is. =neuron-mode= builds on top of an external program
|
||
called =neuron=, which I have never used.
|
||
|
||
Searching for "note" gives us a few more results. =notes-mode= has
|
||
precious little documentation and I cannot tell what it actually does
|
||
(as I said in my presentation for LibrePlanet 2022, inadequate docs are
|
||
a bug). =side-notes= differs from what we try to do with Denote, as it
|
||
basically gives you the means to record your thoughts about some other
|
||
project you are working on and keep them on the side: so it and Denote
|
||
should not be mutually exclusive.
|
||
|
||
If I missed something, please let me know.
|
||
|
||
** Alternative ideas wih Emacs and further reading
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:188c0986-f2fa-444f-b493-5429356e75cf
|
||
:END:
|
||
|
||
This section covers blog posts from the Emacs community on the matter of
|
||
note-taking. They may reference some of the packages covered in the
|
||
previous section or provide their custom code ([[#h:dbb51a1b-90b8-48e8-953c-e2fb3e36981e][Alternatives to Denote]]).
|
||
The list is unsorted.
|
||
|
||
+ José Antonio Ortega Ruiz (aka "jao") explains a note-taking method
|
||
that is simple like Denote but differs in other ways. An interesting
|
||
approach overall: https://jao.io/blog/2022-06-19-simple-note-taking.html.
|
||
|
||
+ Jethro Kuan (the main =org-roam= developer) explains their note-taking
|
||
techniques: https://jethrokuan.github.io/org-roam-guide/. Good ideas
|
||
all round, regardless of the package/code you choose to use.
|
||
|
||
[ Development note: help expand this list. ]
|
||
|
||
* Frequently Asked Questions
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:da2944c6-cde6-4c65-8f2d-579305a159bb
|
||
:END:
|
||
|
||
I (Protesilaos) answer some questions I have received or might get. It
|
||
is assumed that you have read the rest of this manual: I will not go
|
||
into the specifics of how Denote works.
|
||
|
||
** Why develop Denote when PACKAGE already exists?
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:b875450a-ae22-4899-ac23-c10fa9c279bb
|
||
:END:
|
||
|
||
I wrote Denote because I was using a variant of Denote's file-naming
|
||
scheme before I was even an Emacs user (I switched to Emacs from
|
||
Tmux+Vim+CLI in the summer of 2019). I was originally inspired by
|
||
Jekyll, the static site generator, which I started using for my website
|
||
in 2016 (was on WordPress before). Jekyll's files follow the
|
||
=YYYY-MM-DD-TITLE.md= pattern. I liked its efficiency relative to the
|
||
unstructured mess I had before. Eventually, I started using that scheme
|
||
outside the confines of my website's source code. Over time I refined
|
||
it and here we are.
|
||
|
||
Note-taking is something I take very seriously, as I am a prolific
|
||
writer (just check my website, which only reveals the tip of the
|
||
iceberg). As such, I need a program that does exactly what I want and
|
||
which I know how to extend. I originally tried to use Org capture
|
||
templates to create new files with a Denote-style file-naming scheme but
|
||
never managed to achieve it. Maybe because ~org-capture~ has some
|
||
hard-coded assumptions or I simply am not competent enough to hack on
|
||
core Org facilities. Whatever the case, an alternative was in order.
|
||
|
||
The existence of PACKAGE is never a good reason for me not to conduct my
|
||
own experiments for recreational, educational, or practical purposes.
|
||
When the question arises of "why not contribute to PACKAGE instead?" the
|
||
answer is that without me experimenting in the first place, I would lack
|
||
the skills for such a task. Furthermore, contributing to another
|
||
package does not guarantee I get what I want in terms of workflow.
|
||
|
||
Whether you should use Denote or not is another matter altogether:
|
||
choose whatever you want.
|
||
|
||
** Why not rely exclusively on Org?
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:b9831849-5c71-484e-b444-bac19cc13151
|
||
:END:
|
||
|
||
I think Org is one of Emacs' killer apps. I also believe it is not the
|
||
right tool for every job. When I write notes, I want to focus on
|
||
writing. Nothing more. I thus have no need for stuff like org-babel,
|
||
scheduling to-do items, clocking time, and so on. The more "mental
|
||
dependencies" you add to your workflow, the heavier the burden you carry
|
||
and the less focused you are on the task at hand: there is always that
|
||
temptation to tweak the markup, tinker with some syntactic construct,
|
||
obsess about what ought to be irrelevant to writing as such.
|
||
|
||
In technical terms, I also am not fond of Org's code base (I understand
|
||
why it is the way it is---just commenting on the fact). Ever tried to
|
||
read it? You will routinely find functions that are tens-to-hundreds of
|
||
lines long and have all sorts of special casing. As I am not a
|
||
programmer and only learnt to write Elisp through trial and error, I
|
||
have no confidence in my ability to make Org do what I want at that
|
||
level, hence =denote= instead of =org-denote= or something.
|
||
|
||
Perhaps the master programmer is one who can deal with complexity and
|
||
keep adding to it. I am of the opposite view, as language---code
|
||
included---is at its communicative best when it is clear and accessible.
|
||
|
||
Make no mistake: I use Org for the agenda and also to write technical
|
||
documentation that needs to be exported to various formats, including
|
||
this very manual.
|
||
|
||
** Why care about Unix tools when you use Emacs?
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:da1e2469-8f04-450b-a379-a854efa80a36
|
||
:END:
|
||
|
||
My notes form part of my longer-term storage. I do not want to have to
|
||
rely on a special program to be able to read them or filter them. Unix
|
||
is universal, at least as far as I am concerned.
|
||
|
||
Denote streamlines some tasks and makes things easier in general, which
|
||
is consistent with how Emacs provides a layer of interactivity on top of
|
||
Unix. Still, Denote's utilities can, in principle, be implemented as
|
||
POSIX shell scripts (minus the Emacs-specific parts like fontification
|
||
in Dired or the buttonization of links).
|
||
|
||
Portability matters. For example, in the future I might own a
|
||
smartphone, so I prefer not to require Emacs, Org, or some other
|
||
executable to access my files on the go.
|
||
|
||
Furthermore, I might want to share those files with someone. If I make
|
||
Emacs a requirement, I am limiting my circle to a handful of relatively
|
||
advanced users.
|
||
|
||
Please don't misinterpret this: I am using Emacs full-time for my
|
||
computing and maintain a growing list of packages for it. This is just
|
||
me thinking long-term.
|
||
|
||
** Why many small files instead of few large ones?
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:7d2e7b8a-d484-4c1d-8688-17f70f242ad7
|
||
:END:
|
||
|
||
I have read that Org favours the latter method. If true, I strongly
|
||
disagree with it because of the implicit dependency it introduces and
|
||
the way it favours machine-friendliness over human-readability in terms
|
||
of accessing information. Notes are long-term storage. I might want to
|
||
access them on (i) some device with limited features, (ii) print on
|
||
paper, (iii) share with another person who is not a tech wizard.
|
||
|
||
There are good arguments for few large files, but all either prioritize
|
||
machine-friendliness or presuppose the use of sophisticated tools like
|
||
Emacs+Org.
|
||
|
||
Good luck using =less= on a generic TTY to read a file with a zillion
|
||
words, headings, sub-headings, sub-sub-headings, property drawers, and
|
||
other constructs! You will not get the otherwise wonderful folding of
|
||
headings the way you do in Emacs---do not take such features for
|
||
granted.
|
||
|
||
My point is that notes should be atomic to help the user---and
|
||
potentially the user's family, friends, acquaintances---make sense of
|
||
them in a wide range of scenaria. The more program-agnostic your file
|
||
is, the better for you and/or everyone else you might share your
|
||
writings with.
|
||
|
||
Human-readability means that we optimize for what matters to us. If (a)
|
||
you are the only one who will ever read your notes, (b) always have
|
||
access to good software like Emacs+Org, (c) do not care about printing
|
||
on paper, then Denote's model is not for you. Maybe you need to tweak
|
||
some ~org-capture~ template to append a new entry to one mega file (I do
|
||
that for my Org agenda, by the way, as I explained before about using
|
||
the right tool for the job).
|
||
|
||
** I add TODOs to my files; will the many files slow down the Org agenda?
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:63c2f8d4-79ed-4c55-b3ef-e048a05802c0
|
||
:END:
|
||
|
||
I have not tested it, but assume that yes, many files will slow down the
|
||
agenda. Consider looking into one of Denote's alternatives, with
|
||
=org-roam= being the obvious choice ([[#h:dbb51a1b-90b8-48e8-953c-e2fb3e36981e][Alternatives to Denote]]).
|
||
|
||
Or, if you want my opinion, decouple your longer-term storage from your
|
||
ephemeral to-do list: Denote (and others) can be used for the former,
|
||
while you let standard Org work splendidly for the latter---that is what
|
||
I do, anyway.
|
||
|
||
** I want to sort by last modified, why won't Denote let me?
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:a7fd5e0a-78f7-434e-aa2e-e150479c16e2
|
||
:END:
|
||
|
||
Denote does not sort files and will not reinvent tools that handle such
|
||
functionality. This is the job of the file manager or command-line
|
||
executable that lists files.
|
||
|
||
I encourage you to read the manpage of the =ls= executable. It will
|
||
help you in general, while it applies to Emacs as well via Dired. The
|
||
gist is that you can update the =ls= flags that Dired uses on-the-fly:
|
||
type =C-u M-x dired-sort-toggle-or-edit= (=C-u s= by default) and append
|
||
=--sort=time= at the prompt. To reverse the order, add the =-r= flag.
|
||
The user option ~dired-listing-switches~ sets your default preference.
|
||
|
||
** How do you handle the last modified case?
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:764b5e87-cd22-4937-b5fc-af3892d6b3d8
|
||
:END:
|
||
|
||
Denote does not insert any meta data or heading pertaining to edits in
|
||
the file. I am of the view that these either do not scale well or are
|
||
not descriptive enough. Suppose you use a "lastmod" heading with a
|
||
timestamp: which lines where edited and what did the change amount to?
|
||
|
||
This is where an external program can be helpful. Use a Version Control
|
||
System, such as Git, to keep track of all your notes. Every time you
|
||
add a new file, record the addition. Same for post-creation edits.
|
||
Your VCS will let you review the history of those changes. For
|
||
instance, Emacs' built-in version control framework has a command that
|
||
produces a log of changes for the current file: =M-x vc-print-log=,
|
||
bound to =C-x v l= by default. From there one can access the
|
||
corresponding diff output (use =M-x describe-mode= (=C-h m=) in an
|
||
unfamiliar buffer to learn more about it). With Git in particular,
|
||
Emacs users have the option of the all-round excellent =magit= package.
|
||
|
||
In short: let Denote (or equivalent) create notes and link between them,
|
||
the file manager organise and provide access to files, search programs
|
||
deal with searching and narrowing, and version control software handle
|
||
the tracking of changes.
|
||
|
||
* Acknowledgements
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:f8126820-3b59-49fa-bcc2-73bd60132bb9
|
||
:END:
|
||
#+cindex: Contributors
|
||
|
||
Denote is meant to be a collective effort. Every bit of help matters.
|
||
|
||
+ Author/maintainer :: Protesilaos Stavrou.
|
||
|
||
+ Contributions to code or the manual :: Damien Cassou, Jack Baty,
|
||
Kaushal Modi.
|
||
|
||
+ Ideas and/or user feedback :: Colin McLear, Damien Cassou, Frank
|
||
Ehmsen, Jack Baty, Kaushal Modi, Sven Seebeck, Ypot.
|
||
|
||
Special thanks to Peter Povinec who helped refine the file-naming
|
||
scheme, which is the cornerstone of this project.
|
||
|
||
* GNU Free Documentation License
|
||
:PROPERTIES:
|
||
:APPENDIX: t
|
||
:CUSTOM_ID: h:2d84e73e-c143-43b5-b388-a6765da974ea
|
||
:END:
|
||
|
||
#+texinfo: @include doclicense.texi
|
||
|
||
#+begin_export html
|
||
<pre>
|
||
|
||
GNU Free Documentation License
|
||
Version 1.3, 3 November 2008
|
||
|
||
|
||
Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc.
|
||
<https://fsf.org/>
|
||
Everyone is permitted to copy and distribute verbatim copies
|
||
of this license document, but changing it is not allowed.
|
||
|
||
0. PREAMBLE
|
||
|
||
The purpose of this License is to make a manual, textbook, or other
|
||
functional and useful document "free" in the sense of freedom: to
|
||
assure everyone the effective freedom to copy and redistribute it,
|
||
with or without modifying it, either commercially or noncommercially.
|
||
Secondarily, this License preserves for the author and publisher a way
|
||
to get credit for their work, while not being considered responsible
|
||
for modifications made by others.
|
||
|
||
This License is a kind of "copyleft", which means that derivative
|
||
works of the document must themselves be free in the same sense. It
|
||
complements the GNU General Public License, which is a copyleft
|
||
license designed for free software.
|
||
|
||
We have designed this License in order to use it for manuals for free
|
||
software, because free software needs free documentation: a free
|
||
program should come with manuals providing the same freedoms that the
|
||
software does. But this License is not limited to software manuals;
|
||
it can be used for any textual work, regardless of subject matter or
|
||
whether it is published as a printed book. We recommend this License
|
||
principally for works whose purpose is instruction or reference.
|
||
|
||
|
||
1. APPLICABILITY AND DEFINITIONS
|
||
|
||
This License applies to any manual or other work, in any medium, that
|
||
contains a notice placed by the copyright holder saying it can be
|
||
distributed under the terms of this License. Such a notice grants a
|
||
world-wide, royalty-free license, unlimited in duration, to use that
|
||
work under the conditions stated herein. The "Document", below,
|
||
refers to any such manual or work. Any member of the public is a
|
||
licensee, and is addressed as "you". You accept the license if you
|
||
copy, modify or distribute the work in a way requiring permission
|
||
under copyright law.
|
||
|
||
A "Modified Version" of the Document means any work containing the
|
||
Document or a portion of it, either copied verbatim, or with
|
||
modifications and/or translated into another language.
|
||
|
||
A "Secondary Section" is a named appendix or a front-matter section of
|
||
the Document that deals exclusively with the relationship of the
|
||
publishers or authors of the Document to the Document's overall
|
||
subject (or to related matters) and contains nothing that could fall
|
||
directly within that overall subject. (Thus, if the Document is in
|
||
part a textbook of mathematics, a Secondary Section may not explain
|
||
any mathematics.) The relationship could be a matter of historical
|
||
connection with the subject or with related matters, or of legal,
|
||
commercial, philosophical, ethical or political position regarding
|
||
them.
|
||
|
||
The "Invariant Sections" are certain Secondary Sections whose titles
|
||
are designated, as being those of Invariant Sections, in the notice
|
||
that says that the Document is released under this License. If a
|
||
section does not fit the above definition of Secondary then it is not
|
||
allowed to be designated as Invariant. The Document may contain zero
|
||
Invariant Sections. If the Document does not identify any Invariant
|
||
Sections then there are none.
|
||
|
||
The "Cover Texts" are certain short passages of text that are listed,
|
||
as Front-Cover Texts or Back-Cover Texts, in the notice that says that
|
||
the Document is released under this License. A Front-Cover Text may
|
||
be at most 5 words, and a Back-Cover Text may be at most 25 words.
|
||
|
||
A "Transparent" copy of the Document means a machine-readable copy,
|
||
represented in a format whose specification is available to the
|
||
general public, that is suitable for revising the document
|
||
straightforwardly with generic text editors or (for images composed of
|
||
pixels) generic paint programs or (for drawings) some widely available
|
||
drawing editor, and that is suitable for input to text formatters or
|
||
for automatic translation to a variety of formats suitable for input
|
||
to text formatters. A copy made in an otherwise Transparent file
|
||
format whose markup, or absence of markup, has been arranged to thwart
|
||
or discourage subsequent modification by readers is not Transparent.
|
||
An image format is not Transparent if used for any substantial amount
|
||
of text. A copy that is not "Transparent" is called "Opaque".
|
||
|
||
Examples of suitable formats for Transparent copies include plain
|
||
ASCII without markup, Texinfo input format, LaTeX input format, SGML
|
||
or XML using a publicly available DTD, and standard-conforming simple
|
||
HTML, PostScript or PDF designed for human modification. Examples of
|
||
transparent image formats include PNG, XCF and JPG. Opaque formats
|
||
include proprietary formats that can be read and edited only by
|
||
proprietary word processors, SGML or XML for which the DTD and/or
|
||
processing tools are not generally available, and the
|
||
machine-generated HTML, PostScript or PDF produced by some word
|
||
processors for output purposes only.
|
||
|
||
The "Title Page" means, for a printed book, the title page itself,
|
||
plus such following pages as are needed to hold, legibly, the material
|
||
this License requires to appear in the title page. For works in
|
||
formats which do not have any title page as such, "Title Page" means
|
||
the text near the most prominent appearance of the work's title,
|
||
preceding the beginning of the body of the text.
|
||
|
||
The "publisher" means any person or entity that distributes copies of
|
||
the Document to the public.
|
||
|
||
A section "Entitled XYZ" means a named subunit of the Document whose
|
||
title either is precisely XYZ or contains XYZ in parentheses following
|
||
text that translates XYZ in another language. (Here XYZ stands for a
|
||
specific section name mentioned below, such as "Acknowledgements",
|
||
"Dedications", "Endorsements", or "History".) To "Preserve the Title"
|
||
of such a section when you modify the Document means that it remains a
|
||
section "Entitled XYZ" according to this definition.
|
||
|
||
The Document may include Warranty Disclaimers next to the notice which
|
||
states that this License applies to the Document. These Warranty
|
||
Disclaimers are considered to be included by reference in this
|
||
License, but only as regards disclaiming warranties: any other
|
||
implication that these Warranty Disclaimers may have is void and has
|
||
no effect on the meaning of this License.
|
||
|
||
2. VERBATIM COPYING
|
||
|
||
You may copy and distribute the Document in any medium, either
|
||
commercially or noncommercially, provided that this License, the
|
||
copyright notices, and the license notice saying this License applies
|
||
to the Document are reproduced in all copies, and that you add no
|
||
other conditions whatsoever to those of this License. You may not use
|
||
technical measures to obstruct or control the reading or further
|
||
copying of the copies you make or distribute. However, you may accept
|
||
compensation in exchange for copies. If you distribute a large enough
|
||
number of copies you must also follow the conditions in section 3.
|
||
|
||
You may also lend copies, under the same conditions stated above, and
|
||
you may publicly display copies.
|
||
|
||
|
||
3. COPYING IN QUANTITY
|
||
|
||
If you publish printed copies (or copies in media that commonly have
|
||
printed covers) of the Document, numbering more than 100, and the
|
||
Document's license notice requires Cover Texts, you must enclose the
|
||
copies in covers that carry, clearly and legibly, all these Cover
|
||
Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
|
||
the back cover. Both covers must also clearly and legibly identify
|
||
you as the publisher of these copies. The front cover must present
|
||
the full title with all words of the title equally prominent and
|
||
visible. You may add other material on the covers in addition.
|
||
Copying with changes limited to the covers, as long as they preserve
|
||
the title of the Document and satisfy these conditions, can be treated
|
||
as verbatim copying in other respects.
|
||
|
||
If the required texts for either cover are too voluminous to fit
|
||
legibly, you should put the first ones listed (as many as fit
|
||
reasonably) on the actual cover, and continue the rest onto adjacent
|
||
pages.
|
||
|
||
If you publish or distribute Opaque copies of the Document numbering
|
||
more than 100, you must either include a machine-readable Transparent
|
||
copy along with each Opaque copy, or state in or with each Opaque copy
|
||
a computer-network location from which the general network-using
|
||
public has access to download using public-standard network protocols
|
||
a complete Transparent copy of the Document, free of added material.
|
||
If you use the latter option, you must take reasonably prudent steps,
|
||
when you begin distribution of Opaque copies in quantity, to ensure
|
||
that this Transparent copy will remain thus accessible at the stated
|
||
location until at least one year after the last time you distribute an
|
||
Opaque copy (directly or through your agents or retailers) of that
|
||
edition to the public.
|
||
|
||
It is requested, but not required, that you contact the authors of the
|
||
Document well before redistributing any large number of copies, to
|
||
give them a chance to provide you with an updated version of the
|
||
Document.
|
||
|
||
|
||
4. MODIFICATIONS
|
||
|
||
You may copy and distribute a Modified Version of the Document under
|
||
the conditions of sections 2 and 3 above, provided that you release
|
||
the Modified Version under precisely this License, with the Modified
|
||
Version filling the role of the Document, thus licensing distribution
|
||
and modification of the Modified Version to whoever possesses a copy
|
||
of it. In addition, you must do these things in the Modified Version:
|
||
|
||
A. Use in the Title Page (and on the covers, if any) a title distinct
|
||
from that of the Document, and from those of previous versions
|
||
(which should, if there were any, be listed in the History section
|
||
of the Document). You may use the same title as a previous version
|
||
if the original publisher of that version gives permission.
|
||
B. List on the Title Page, as authors, one or more persons or entities
|
||
responsible for authorship of the modifications in the Modified
|
||
Version, together with at least five of the principal authors of the
|
||
Document (all of its principal authors, if it has fewer than five),
|
||
unless they release you from this requirement.
|
||
C. State on the Title page the name of the publisher of the
|
||
Modified Version, as the publisher.
|
||
D. Preserve all the copyright notices of the Document.
|
||
E. Add an appropriate copyright notice for your modifications
|
||
adjacent to the other copyright notices.
|
||
F. Include, immediately after the copyright notices, a license notice
|
||
giving the public permission to use the Modified Version under the
|
||
terms of this License, in the form shown in the Addendum below.
|
||
G. Preserve in that license notice the full lists of Invariant Sections
|
||
and required Cover Texts given in the Document's license notice.
|
||
H. Include an unaltered copy of this License.
|
||
I. Preserve the section Entitled "History", Preserve its Title, and add
|
||
to it an item stating at least the title, year, new authors, and
|
||
publisher of the Modified Version as given on the Title Page. If
|
||
there is no section Entitled "History" in the Document, create one
|
||
stating the title, year, authors, and publisher of the Document as
|
||
given on its Title Page, then add an item describing the Modified
|
||
Version as stated in the previous sentence.
|
||
J. Preserve the network location, if any, given in the Document for
|
||
public access to a Transparent copy of the Document, and likewise
|
||
the network locations given in the Document for previous versions
|
||
it was based on. These may be placed in the "History" section.
|
||
You may omit a network location for a work that was published at
|
||
least four years before the Document itself, or if the original
|
||
publisher of the version it refers to gives permission.
|
||
K. For any section Entitled "Acknowledgements" or "Dedications",
|
||
Preserve the Title of the section, and preserve in the section all
|
||
the substance and tone of each of the contributor acknowledgements
|
||
and/or dedications given therein.
|
||
L. Preserve all the Invariant Sections of the Document,
|
||
unaltered in their text and in their titles. Section numbers
|
||
or the equivalent are not considered part of the section titles.
|
||
M. Delete any section Entitled "Endorsements". Such a section
|
||
may not be included in the Modified Version.
|
||
N. Do not retitle any existing section to be Entitled "Endorsements"
|
||
or to conflict in title with any Invariant Section.
|
||
O. Preserve any Warranty Disclaimers.
|
||
|
||
If the Modified Version includes new front-matter sections or
|
||
appendices that qualify as Secondary Sections and contain no material
|
||
copied from the Document, you may at your option designate some or all
|
||
of these sections as invariant. To do this, add their titles to the
|
||
list of Invariant Sections in the Modified Version's license notice.
|
||
These titles must be distinct from any other section titles.
|
||
|
||
You may add a section Entitled "Endorsements", provided it contains
|
||
nothing but endorsements of your Modified Version by various
|
||
parties--for example, statements of peer review or that the text has
|
||
been approved by an organization as the authoritative definition of a
|
||
standard.
|
||
|
||
You may add a passage of up to five words as a Front-Cover Text, and a
|
||
passage of up to 25 words as a Back-Cover Text, to the end of the list
|
||
of Cover Texts in the Modified Version. Only one passage of
|
||
Front-Cover Text and one of Back-Cover Text may be added by (or
|
||
through arrangements made by) any one entity. If the Document already
|
||
includes a cover text for the same cover, previously added by you or
|
||
by arrangement made by the same entity you are acting on behalf of,
|
||
you may not add another; but you may replace the old one, on explicit
|
||
permission from the previous publisher that added the old one.
|
||
|
||
The author(s) and publisher(s) of the Document do not by this License
|
||
give permission to use their names for publicity for or to assert or
|
||
imply endorsement of any Modified Version.
|
||
|
||
|
||
5. COMBINING DOCUMENTS
|
||
|
||
You may combine the Document with other documents released under this
|
||
License, under the terms defined in section 4 above for modified
|
||
versions, provided that you include in the combination all of the
|
||
Invariant Sections of all of the original documents, unmodified, and
|
||
list them all as Invariant Sections of your combined work in its
|
||
license notice, and that you preserve all their Warranty Disclaimers.
|
||
|
||
The combined work need only contain one copy of this License, and
|
||
multiple identical Invariant Sections may be replaced with a single
|
||
copy. If there are multiple Invariant Sections with the same name but
|
||
different contents, make the title of each such section unique by
|
||
adding at the end of it, in parentheses, the name of the original
|
||
author or publisher of that section if known, or else a unique number.
|
||
Make the same adjustment to the section titles in the list of
|
||
Invariant Sections in the license notice of the combined work.
|
||
|
||
In the combination, you must combine any sections Entitled "History"
|
||
in the various original documents, forming one section Entitled
|
||
"History"; likewise combine any sections Entitled "Acknowledgements",
|
||
and any sections Entitled "Dedications". You must delete all sections
|
||
Entitled "Endorsements".
|
||
|
||
|
||
6. COLLECTIONS OF DOCUMENTS
|
||
|
||
You may make a collection consisting of the Document and other
|
||
documents released under this License, and replace the individual
|
||
copies of this License in the various documents with a single copy
|
||
that is included in the collection, provided that you follow the rules
|
||
of this License for verbatim copying of each of the documents in all
|
||
other respects.
|
||
|
||
You may extract a single document from such a collection, and
|
||
distribute it individually under this License, provided you insert a
|
||
copy of this License into the extracted document, and follow this
|
||
License in all other respects regarding verbatim copying of that
|
||
document.
|
||
|
||
|
||
7. AGGREGATION WITH INDEPENDENT WORKS
|
||
|
||
A compilation of the Document or its derivatives with other separate
|
||
and independent documents or works, in or on a volume of a storage or
|
||
distribution medium, is called an "aggregate" if the copyright
|
||
resulting from the compilation is not used to limit the legal rights
|
||
of the compilation's users beyond what the individual works permit.
|
||
When the Document is included in an aggregate, this License does not
|
||
apply to the other works in the aggregate which are not themselves
|
||
derivative works of the Document.
|
||
|
||
If the Cover Text requirement of section 3 is applicable to these
|
||
copies of the Document, then if the Document is less than one half of
|
||
the entire aggregate, the Document's Cover Texts may be placed on
|
||
covers that bracket the Document within the aggregate, or the
|
||
electronic equivalent of covers if the Document is in electronic form.
|
||
Otherwise they must appear on printed covers that bracket the whole
|
||
aggregate.
|
||
|
||
|
||
8. TRANSLATION
|
||
|
||
Translation is considered a kind of modification, so you may
|
||
distribute translations of the Document under the terms of section 4.
|
||
Replacing Invariant Sections with translations requires special
|
||
permission from their copyright holders, but you may include
|
||
translations of some or all Invariant Sections in addition to the
|
||
original versions of these Invariant Sections. You may include a
|
||
translation of this License, and all the license notices in the
|
||
Document, and any Warranty Disclaimers, provided that you also include
|
||
the original English version of this License and the original versions
|
||
of those notices and disclaimers. In case of a disagreement between
|
||
the translation and the original version of this License or a notice
|
||
or disclaimer, the original version will prevail.
|
||
|
||
If a section in the Document is Entitled "Acknowledgements",
|
||
"Dedications", or "History", the requirement (section 4) to Preserve
|
||
its Title (section 1) will typically require changing the actual
|
||
title.
|
||
|
||
|
||
9. TERMINATION
|
||
|
||
You may not copy, modify, sublicense, or distribute the Document
|
||
except as expressly provided under this License. Any attempt
|
||
otherwise to copy, modify, sublicense, or distribute it is void, and
|
||
will automatically terminate your rights under this License.
|
||
|
||
However, if you cease all violation of this License, then your license
|
||
from a particular copyright holder is reinstated (a) provisionally,
|
||
unless and until the copyright holder explicitly and finally
|
||
terminates your license, and (b) permanently, if the copyright holder
|
||
fails to notify you of the violation by some reasonable means prior to
|
||
60 days after the cessation.
|
||
|
||
Moreover, your license from a particular copyright holder is
|
||
reinstated permanently if the copyright holder notifies you of the
|
||
violation by some reasonable means, this is the first time you have
|
||
received notice of violation of this License (for any work) from that
|
||
copyright holder, and you cure the violation prior to 30 days after
|
||
your receipt of the notice.
|
||
|
||
Termination of your rights under this section does not terminate the
|
||
licenses of parties who have received copies or rights from you under
|
||
this License. If your rights have been terminated and not permanently
|
||
reinstated, receipt of a copy of some or all of the same material does
|
||
not give you any rights to use it.
|
||
|
||
|
||
10. FUTURE REVISIONS OF THIS LICENSE
|
||
|
||
The Free Software Foundation may publish new, revised versions of the
|
||
GNU Free Documentation License from time to time. Such new versions
|
||
will be similar in spirit to the present version, but may differ in
|
||
detail to address new problems or concerns. See
|
||
https://www.gnu.org/licenses/.
|
||
|
||
Each version of the License is given a distinguishing version number.
|
||
If the Document specifies that a particular numbered version of this
|
||
License "or any later version" applies to it, you have the option of
|
||
following the terms and conditions either of that specified version or
|
||
of any later version that has been published (not as a draft) by the
|
||
Free Software Foundation. If the Document does not specify a version
|
||
number of this License, you may choose any version ever published (not
|
||
as a draft) by the Free Software Foundation. If the Document
|
||
specifies that a proxy can decide which future versions of this
|
||
License can be used, that proxy's public statement of acceptance of a
|
||
version permanently authorizes you to choose that version for the
|
||
Document.
|
||
|
||
11. RELICENSING
|
||
|
||
"Massive Multiauthor Collaboration Site" (or "MMC Site") means any
|
||
World Wide Web server that publishes copyrightable works and also
|
||
provides prominent facilities for anybody to edit those works. A
|
||
public wiki that anybody can edit is an example of such a server. A
|
||
"Massive Multiauthor Collaboration" (or "MMC") contained in the site
|
||
means any set of copyrightable works thus published on the MMC site.
|
||
|
||
"CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0
|
||
license published by Creative Commons Corporation, a not-for-profit
|
||
corporation with a principal place of business in San Francisco,
|
||
California, as well as future copyleft versions of that license
|
||
published by that same organization.
|
||
|
||
"Incorporate" means to publish or republish a Document, in whole or in
|
||
part, as part of another Document.
|
||
|
||
An MMC is "eligible for relicensing" if it is licensed under this
|
||
License, and if all works that were first published under this License
|
||
somewhere other than this MMC, and subsequently incorporated in whole or
|
||
in part into the MMC, (1) had no cover texts or invariant sections, and
|
||
(2) were thus incorporated prior to November 1, 2008.
|
||
|
||
The operator of an MMC Site may republish an MMC contained in the site
|
||
under CC-BY-SA on the same site at any time before August 1, 2009,
|
||
provided the MMC is eligible for relicensing.
|
||
|
||
|
||
ADDENDUM: How to use this License for your documents
|
||
|
||
To use this License in a document you have written, include a copy of
|
||
the License in the document and put the following copyright and
|
||
license notices just after the title page:
|
||
|
||
Copyright (c) YEAR YOUR NAME.
|
||
Permission is granted to copy, distribute and/or modify this document
|
||
under the terms of the GNU Free Documentation License, Version 1.3
|
||
or any later version published by the Free Software Foundation;
|
||
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
|
||
A copy of the license is included in the section entitled "GNU
|
||
Free Documentation License".
|
||
|
||
If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
|
||
replace the "with...Texts." line with this:
|
||
|
||
with the Invariant Sections being LIST THEIR TITLES, with the
|
||
Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.
|
||
|
||
If you have Invariant Sections without Cover Texts, or some other
|
||
combination of the three, merge those two alternatives to suit the
|
||
situation.
|
||
|
||
If your document contains nontrivial examples of program code, we
|
||
recommend releasing these examples in parallel under your choice of
|
||
free software license, such as the GNU General Public License,
|
||
to permit their use in free software.
|
||
</pre>
|
||
#+end_export
|
||
|
||
#+html: <!--
|
||
|
||
* Indices
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: h:dd530040-de9d-4f2b-8dfd-d8b8f14c058e
|
||
:END:
|
||
|
||
** Function index
|
||
:PROPERTIES:
|
||
:INDEX: fn
|
||
:CUSTOM_ID: h:317b8c20-6dc1-4390-a20a-d01d75a48ccb
|
||
:END:
|
||
|
||
** Variable index
|
||
:PROPERTIES:
|
||
:INDEX: vr
|
||
:CUSTOM_ID: h:2f69d4fe-0804-4f7f-aa57-4e03e7f20d98
|
||
:END:
|
||
|
||
** Concept index
|
||
:PROPERTIES:
|
||
:INDEX: cp
|
||
:CUSTOM_ID: h:10365e44-2fc0-4b66-a613-682fea09ee68
|
||
:END:
|
||
|
||
#+html: -->
|