about summary refs log tree commit diff stats
path: root/lisp/+elfeed.el
blob: 8a0376de8b314928434eebef92374c3b5e11035e (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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
;;; +elfeed.el -*- lexical-binding: t; -*-

;;; Code:

;; https://karthinks.com/software/lazy-elfeed/
(defun +elfeed-scroll-up-command (&optional arg)
  "Scroll up or go to next feed item in Elfeed"
  (interactive "^P")
  (let ((scroll-error-top-bottom nil))
    (condition-case-unless-debug nil
        (scroll-up-command arg)
      (error (elfeed-show-next)))))

(defun +elfeed-scroll-down-command (&optional arg)
  "Scroll up or go to next feed item in Elfeed"
  (interactive "^P")
  (let ((scroll-error-top-bottom nil))
    (condition-case-unless-debug nil
        (scroll-down-command arg)
      (error (elfeed-show-prev)))))

(defun +elfeed-search-browse-generic ()
  "Browse a url with `browse-url-generic-browser'."
  (interactive)
  (elfeed-search-browse-url t))

(defun +elfeed-show-browse-generic ()
  "Browse a url with `browse-url-generic-browser'."
  (interactive)
  (elfeed-show-visit t))

;;; Fetch feeds async
;; https://github.com/skeeto/elfeed/issues/367

(defun +elfeed--update-message ()
  (message "[Elfeed] Update in progress")
  'ignore)

(defvar +elfeed--update-running nil "Whether an update is currently running.")

(defun +elfeed-update-command ()
  (interactive)
  (unless +elfeed--update-running
    (let ((script (expand-file-name "~/.local/bin/elfeed-update.el"))
          (update-message-format "[Elfeed] Background update: %s"))
      (message update-message-format "start")
      (setq +elfeed--update-running t)
      (elfeed-db-save)
      (advice-add 'elfeed :override #'+elfeed--update-message)
      (ignore-errors (kill-buffer "*elfeed-search*"))
      (ignore-errors (kill-buffer "*elfeed-log*"))
      (elfeed-db-unload)
      (unless (file-exists-p script)
        (make-directory (file-name-directory script) :parents)
        (with-temp-buffer
          (insert
           (nconcat nil
             "#!/usr/bin/env -S emacs --script"
             "(setq lexical-binding t)"
             ;; I have to load the necessary files
             "(load (locate-user-emacs-file \"early-init\"))"
             "(straight-use-package 'elfeed)"
             "(straight-use-package 'elfeed-org)"
             "(require 'elfeed)"
             "(require 'elfeed-org)"
             ;; And set needed variables
             (let ((copy-environment))
               (dolist (var '(rmh-elfeed-org-files
                              elfeed-db-directory
                              elfeed-curl-program-name
                              elfeed-use-curl
                              elfeed-curl-extra-arguments
                              elfeed-enclosure-default-dir))
                 (push (concat "(setq " (symbol-name var)
                               " '" (prin1-to-string (symbol-value var)) ")\n")
                       copy-environment))
               (nreverse copy-environment))
             ;; Overwrite log function to go to stdout
             "(defun elfeed-log (level fmt &rest objects)"
             "  (princ (format \"[%s] [%s]: %s\\n\""
             "                 (format-time-string \"%F %T\")"
             "                 level"
             "                 (apply #'format fmt objects))))"
             ;; Load elfeed
             "(elfeed-org)"
             "(elfeed-db-load)"
             "(elfeed)"
             ;; Update elfeed
             "(elfeed-update)"
             ;; Wait to finish ... I think.
             "(while (> (elfeed-queue-count-total) 0)"
             "  (sleep-for 5)"
             "  (message \"%s\" (elfeed-queue-count-total))"
             "  (accept-process-output))"
             ;; Save and garbage-collect
             "(elfeed-db-save)"
             "(elfeed-db-gc)"))
          (write-file script))
        (chmod script #o777))
      (set-process-sentinel (start-process-shell-command
                             "Elfeed" nil script)
                            (lambda (a b)
                              (advice-remove 'elfeed #'+elfeed--update-message)
                              (setq +elfeed--update-running nil)
                              (message update-message-format
                                       (string-trim b)))))))

(defvar +elfeed--update-timer nil "Timer for `elfeed-update-command'.")
(defvar +elfeed--update-first-time 6 "How long to wait for the first time.")
(defvar +elfeed--update-repeat (* 60 15) "How long between updates.")

(defun +elfeed--cancel-update-timer ()
  "Cancel `+elfeed--update-timer'."
  (unless +elfeed--update-running
    (ignore-errors (cancel-timer +elfeed--update-timer))
    (setq +elfeed--update-timer nil)))

(defun +elfeed--reinstate-update-timer ()
  "Reinstate `+elfeed--update-timer'."
  ;; First, unload the db
  (elfeed-db-save)
  (elfeed-db-unload)
  (setq +elfeed--update-timer
        (run-at-time +elfeed--update-first-time
                     +elfeed--update-repeat
                     #'+elfeed-update-command)))

(define-minor-mode +elfeed-update-async-mode
  "Minor mode to update elfeed async-style."
  :global t
  (if +elfeed-update-async-mode
      (progn                            ; enable
        (+elfeed--cancel-update-timer) ; first disable any hangers-on
        (+elfeed--reinstate-update-timer)
        (advice-add 'elfeed :before '+elfeed--cancel-update-timer)
        (advice-add 'elfeed-search-quit-window :after '+elfeed--reinstate-update-timer))
    (progn                              ; disable
      (advice-remove 'elfeed '+elfeed--cancel-update-timer)
      (advice-remove 'elfeed-search-quit-window '+elfeed--reinstate-update-timer)
      (+elfeed--cancel-update-timer))))

(provide '+elfeed)
;;; +elfeed.el ends here