blob: 9c5881922d03283a069682909d733a1792c8da53 (
plain)
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
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)))))
```
|