screencast_output.mp4
The article contains the detailed presentation of the environment that is designed to be used for knowledge management and active recall, based upon a set of Emacs packages, the names of which are given below:
- howm,
- org,
- org-drill.
This environment glues together these various modes with added Lisp code. Code would be placed in order of execution given below. With this article provided as an org-mode-formatted file, one can edit it and tangle the source code block into the Emacs config via org-mode and org-babel.
The idea for this solution comes from the author’s inability to use RemNote — a proprietary software for note-taking, with an option to easily convert notes into flashcards.
Org-mode is major mode preinstalled in GNU/Emacs by default.
Org-drill can be installed with this simple use-package directive:
(use-package org-drill
:pin melpa
:ensure t)
Unfortunately, there are various bugs present in org-drill; however the workaround for this package, found on reddit, is provided below:
(defun org-drill-time-to-inactive-org-timestamp (time)
"Convert TIME into org-mode timestamp."
(format-time-string
(concat "[" (cdr org-time-stamp-formats) "]")
time))
Link to discussion on the Reddit altfrontend: https://safereddit.com/r/orgmode/comments/1g51wtc/orgdrill_gives_me_the_error_not_an_org_time_string/
Howm-mode is a minor mode, meaning that it can be used in combination with a selected major mode - like org-mode - and multiple minor-modes simultaneously.
The Howm markup is simple: = symbol at the start of the line creates a title for the given note; one might add multiple titles in the same file.
3 > characters create a link that works in howm like a search query; after entering this link, one would see a search result with all the headings from the text files containing parts of the search query.
3 < symbols create a search query as well, but instead of linking it would be similar to a hashtag. After saving the file with such link, the words typed in it are to be highlighted as links across the enitre set of notes.
As mentioned above, the howm-mode is a minor mode and can be combined with other Emacs modes. It is possible to configure it for usage with either org-mode or markdown-mode. One can also use multiple major mode markups with howm-mode.
Simple use-package directive, as in the official Quick Start.
(use-package howm
:ensure t
:init
;; What format to use for the files?
(setq howm-file-name-format "%Y-%m-%d-%H%M%S.org")
(setq howm-view-title-header "*")
(setq howm-dtime-format "<%Y-%m-%d %a %H:%M>")
;; Avoid conflicts with Org-mode by changing Howm's prefix from "C-c ,".
(setq howm-prefix (kbd "C-c ;"))
:bind*
;; Conveniently open the Howm menu with "C-c ; ;".
("C-c ; ;" . howm-menu))
Simple use-package directive; one can modify the above-mentioned one
by removing howm-view-title-header
variable as well.
(use-package howm :config
:ensure t)
Emacs can set local variables as comments in the edited files. There is also a way to do it in one line at the start of the file, called a prop-line. It used to be applied to add local encoding variable into a file with Python source code.
Emacs would automatically switch to major mode selected in prop-line once the file is opened.
Below is a function to add a prop-line to the file.
(defun howm-insert-prop-line (mode)
"Activate major mode and modify the file so that this mode is
activated automatically the next time it is opened"
(interactive (list (intern-soft
(completing-read "Choose major mode: "
(mapcar #'cdr auto-mode-alist)))))
(howm-mode)
(unless (or (null mode)
(eq mode major-mode))
(funcall mode)
(howm-mode)
(add-file-local-variable-prop-line
'mode (intern (string-trim-right (symbol-name mode) "-mode\\'")))))
One can also use the general function for adding prop-line, as written by the author of howm himself.
Although keeping the writings in howm is preferable for myself, a need to transfer the texts in various other places, where different markup languages, such as markdown, could be used, exists. While admiring the org-mode capabilities deeply, I don’t like the idea of having to choose between markup languages, whereas I can use several of such. That resulted in my attempt to create a workflow for managing notes in multiple formats. One can argue that it is a little bit clunky, but I believe there is enough space for improvement.
I wrote 2 elisp functions that will be executed after starting
org-drill session. To execute them, I wrote advises for org-drill
and
org-drill-cram
functions, so that advice’s would call my function
before executing the org-drill functions.
(define-advice org-drill (:before (&rest _args))
(my-org-drill-set-scope))
(define-advice org-drill-cram (:before (&rest _args))
(my-org-drill-set-scope))
So, advice’s would execute a function for setting scope in org-drill. By default, org-drill does not operate on decks of flashcards, but uses scopes — a set of variables containing information in which files to search for the flashcards.
Here is my function for choosing scope:
(defun my-org-drill-set-scope ()
(interactive)
(let ((scope-var
(completing-read "Choose scope for org-drill: " (list
"howm"
"file"
"tree"
"file-no-restriction"
"agenda"
"agenda-with-archives"
"directory"))))
(if (equal scope-var "howm")
(setq org-drill-scope (my-org-drill-file-names-in-howm))
(setq org-drill-scope (intern scope-var)))))
Note that this “howm” scope is non-existent in org-drill itself. So
when selecting this option, scope would be set to a list of files
containing all files in howm with tag :drill:
. Yes, that is
an org-mode tag, but due to the fact that howm simply uses grep
underneath, it is, however, possible to return the list of files that contain
the given string.
Here is a function that returns the said list of files for howm scope.
(defun my-org-drill-file-names-in-howm ()
"Return list of absolute filenames of org-drill files in howm"
(delete-dups
(mapcar #'car (howm-grep "\:drill\:"
(howm-files-in-directory howm-directory)))))
That is all, really. As I said at the start of the paragraph there are only two functions needed to implement given system.
Above is a demonstration of how easy it is to create an out-liner with functions of personal wiki and active recall learning software interconnected in one lisp image of GNU Emacs.
I hope that it will become more widespread and will be adopted more often than similar proprietary solutions, since it is much more extensible.