summaryrefslogtreecommitdiff
path: root/content
diff options
context:
space:
mode:
authorrtk0c <[email protected]>2025-04-19 12:33:01 -0700
committerrtk0c <[email protected]>2025-04-19 12:33:01 -0700
commit5cf19f1f3d7f7310d5314adb1660b7633fc8790f (patch)
tree17bf3191cc221512d1b6edc1f6d3a6320045835f /content
parentc7ffe17f14cee4d439c7541ffb4abb8cabbfc0db (diff)
Watchlist × Emacs org-mode
Diffstat (limited to 'content')
-rw-r--r--content/blog/org-mode-watchlist.md78
1 files changed, 78 insertions, 0 deletions
diff --git a/content/blog/org-mode-watchlist.md b/content/blog/org-mode-watchlist.md
new file mode 100644
index 0000000..9c58819
--- /dev/null
+++ b/content/blog/org-mode-watchlist.md
@@ -0,0 +1,78 @@
+---
+title: "Watchlist × Emacs org-mode"
+date: 2025-04-19T12:29:00-07:00
+---
+
+Watch progress websites exist for [anime](https://myanimelist.net) and [film](https://letterboxd.com). They work great. Socialization is great.
+
+But they don't record the _exact time_ at which I finished each episode. I find such statistics amusing to dig through in some kind of a year-end review. I also found it tremendously helpful to know which episodes were most recently watched, and in what order. Helps with recollecting the context of each show, especially when chasing more than a couple of shows at the same time.
+Depending on your judgment, using Letterboxd and MyAnimeList may also constitute giving private information to 3rd parties.
+
+So I ended with an organization system that's, effectively, top layer of bullet points for the show, and inner layer for the episodes. Something like:
+
+```org
+* STRT SHIROBAKO
+** [2025-04-01 Tue 11:11] E01
+** [2025-04-16 Wed 22:22] E02
+* TODO Do It Yourself!!
+* DONE ゆるキャンプ
+** [2025-03-20 Thu 20:21] E10
+** [2025-03-21 Fri 20:59] E11
+** [2025-04-14 Mon 21:36] E12
+* STRT mono
+** [2025-04-13 Sun 16:56] E01
+```
+
+I want to be able to run a command, and get it as a linear timeline:
+
+```org
+* [2025-03-20 Thu 20:21] ゆるキャンプ E10
+* [2025-03-21 Fri 20:59] ゆるキャンプ E11
+* [2025-04-01 Tue 11:11] SHIROBAKO E01
+* [2025-04-13 Sun 16:56] mono E01
+* [2025-04-14 Mon 21:36] ゆるキャンプ E12
+* [2025-04-16 Wed 22:22] SHIROBAKO E02
+```
+
+Which turns out to be a pretty easy simple regex-based forward parsing algorithm. I thought about using `org-element-map`, but it seemed like a bit of an overkill?
+
+To use, I do <kbd>g g M-x org-category->timeline</kbd> (evidently, I use evil-mode), bringing me to a new buffer `*Category Timeline*` filled out appropriately.
+
+```emacs-lisp
+(defun org-category->timeline ()
+ "Collect category-timestamp tree into a single, chronologically
+ordered timestamp list. Starting at point."
+ (interactive)
+ (let ((pt (point))
+ (curr-category nil)
+ (curr-pt (search-forward "\n* " nil t))
+ (items '()))
+ ;; Collect items
+ (while curr-pt
+ (goto-char curr-pt)
+ ;; Skip org-todo marker
+ (forward-word) (forward-char)
+ (setq curr-category (buffer-substring-no-properties (point) (line-end-position))
+ curr-pt (save-excursion (search-forward "\n* " nil t)))
+ (while-let ((i (re-search-forward (rx "\n** ["
+ (group (* (not "]")))
+ "] ")
+ curr-pt t)))
+ (let ((time (match-string-no-properties 1))
+ (comment (buffer-substring-no-properties (point) (line-end-position))))
+ (push (list (encode-time (org-parse-time-string time))
+ time curr-category comment)
+ items))))
+ ;; Sort by time
+ (sort items (lambda (a b) (time-less-p (car a) (car b))))
+ ;; Restore to starting point in the source buffer
+ (goto-char pt)
+ ;; Print items into a new buffer
+ (switch-to-buffer "*Category Timeline*")
+ (erase-buffer)
+ (dolist (i items)
+ (let ((time (cadr i))
+ (category (caddr i))
+ (comment (cadddr i)))
+ (insert "* [" time "] " category " " comment ?\n)))))
+```