summaryrefslogtreecommitdiff
path: root/elfeed-custom-feeds-github.el
diff options
context:
space:
mode:
authorvin <git@vineetk.net>2025-12-08 16:51:59 -0500
committervin <git@vineetk.net>2025-12-08 16:55:05 -0500
commitaf9627b43eaf4e40fadc9be82ccc2f10f33746a3 (patch)
treed66c4aed05c37f159718e4a8af6b8b80134f4116 /elfeed-custom-feeds-github.el
parent2113d0279b035f183c0c05627bbd2b0779e98f35 (diff)
attempt to make the plugin more async-y
Diffstat (limited to 'elfeed-custom-feeds-github.el')
-rw-r--r--elfeed-custom-feeds-github.el76
1 files changed, 54 insertions, 22 deletions
diff --git a/elfeed-custom-feeds-github.el b/elfeed-custom-feeds-github.el
index 660350d..a857963 100644
--- a/elfeed-custom-feeds-github.el
+++ b/elfeed-custom-feeds-github.el
@@ -57,15 +57,15 @@
57 (funcall cb r dn items)))) 57 (funcall cb r dn items))))
58 nil t))))) 58 nil t)))))
59 59
60(defun elfeed-custom-feeds-github--prs-to-elfeed (repo display-name prs) 60(defun elfeed-custom-feeds-github--prs-to-elfeed (repo display-name prs completion-callback)
61 "Convert GitHub PRS to elfeed entries for REPO with DISPLAY-NAME." 61 "Convert GitHub PRS to elfeed entries for REPO with DISPLAY-NAME.
62Call COMPLETION-CALLBACK with (repo display-name new-entries) when done."
62 (let ((feed-url (format "https://github.com/%s/pulls" repo)) 63 (let ((feed-url (format "https://github.com/%s/pulls" repo))
63 (new-count 0)
64 (new-entries ())) 64 (new-entries ()))
65 (let ((feed (elfeed-db-get-feed feed-url))) 65 (let ((feed (elfeed-db-get-feed feed-url)))
66 (setf (elfeed-feed-url feed) feed-url 66 (setf (elfeed-feed-url feed) feed-url
67 (elfeed-feed-title feed) (format "GitHub: %s [%s]" repo display-name))) 67 (elfeed-feed-title feed) (format "GitHub: %s [%s]" repo display-name)))
68 68
69 (dolist (pr prs) 69 (dolist (pr prs)
70 (let* ((number (alist-get 'number pr)) 70 (let* ((number (alist-get 'number pr))
71 (title-text (alist-get 'title pr)) 71 (title-text (alist-get 'title pr))
@@ -86,7 +86,7 @@
86 (format "<p><strong>Labels:</strong> %s</p>" 86 (format "<p><strong>Labels:</strong> %s</p>"
87 (mapconcat 'identity labels ", ")) 87 (mapconcat 'identity labels ", "))
88 "") 88 "")
89 (replace-regexp-in-string "<" "&lt;" 89 (replace-regexp-in-string "<" "&lt;"
90 (replace-regexp-in-string ">" "&gt;" body))))) 90 (replace-regexp-in-string ">" "&gt;" body)))))
91 (unless (elfeed-db-get-entry entry-id) 91 (unless (elfeed-db-get-entry entry-id)
92 (let ((entry (elfeed-entry--create 92 (let ((entry (elfeed-entry--create
@@ -98,27 +98,59 @@
98 :content-type 'html 98 :content-type 'html
99 :feed-id feed-url 99 :feed-id feed-url
100 :tags '(unread github)))) 100 :tags '(unread github))))
101 (push entry new-entries) 101 (push entry new-entries)))))
102 (setq new-count (1+ new-count)))))) 102
103 103 ;; Call completion callback with results
104 (when new-entries 104 (funcall completion-callback repo display-name (nreverse new-entries))))
105 (elfeed-db-add (nreverse new-entries)))
106
107 (message "GitHub feed %s [%s]: %d new entries" repo display-name new-count)
108 (when (get-buffer "*elfeed-search*")
109 (with-current-buffer "*elfeed-search*"
110 (elfeed-search-update--force)))))
111 105
112;;;###autoload 106;;;###autoload
113(defun elfeed-custom-feeds-github-update () 107(defun elfeed-custom-feeds-github-update ()
114 "Update all GitHub PR feeds." 108 "Update all GitHub PR feeds asynchronously.
109Batches all entries and updates UI once at the end to avoid blocking."
115 (interactive) 110 (interactive)
116 (cl-loop for (repo query display-name) in elfeed-custom-github-pr-queries 111 (let* ((total (length elfeed-custom-github-pr-queries))
117 for i from 0 112 (processed 0)
118 for delay = (* i elfeed-custom-github-request-delay) 113 (all-new-entries '())
119 do (elfeed-custom-feeds-github--fetch-prs repo query display-name 114 (results '()))
120 #'elfeed-custom-feeds-github--prs-to-elfeed 115
121 delay))) 116 (when (zerop total)
117 (message "No GitHub PR queries configured")
118 (cl-return-from elfeed-custom-feeds-github-update nil))
119
120 ;; Completion callback that batches everything
121 (let ((completion-callback
122 (lambda (repo display-name new-entries)
123 (setq processed (1+ processed))
124 (when new-entries
125 (setq all-new-entries (append all-new-entries new-entries)))
126 (push (list repo display-name (length new-entries)) results)
127
128 ;; When all queries are done, batch add to DB and update UI once
129 (when (= processed total)
130 (let ((total-count (length all-new-entries)))
131 (when (> total-count 0)
132 (elfeed-db-add all-new-entries))
133 ;; Report results for each feed
134 (dolist (result (nreverse results))
135 (message "GitHub feed %s [%s]: %d new entries"
136 (nth 0 result) (nth 1 result) (nth 2 result)))
137 ;; Defer UI update to avoid blocking
138 (run-with-idle-timer 0.1 nil
139 (lambda ()
140 (when (get-buffer "*elfeed-search*")
141 (with-current-buffer "*elfeed-search*"
142 (elfeed-search-update--force))))))))))
143
144 ;; Start all async fetches
145 (cl-loop for (repo query display-name) in elfeed-custom-github-pr-queries
146 for i from 0
147 for delay = (* i elfeed-custom-github-request-delay)
148 do (elfeed-custom-feeds-github--fetch-prs
149 repo query display-name
150 (lambda (r dn items)
151 (elfeed-custom-feeds-github--prs-to-elfeed r dn items completion-callback))
152 delay)))
153 nil))
122 154
123(provide 'elfeed-custom-feeds-github) 155(provide 'elfeed-custom-feeds-github)
124 156