summary refs log tree commit diff stats
path: root/lisp/+elfeed.el
blob: 4a874c3e5882849ab891049b711614641c74d5c2 (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
;;; +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)
  (let ((script (expand-file-name "~/.local/bin/elfeed-update.el")))
    (message "[Elfeed] Updating in the background.")
    (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"
           ;; 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
           `("(setq rmh-elfeed-org-files '("
             ,(mapconcat (lambda (el)
                           (format "\"%s\"" el))
                         rmh-elfeed-org-files
                         " ")
             "))")
           ;; 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 "[Elfeed] Background update %s."
                                     (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'."
  (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 every 15 minutes."
  :global t
  (if +elfeed-update-async-mode
      (progn                            ; enable
        (+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