Workflow for learning and reviewing information efficiently
Emacs/Learn
Introduction
This workflow is useful for breaking down study sessions into
manageable time chunks using org-pomodoro. Each time chunk can be
used to complete a topic. If the material requires a review, tag
it with a TODO
and schedule review drills using org-drill.
Org agenda can be used to manage future review sessions.
Customization
Select where to place drill files
(defcustom learn:default-drill-dirs
'( "~/Documents/KB" "~/Documents/research/notes")
"specifies the default org-drill directory"
:type '(file)
:group 'org-drill)
Some advanced org-drill settings
(setq org-drill-maximum-items-per-session 50
org-drill-maximum-duration 20 ;(minutes)
org-drill-use-visible-cloze-face-p t
org-drill-add-random-noise-to-intervals-p t
org-drill-hint-separator "||"
org-drill-left-cloze-delimiter "["
org-drill-right-cloze-delimiter "]"
org-drill-learn-fraction 0.25
org-drill-cram-hours 2
org-drill-leech-method 'warn)
Key Bindings
(kb::def :states 'normal
"o" '(:ignore t "Org")
"od" '(learn::drills :which-key "start drills")
"op" '(org-pomodoro :which-key "pomodoro"))
Functions
Learning Drills: use org-drill to find and run drills. This involves two steps. First, list of org files containing drills are generated using async search
(defun learn::find-drills-async ( paths callback)
(require 'async)
(async-start
;;search command
`(lambda ( )
(require 'dash)
(require 's)
(require 'cl-lib)
(cl-loop
for path in ',paths
append (delete
""
(-non-nil
(s-lines
(shell-command-to-string
(format "ag --org -l -U \":drill:\" %s"
path)))))))
;; result callback
callback))
Once the drill list is populated, org-drill can be run using:
(defun learn::drills ( )
(interactive)
(require 'gix-log)
(require 'dash)
(require 's)
(require 'cl)
(require 'org-drill)
(let* ((drill-dirs learn:default-drill-dirs))
(log:info "scaning for org files...")
(cond ( ;;found search dirs?
(not (null drill-dirs))
;; summarize search directories
(cl-loop
for dir in drill-dirs
do (log:sub-info "drills directory: %s" dir))
;; do search
(learn::find-drills-async
drill-dirs
(lambda (result)
(require 'org-drill)
(setq org-drill-scope result)
(cond (;; is scope valid?
(and (not (null org-drill-scope))
(not (zerop (length org-drill-scope))))
(log:sub-info "scope: %s\n" org-drill-scope)
(org-drill))
(t ;; invalid scope
(log:info "There are no drills found for now!"))))))
(t
(log:info "No search path specified: <%s>" search-dirs)
(log:sub-info "Try using org-drill within project directory")
(log:sub-info "Also, try customizing `learn:default-drill-dirs'")))))
Pomodoro Tasks how can TODO
task states be tracked efficiently?
State of a TODO
task can change for two reasons
- Manually when the user changes the state, for example via Tab cycling
- When a pomodoro timer starts or finishes a break
The first case can easily be addressed by using org-todo-working-hook, org-todo-paused-hook, and help:org-todo-done-hook hooks.
For the later case, org-pomodoro comes with a set of hooks that run when a pomodoro is, started paused, resumed, finished, and killed.
(defvar learn::pomodoro-count nil)
(defvar learn::pomodoro-ignore-state-changed nil)
(defun learn::on-todo-state-working ( )
"Start or resume org-pomodoro"
(require 'org-pomodoro)
(setq learn::pomodoro-count org-pomodoro-count)
(unless learn::pomodoro-ignore-state-changed
(cond (;; is pomodoro started yet?
(eq org-pomodoro-state :none)
(org-pomodoro))
(;; is pomodoro on short break?
(eq org-pomodoro-state :break)
(let ((org-pomodoro-keep-killed-pomodoro-time t))
(org-pomodoro-killed)))
(t ;; default do notthing
))))
(defun learn::on-todo-state-paused ( )
"Pause active pomodoro(if any)"
(setq learn::pomodoro-count org-pomodoro-count)
(unless learn::pomodoro-ignore-state-changed
(cond (;; any pomodoro running?
(eq org-pomodoro-state :pomodoro)
(let ((org-pomodoro-keep-killed-pomodoro-time t))
(org-pomodoro-killed)))
(;; any break in progress?
(or (eq org-pomodoro-state :break)
(eq org-pomodoro-state :long-break))
(org-pomodoro-killed)))))
(defun learn::on-todo-state-done ( )
"Stops any pomodoro activity."
(setq learn::pomodoro-count org-pomodoro-count)
(unless learn::pomodoro-ignore-state-changed
(when (org-pomodoro-active-p)
(org-pomodoro-killed))))
(defun learn::pomodoro/on-break-finished ( )
"Update task state to WORKING and resume pomodoro."
(setq learn::pomodoro-count org-pomodoro-count)
(let ((learn::pomodoro-ignore-state-changed t)
(m (car org-clock-history)))
(save-window-excursion
(pop-to-buffer-same-window (marker-buffer m))
(if (or (< m (point-min)) (> m (point-max))) (widen))
(goto-char m)
(cond ((yes-or-no-p "Ready for another pomodoro session?")
(org-todo "TODO")
(org-show-entry)
(org-pomodoro))
(t
(org-todo "TODO")
(org-show-entry))))))
(defun learn::pomodoro/on-finished ( )
(setq learn::pomodoro-count org-pomodoro-count)
(save-window-excursion
(let (
(m (car org-clock-history))
(learn::pomodoro-ignore-state-changed t)
)
(pop-to-buffer-same-window (marker-buffer m))
(when (or
(< m (point-min))
(> m (point-max)))
(widen))
(goto-char m)
(org-todo "TODO")
(org-show-entry))))
(defun learn::pomodoro/on-started ( )
(setq learn::pomodoro-count org-pomodoro-count)
(save-window-excursion
(let ((m org-clock-marker)
(learn::pomodoro-ignore-state-changed t))
(pop-to-buffer-same-window (marker-buffer m))
(when (or
(< m (point-min))
(> m (point-max)))
(widen))
(goto-char m)
(org-todo "WORKING")
(org-show-entry))))
Packages
Package: org-drill
(use-package org-drill
:guix (:name emacs-org-drill)
:init
<<org-drill-init>>
:config
<<org-drill-config>>)
Package: pomodoro
(use-package org-pomodoro
:guix (:name emacs-org-pomodoro)
:demand t
:commands
org-pomodoro
:hook
(org-todo-working . learn::on-todo-state-working)
(org-todo-paused . learn::on-todo-state-paused)
(org-todo-done . learn::on-todo-state-done)
(org-pomodoro-finished . learn::pomodoro/on-finished)
(org-pomodoro-break-finished . learn::pomodoro/on-break-finished)
(org-pomodoro-started . learn::pomodoro/on-started)
:custom
(org-pomodoro-ask-upon-killing nil)
(org-pomodoro-format "%s") ;;
(org-pomodoro-short-break-format "%s")
(org-pomodoro-long-break-format "%s")
(org-pomodoro-play-sounds t)
:custom-face
(org-pomodoro-mode-line ((t (:foreground "#E9967a"))))
(org-pomodoro-mode-line-break ((t (:foreground "#90ee90")))))
Package: sox
(use-package sox
:guix (:name sox)
:disabled)