This is a package for easily selecting notes via consult. It’s most basic use is
to integrate directories of files (notes) and to provide easy narrowing via
consult
. But notes can be in principle added from any source that can be
integrated with consult.
consult-notes
can be used with any directory (or directories) of note files. It
easily integrates with note systems like zk, denote, or org-roam.
Additionally, it may also search org headings in a set of specified files.
Consult-notes also provides annotations on note candidates in the minibuffer
(defaults are: directory, file size, last-modified time; denote integration
substitutes keyword for directory; org-roam integration includes tags and number
of backlinks, and org-heading integration provides the file name). Consult-notes
may be configured to act on selected candidates via embark (see below). For
other customizations please consult the options via M-x customize-group
consult-notes
.
Installation
This package is available on MELPA. Or you can install the package from this repo. Installation with use-package and straight is pretty easy:
(use-package consult-notes
:straight (:type git :host github :repo "mclear-tools/consult-notes")
:commands (consult-notes
consult-notes-search-in-all-notes
;; if using org-roam
consult-notes-org-roam-find-node
consult-notes-org-roam-find-node-relation)
:config
(setq consult-notes-file-dir-sources '(("Name" ?key "path/to/dir"))) ;; Set notes dir(s), see below
;; Set org-roam integration, denote integration, or org-heading integration e.g.:
(setq consult-notes-org-headings-files '("~/path/to/file1.org"
"~/path/to/file2.org"))
(consult-notes-org-headings-mode)
(when (locate-library "denote")
(consult-notes-denote-mode))
;; search only for text files in denote dir
(setq consult-notes-denote-files-function (function denote-directory-text-only-files)))
Usage
Set notes directories via consult-notes-file-dir-sources
. This is a list that
consists of three elements: a title heading, a key (for narrowing), and a
directory path. For example (note the trailing slashes):
(setq consult-notes-file-dir-sources
'(("Org" ?o "~/Dropbox/org-files/")
("Org Refile" ?r "~/Dropbox/Work/projects/notebook/org-refile/")))
consult-multi
will take each of these sources and present them together in one
integrated consult completion buffer. To narrow to a particular source, use its
designated narrowing key.
NOTE: If you don’t use any sources beyond that of files in directories, then you don’t need to set anything other than consult-notes-file-dir-sources
. Org-roam or denote sources are set by using the relevant minor-mode (see below). However, if you do want to integrate other different kinds of sources (e.g. bookmarks or buffers) into consult-notes
then please see the instructions for adding multiple sources with consult. To add an additional non-directory source one should do so by means of add-to-list
in one’s config, e.g.
(with-eval-after-load 'consult-notes
(add-to-list 'consult-notes-all-sources 'my-notes--additional-source 'append))
You may customize narrowing keys, separator names and annotations used. Please
see customize-group RET 'consult-notes' RET
(or the relevant `.el’ files) for
details. The faces used by consult-notes are all similarly customizable.
Though consult-notes by default searches only for names of files (though see the
minor modes for denote and org-roam integration), you may also easily search the
(line) contents of all notes in consult-notes-all-sources
using the function
consult-notes-search-in-all-notes
. This uses consult-grep
or consult-ripgrep
as
its basis (see the consult-notes-use-rg
variable). You can set the arguments for
the grep or ripgrep search with the variables consult-notes-grep-args
and
consult-notes-ripgrep-args
respectively.
Denote
Denote may be used in conjunction with consult-notes in one of two ways. You can
simply set one or more directories containing your denote notes via the
consult-notes-file-dir-sources
variable as described above, or you can turn on
the minor mode (consult-notes-denote-mode)
, which does three things. First, it
adds your denote-directory
files to consult-notes-all-sources
. Second, it sets
the display of denote files in consult slightly differently, in the format of
ID Title #keywords /directory size date modified
. ID, title, keywords, and
directory are all searchable. If you like you can customize variables to hide
the ID and directory. Third, the minor mode sets the default function when there
is no match to create a denote note. Turning off the minor mode resets the
defaults.
Please note that if you use denote with siloed directories then you need to
modify the default dir-locals.el
file so as use a string rather than the
variable default-directory
. So put something like the following in the
dir-locals.el
file:
((nil . ((denote-directory . "./"))))
Org-Roam
Org-roam may be used in conjunction with consult-notes but two things should be kept in mind. First, org-roam works primarily with the concept of a ‘node’, which can be either a file or a headline within a file. This means we need to add org-roam sources differently from that of standard directory sources. Second, org-roam provides its own completing read interface, which needs to be integrated with consult-notes.
So, if you want to integrate consult-notes with org-roam, be sure to call the
minor-mode integration via the function (consult-notes-org-roam-mode)
. This sets
up a minor mode providing some useful functions to integrate search of org-roam
nodes and of org-roam references with the consult-notes
search and display
functions. It also sets the org-roam display interface to look like that of the
consult-notes interface when used apart from consult (e.g. in calling
org-roam-node-find
). It adds all your org-roam nodes (whether files or
headlines) to the consult-notes interface (you don’t need to do anything
additional for this – it simply reads off of your org-roam settings), and it
adds your org-roam directory to the list of directories on which
consult-notes-search-in-all-notes
runs. More functionality may be added in the
future.
The annotation of org-roam notes in consult-notes uses a function that displays
directory and modified time. You can display the number of backlinks and file
size by setting the variables consult-notes-org-roam-blinks
and
consult-notes-org-roam-show-file-size
to t
. Please see the function
consult-notes-org-roam-annotate
for further details. If you have an org-roam
database that consists of 3000+ nodes, you may see some latency with these
additional annotations, so please adjust accordingly.
Org Headings
If you have org files with many headings (say some subset of your agenda files,
for example) that you would like to include in a consult-notes search, you can
enable consult-notes-org-headings-mode
and the headings for files you specify in
consult-notes-org-headings-files
will be included in consult-notes.
Embark support
If you use embark you can integrate consult-notes actions with embark. Note that Embark will run on the CAND at point, which will often return either a file name, or a file name plus other annotations, depending on what your sources are. So you’ll have to write a function to manipulate CAND to give you a viable path to the file or a directory containing the file.
(defun consult-notes-my-embark-function (cand)
"Do something with CAND"
(interactive "fNote: ")
(my-function))
(defvar-keymap consult-notes-map
:doc "Keymap for Embark notes actions."
:parent embark-file-map
"m" #'consult-notes-my-embark-function)
(add-to-list 'embark-keymap-alist `(,consult-notes-category . consult-notes-map))
;; make embark-export use dired for notes
(setf (alist-get consult-notes-category embark-exporters-alist) #'embark-export-dired)
Citar Support
If you use citar you can integrate support with consult-notes and org-roam as follows:
;; Search org-roam notes for citations (depends on citar)
(defun consult-notes-org-roam-cited (reference)
"Return a list of notes that cite the REFERENCE."
(interactive (list (citar-select-ref
:rebuild-cache current-prefix-arg
:filter (citar-has-note))))
(let* ((ids
(org-roam-db-query [:select * :from citations
:where (= cite-key $s1)]
(car reference)))
(anodes
(mapcar (lambda (id)
(org-roam-node-from-id (car id)))
ids))
(template
(org-roam-node--process-display-format org-roam-node-display-template))
(bnodes
(mapcar (lambda (node)
(org-roam-node-read--to-candidate node template)) anodes))
(node (completing-read
"Node: "
(lambda (string pred action)
(if (eq action 'metadata)
`(metadata
;; get title using annotation function
(annotation-function
. ,(lambda (title)
(funcall org-roam-node-annotation-function
(get-text-property 0 'node title))))
(category . org-roam-node))
(complete-with-action action bnodes string pred)))))
(fnode
(cdr (assoc node bnodes))))
(if ids
;; Open node in other window
(org-roam-node-open fnode)
(message "No notes cite this reference."))))
Related Packages
- Consult-org-roam offers consult-completion/narrowing functionality related strictly to org-roam.
- Deft provides dedicated buffer notes search/filtering
- Denote provides simple note creation with an efficient file-naming scheme
- Emacs-zettelkasten provides a basis for a zettelkasten type notetaking system
- Zk offers a dead-simple, feature-rich Zettelkasten implementation for Emacs
Acknowledgments
Thanks to Daniel Mendler for consult and advice about the consult-grep
function,
the good work of Howard Melman, whose original notes function provided the initial
basis for this package, and both Protesilaos Stavrou and Bruce D’Arcus for helpful discussion and advice.