Skip to content

troyfigiel/consult-notes

 
 

Repository files navigation

GNU Emacs MELPA 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 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.

screenshots/notes-screenshot1.png

screenshots/notes-screenshot2.png

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:

(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, 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:

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

About

Use consult to search notes

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Emacs Lisp 100.0%