Incremental writing

Potential of slipboxes, Incremental reading

If you're already used to keeping a personal wiki, you can see the similarities to the concept of incremental writing. If you aren't, it may seem odd.

I once created a headline in my proto-personal wiki (a file named wiki.org) for historical figures I wanted to know more about. I populated it with a subheading for each name. I incrementally added descriptions over months, but there were many figures I had the habit of skipping. "I'll get around to writing about David Hume later". This isn't bad until, of course, I keep skipping David Hume as a habit.

Suppose you could be shown a single one of those headlines at a time, randomly chosen for you. When shown, you'd write down honestly what you know about this person. Top of your head stuff is enough. The next time you're shown the same person, you can add to the description. Maybe even do research, depending on your standards. Rinse and repeat.

We can imagine a fairly simple elisp function for that. You could have it called automatically – let's say you normally visit the file wiki.org in View mode, and when you begin to edit, a hook is triggered to make you edit through this functionality rather than editing the file bare. The functionality would then serve up a random heading after another. Perhaps it would favor the headings with little text, or it'd show you complete headings just as often, letting you review your wiki.org as well as add to it.

Well, I sat for five hours and cranked out the "simple elisp function". Enjoy! My first time coding with org-mode.

(defvar iw-entries)

(defcustom iw-ignore "-complete"
  "Passed as the MATCH parameter to the `org-map-entries'
function. See `iw-scan-buffer'." :type 'string :group 'iw)

(defun iw-next-entry-is-deeper ()
  "Return t if the next Org headline is nested deeper than the
current one."
  (save-excursion
    (let ((prev-level (org-current-level)))
      (org-next-visible-heading 1)
      (> (org-current-level) prev-level))))

(defun iw-scan-buffer ()
  "Scan current Org buffer for leaf entries not matched by `iw-ignore',
and add them to `iw-entries'."
  (interactive)
  (save-excursion
    (org-map-entries
     (lambda ()
       (unless (iw-next-entry-is-deeper)
         (let ((full-olp (org-get-outline-path))
               (headline (nth 4 (org-heading-components))))
           (add-to-list 'full-olp buffer-file-name)
           (add-to-list 'full-olp headline t)
           (add-to-list 'iw-entries full-olp t)
           )))
     iw-ignore nil)))

(defun iw-visit-random-entry ()
  (interactive)
  (org-goto-marker-or-bmk
   (org-find-olp (nth (random (length iw-entries)) iw-entries)))
  (org-narrow-to-subtree)
  (outline-show-subtree))

(global-set-key "M-n" #'iw-visit-random-entry)

Note this works across multiple files. Just scan each file you want to work with. You can jump to any incomplete node in any of the scanned files. These nodes could be blog posts, READMEs, topics in your personal wiki, topics of study (for school). When you consider a node complete, you give it a tag and the function will ignore them.

The code works but is still rudimentary, it does not clean up entries you tag :complete: after the fact. You can eval (setq iw-entries nil) and re-scan files.

My wish list

  • Make a queue of nodes, so you cannot revisit a node without first visiting all others once
    • Actually it can be a list named 'iw-visited-entries' or so. Add to it with each random visit, then when it matches iw-entries, empty it again.
  • Keep a persistent list of files to re-scan on save

What links here

Created (6 years ago)