Skip to content

Latest commit

 

History

History
207 lines (163 loc) · 7.22 KB

2025-01-22-195006.org

File metadata and controls

207 lines (163 loc) · 7.22 KB

howm & org-drill: Note-taking tool with flashcards combined

screencast_output.mp4

Abstract

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.

Prerequisites

org & org-drill

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)

workarounds for org-drill

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

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.

howm with org-mode as a default markup

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

howm with function to select any major mode available

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.

code in order of execution

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.

Conclusion

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.