Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/mclear-tools/consult-notes

Use consult to search notes
https://github.com/mclear-tools/consult-notes

Last synced: 3 months ago
JSON representation

Use consult to search notes

Awesome Lists containing this project

README

        

#+html: GNU Emacs
#+html: MELPA
#+html: Buy Me A Coffee

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 [[https://github.com/localauthor/zk][zk]], [[https://github.com/protesilaos/denote][denote]], or [[https://github.com/org-roam/org-roam][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 [[https://github.com/oantolin/embark][embark]] (see below). For
other customizations please consult the options via =M-x customize-group
consult-notes=.

#+ATTR_HTML: :width 85%
[[file:screenshots/notes-screenshot1.png]]
#+ATTR_HTML: :width 85%
[[file:screenshots/notes-screenshot2.png]]
#+ATTR_HTML: :width 85%
[[file:screenshots/notes-screenshot3.png]]

* 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:

#+begin_src emacs-lisp
(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)))
#+end_src

* 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):

#+begin_src emacs-lisp
(setq consult-notes-file-dir-sources
'(("Org" ?o "~/Dropbox/org-files/")
("Org Refile" ?r "~/Dropbox/Work/projects/notebook/org-refile/")))
#+end_src

=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.

Optionally you can add =:hidden t= to hide particular folder from default list presented by =consult-multi=. The folder will be still available via it's narrowing key.
#+begin_src emacs-lisp
(setq consult-notes-file-dir-sources
'(("Visible" ?o "~/Dropbox/org-files/visible/")
("Hidden" ?r "~/Dropbox/org-files/hidden/" :hidden t)))
#+end_src

*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 [[https://github.com/minad/consult#multiple-sources][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.

#+begin_src emacs-lisp
(with-eval-after-load 'consult-notes
(add-to-list 'consult-notes-all-sources 'my-notes--additional-source 'append))
#+end_src

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
[[https://github.com/protesilaos/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, change the margin between the title and the keywords, or
to adjust the way in which the keywords and directory are displayed. 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:

#+begin_src emacs-lisp
((nil . ((denote-directory . "./"))))
#+end_src

* Org-Roam

[[https://github.com/org-roam/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 [[https://github.com/oantolin/embark][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.

#+begin_src emacs-lisp
(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)
#+end_src

* Citar Support
If you use [[https://github.com/emacs-citar/citar][citar]] you can integrate support with consult-notes and org-roam as follows:

#+begin_src emacs-lisp
;; 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."))))
#+end_src

* Related Packages
- [[https://github.com/jgru/consult-org-roam][Consult-org-roam]] offers consult-completion/narrowing functionality related strictly to org-roam.
- [[https://github.com/jrblevin/deft][Deft]] provides dedicated buffer notes search/filtering
- [[https://github.com/protesilaos/denote][Denote]] provides simple note creation with an efficient file-naming scheme
- [[https://github.com/ymherklotz/emacs-zettelkasten][Emacs-zettelkasten]] provides a basis for a zettelkasten type notetaking system
- [[https://github.com/localauthor/zk][Zk]] offers a dead-simple, feature-rich Zettelkasten implementation for Emacs

* Acknowledgments

Thanks to [[https://github.com/minad][Daniel Mendler]] for consult and advice about the =consult-grep= function,
the good work of Howard Melman, whose original [[https://github.com/minad/consult/wiki/hrm-notes][notes function]] provided the initial
basis for this package, and both [[https://protesilaos.com][Protesilaos Stavrou]] and [[https://github.com/bdarcus][Bruce D'Arcus]] for helpful discussion and advice.