emacs/lisp/+elfeed.el

134 lines
5.0 KiB
EmacsLisp

;;; +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"))
(update-message-format "[Elfeed] Updating in the background..."))
(with-temp-message update-message-format
(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
`("(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 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'."
(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