# musing about the difficulty of doing one-off scripted edits in emacs lisp -rw-r--r-- 2.2 KiB View raw
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
;; The blob of elisp below scans through a markdown section (known to be
;; at the end of the document, and to contain only an unsorted list, all
;; of whose items are of the form "* `something`") and moves each list item
;; to one of two other sections, depending on whether the text of `something` 
;; appears in a similarly-formatted list in a scratch buffer.
;;
;; I'm recording it for posterity because I've been using Emacs for *thirty
;; years* and yet this is the first time I've ever even *attempted* this, and
;; it took me about half an hour to make it happen, with a bunch of staring at
;; the elisp reference manual.  For all of Emacs' vaunted extensibility and
;; scriptability, there's a big gulf on both the "manipulexity" and "whipuptitude"
;; axes (as Larry Wall once put it) in between what's feasible to do in a keyboard
;; macro, and the Elisp programming environment, which is geared to the needs of
;; people writing major modes and whatnot, not so much to the needs of people
;; trying to do data shuffling operations inside their buffers.  I could've done
;; the same task in five minutes and half as many lines of Python ... but not
;; without dumping both buffers into files and stepping outside of emacs.
;;
;; What would a better in-editor data shuffling language/library look like?
;; Dunno, but *someone* should think about it.

(let ((columns))
  (save-excursion
    (set-buffer "*Columns*")
    (goto-char (point-min))
    (while (re-search-forward "^\\* `\\([^`]+\\)`$" nil t)
      (push (match-string 1) columns)))

  (save-excursion
    (set-buffer "menus.md")
    (goto-char (point-min))
    (search-forward "\n### unsorted\n")
    (atomic-change-group
      (while (re-search-forward "^\\* `\\([^`]+\\)`$" nil t)
        (when (not (eobp))
          (forward-char 1))
        (let ((insert-before
               (if (member (match-string 1) columns)
                   "\n\n### other\n" "\n\n### unsorted\n"))
              (line (delete-and-extract-region (match-beginning 0) (point))))
          (save-excursion
            (goto-char (point-min))
            (search-forward insert-before)
            (goto-char (match-beginning 0))
            (insert line)))))))