;;; +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-message-format "[Elfeed] Updating in the background...%s")) (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" ;; 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