simfish:

Emacs/Notes

Notes is LitDoc based workflow for Zettelkasten based note taking.

cover image


Requirements


Introduction

This is a note taking and review workflow. It integrates Zettelkasten based note taking & organization using org-roam Emacs package.

The basic life cycle of a note starts by capturing information of interest. This is achieved using tasks workflow. The captured information is added as a TODO task in an org agenda inbox. The TODO entry can be associated with a deft note file link, which is used to collect details of the information.

At later point in time, the user can re-visit the note from org-agenda or directly from deft notes, and make a decision whether to discard the note or expand on it. If the latter is chosen, the note is rewritten using one own words. Additional information such as citation, calculation, hand written notes, figures, code samples and so forth can be attached to the note using org-attach. This stage is equivalent to literature review in Zettelkasten method.

Subsequent visits to the note will allow the user to build in-depth understanding of the topic and should result in a set of distilled Zettelkasten notes.

Dependencies

This workflow depends on Anki and Xournal++.

;;(use-modules (anki))
(specifications->manifest '(
  "xournalpp"
  "emacs-request"
  ;;"anki"
  ))

Customizations

org-roam notes directory,

(defcustom notes:dir
 (expand-file-name "~/Documents/KB/notes")
 "Notes directory path.
 The directory is storage location for org-roam based notes.")

Anki base directory,

(defcustom notes:anki-dir
 (expand-file-name "${HOME}/Documents/KB/anki")
 "Anki base directory.
 The directory is storage location anki add-ons, database, and user preferences.")

External application file associations

(eval-after-load "org"
  '(progn
     ;; xournal app association
     (if (assoc "\\.xopp\\'" org-file-apps)
         (setcdr (assoc "\\.xopp\\'" org-file-apps) "xournalpp %s")
         (add-to-list 'org-file-apps '("\\.xopp\\'" . "xournalpp %s") t))
         (setcdr (assoc "\\.xopp\\'" org-file-apps) "xournalpp %s")
         ))

Xournal++ org-attachment file template,

(defcustom notes:xournalpp-doc-template
  "<xournal creator=\"xournalpp 1.3.3\" fileversion=\"4\">
  <title>Xournal++ document - see https://xournalpp.github.io/</title>
  <preview>iVBORw0KGgoAAAANSUhEUgAAAFsAAACACAIAAADrrYIiAAAABmJLR0QA/wD/AP+gvaeTAAAB+UlEQVR4nO3b0WrDMAyFYdlx3v99m0jahSBQpyQuaBBvvy9CL5SzdfmkMkTF3d399XrdXgfLVHXf9/TMbdtyM83snOnuVTjvp23bJiIj18EyMzueQFZmBLp7bqaqdpki0tZ1jVfx4vo6Uha/+rIsuZlm1lpLzHT3Wus5EyMYwQhGMIIRjGAEIxh5uhH+0+sPXUPXMFkxghGMYAQjGMEIRjAyvREziwd7ewbL4i9SSknMjP3j4E8fz/x4b3P3IHR7Bsu+Ok/LFJEWvM1sWZbr62BZKSW6JjEznl5uZrz/871MViYrn74YwQhGMIIRjGAEIxiZ3Qh73/7QNXQNkxUjGMEIRjCCEYxgBCPTG4l12fEQLq6DZbEuHCl7YOavbMKPBWpuppmlb9fPmSLSgo27t9aur4NlR9fkZpZSbsu+yow5cr6Xycpk5dMXIxjBCEYwghGMYAQjsxth79sfuoauYbJiBCMYwQhGMIIRjGBkeiN8u7W7t6mqiKhqrfX6OlgWRnIzo2tUNTdTVUsp3b3/eu97zmSyMln59MUIRjCCEYxgBCMYwcgfMMLetz90DV3DZMUIRjCCEYxgBCMYwcj0RqbY+8abzM38WDnN3vf4Mm763rcrnmnvG13D3pfJ+oTJihGMYAQjGMEIRjCCEYw83Ah73/7QNX3X/ACCOyI7neU/3wAAAABJRU5ErkJggg==</preview>
  <page width=\"595.27559\" height=\"841.88976\">
  <background type=\"solid\" color=\"#ffffffff\" style=\"graph\"/>
  <layer/>
  </page>
  </xournal>"

  "Template Xournal++ document")

Key Bindings

Note Taking

;; note launcher
(kb::def :states  'normal
  "n"    '(:ignore t                           :which-key "notes")
  "ni"   '(org-roam-node-insert                :which-key "insert")
  "nn"   '(org-roam-capture                    :which-key "open/create"))

Searching,

(kb::def :states  'normal
  "n/"  '(deft  :which-key "title search"))

Note tagging & tag editing,

;; Tags & Attachements
(kb::def :states  'normal
  :keymaps 'org-mode-map
  "nt"    '(:ignore t                           :which-key "roam tags")
  "ntt"   '(org-roam-tag-add                    :which-key "add")
  "ntd"   '(org-roam-tag-delete                 :which-key "delete"))

Annotating, The org-noter package can be used to create document outline. This is only useful after creating an org-roam note.

(kb::def :states  'normal
  :keymaps 'pdf-view-mode-map
  "n"    '(:ignore t                           :which-key "notes")
  "no"   '(org-noter-create-skeleton           :which-key "outline")
  "nq"   '(org-noter-kill-session              :which-key "quit sessions"))

Listing back-links,

(kb::def :states  'normal
  :keymaps 'org-mode-map
  "n"    '(:ignore t                           :which-key "notes")
  "nb"   '(org-roam-buffer-toggle              :which-key "show backlinks"))

Notes can be visualized using org-roam-ui:

(kb::def :states  'normal
  :keymaps 'org-mode-map
  "n"    '(:ignore t                           :which-key "notes")
  "nv"   '(org-roam-ui-open                    :which-key "visualize notes"))

Note file attachment keybindings,

;; Attachements
(kb::def :states  'normal
  :keymaps 'org-mode-map
  "na"    '(:ignore t                           :which-key "attachment")
  "naa"   '(org-attach                          :which-key "default")
  "nax"   '(notes::attach-xournalpp             :which-key "Xournal++")
  "nao"   '(org-attach-open                     :which-key "open"))

Functions

Attaching to note Xournal++ file

(defun notes::attach-xournalpp ( )
  "Create a new Xournal++ (.xopp) document and attach it to the current Org entry."
  (interactive)
  (unless (derived-mode-p 'org-mode)
    (error "note::add-xournal-file: Not in org-mode"))
  (let* ((attach-dir (org-attach-dir t))
         (xml-tmp-file   (make-temp-file nil nil ".xml"))
         (xopp-tmp-file  (make-temp-file nil nil ".xopp")))
    ;; Write gzipped XML to the .xopp file
    (with-temp-buffer
      (insert notes:xournalpp-doc-template)
      (write-region (point-min) (point-max) xml-tmp-file))

    ;; gzip the file
    (call-process
     "gzip" nil nil nil "-f" "-c"
     xml-tmp-file  ">" xopp-tmp-file)

    ;; attach the file to Org entry
    (org-attach-attach xopp-tmp-file nil 'mv)

    ;; Open in Xournal++
    ;;(start-process "xournalpp" nil "xournalpp" filepath)

    (message "Created xournal++ file attachement")))

Packages

Package: org-roam

;; //////////////////////////////////////////////////////////////////////////////
;; Note Taking
;; //////////////////////////////////////////////////////////////////////////////

(defun notes::get-dir ( )
  "Returns the root directory where annotated papers are stored"
  notes:dir)

(use-package org-roam
  :guix (:name emacs-org-roam)
  :demand t
  :hook
  ((after-init . org-roam-mode)
   (org-roam-backlinks-mode . visual-line-mode))
  :init
  (setq org-roam-v2-ack t)
  :general
  <<org-roam-kb>>
  :config
  (setq org-roam-capture-templates '(("d" "default" plain "%?"
   :target (file+head "${slug}-%<%Y%m%d%H%M%S>.org" "#+title: ${title}")
   :unnarrowed t)))
  :custom
  (org-roam-db-location (file-truename  "~/.config/distro-config/notes/org-roamd.db"))
  (org-roam-directory   (notes::get-dir))
  (org-roam-completion-system 'helm))

Package: org-roam-bibtex

(use-package org-roam-bibtex
  :guix (:name emacs-org-roam-bibtex)
  :demand t)

Package: org-noter

(use-package org-noter
  :guix (:name emacs-org-noter)
  :demand t
  :config
  ;;orb settings
  (require 'org-roam-bibtex)
  (setq orb-preformat-keywords
        '(("citekey" . "=key=")
          "title"
          "url"
          "file"
          "author-or-editor"
          "keywords"))
  (setq orb-templates
        '(("r" "ref" plain (function org-roam-capture--get-point)
           ""
           :file-name "${citekey}"
           :head "#+TITLE: ${citekey}: ${title}\n#+ROAM_KEY: ${ref}
           - tags ::
           - keywords :: ${keywords}
           ,* ${title}
           :PROPERTIES:
           :Custom_ID: ${citekey}
           :URL: ${url}
           :AUTHOR: ${author-or-editor}
           :NOTER_DOCUMENT: ${file}
           :NOTER_PAGE:
           :END:"))))

Package: deft

;;  (setq deft-extensions '("org" "md" "txt" "taskpaper"))
(advice-add 'deft-parse-title :override
    (lambda (file contents)
      (if deft-use-filename-as-title
	  (deft-base-filename file)
	(let* ((case-fold-search 't)
	       (begin (string-match "title: " contents))
	       (end-of-begin (match-end 0))
	       (end (string-match "\n" contents begin)))
	  (if begin
	      (substring contents end-of-begin end)
	    (format "%s" file))))))

(use-package deft
  :guix (:using channel :name emacs-deft)
  :after org
  :general
  <<deft-kb>>
  :config
  (setq deft-directory (notes::get-dir))
  (setq deft-recursive t)
  (setq deft-text-mode 'org-mode)
  (setq deft-use-filename-as-title 't)
  (setq deft-strip-summary-regexp
      (concat "\\("
	  "^:.+:.*\n" ; any line with a :SOMETHING:
	  "\\|^#\\+.*\n" ; anyline starting with a #+
	  "\\|^\\*.+.*\n" ; anyline where an asterisk starts the line
	  "\\)")))