aboutsummaryrefslogtreecommitdiff
path: root/modules/elfeed-config.el
diff options
context:
space:
mode:
Diffstat (limited to 'modules/elfeed-config.el')
-rw-r--r--modules/elfeed-config.el71
1 files changed, 43 insertions, 28 deletions
diff --git a/modules/elfeed-config.el b/modules/elfeed-config.el
index ad7bda83a..7b4d7d745 100644
--- a/modules/elfeed-config.el
+++ b/modules/elfeed-config.el
@@ -29,21 +29,26 @@
(require 'system-lib)
(require 'media-utils)
+(declare-function elfeed "elfeed")
+(declare-function elfeed-update "elfeed")
+(declare-function elfeed-entry-link "elfeed")
+(declare-function elfeed-untag "elfeed")
+(declare-function elfeed-search-selected "elfeed")
+(declare-function elfeed-search-tag-all "elfeed")
+(declare-function elfeed-search-update-entry "elfeed")
+(declare-function elfeed-search-update--force "elfeed")
+(declare-function elfeed-search-untag-all-unread "elfeed")
+(declare-function eww-browse-url "eww")
+(declare-function eww-readable "eww")
+
;; ------------------------------- Elfeed Config -------------------------------
(use-package elfeed
:bind
- ("M-S-r" . cj/elfeed-open) ;; was M-R
(:map elfeed-show-mode-map
("w" . eww-open-in-new-buffer))
(:map elfeed-search-mode-map
- ("w" . cj/elfeed-eww-open) ;; opens in eww
- ("b" . cj/elfeed-browser-open) ;; opens in external browser
- ("d" . cj/elfeed-youtube-dl) ;; async download with yt-dlp and tsp
- ("v" . cj/play-with-video-player)) ;; async play with mpv
- ("V" . cj/select-media-player) ;; Capital V to select player
- ("R" . cj/elfeed-mark-all-as-read) ;; capital marks all as read, since upper case marks one as read
- ("U" . cj/elfeed-mark-all-as-unread) ;; capital marks all as unread, since lower case marks one as unread
+ ("V" . cj/select-media-player)) ;; Capital V to select player
:config
(setq elfeed-db-directory (concat user-emacs-directory ".elfeed-db"))
(setq-default elfeed-search-title-max-width 150)
@@ -90,19 +95,22 @@
(elfeed)
(elfeed-update)
(elfeed-search-update--force))
+(keymap-global-set "M-S-r" #'cj/elfeed-open) ;; was M-R
;; -------------------------- Elfeed Filter Functions --------------------------
(defun cj/elfeed-mark-all-as-read ()
"Remove the \='unread\=' tag from all visible entries in search buffer."
(interactive)
- (mark-whole-buffer)
+ (goto-char (point-min))
+ (push-mark (point-max) nil t)
(elfeed-search-untag-all-unread))
(defun cj/elfeed-mark-all-as-unread ()
"Add the \='unread\=' tag from all visible entries in the search buffer."
(interactive)
- (mark-whole-buffer)
+ (goto-char (point-min))
+ (push-mark (point-max) nil t)
(elfeed-search-tag-all 'unread))
(defun cj/elfeed-set-filter-and-update (filterstring)
@@ -126,23 +134,13 @@ Returns the stream URL or nil on failure."
(cmd-args (append '("yt-dlp" "-q" "-g")
format-args
(list url)))
- ;; DEBUG: Log the command
- (_ (cj/log-silently "DEBUG: Extracting with command: %s"
- (mapconcat #'shell-quote-argument cmd-args " ")))
(output (with-temp-buffer
(let ((exit-code (apply #'call-process
(car cmd-args) nil t nil
(cdr cmd-args))))
(if (zerop exit-code)
(string-trim (buffer-string))
- (progn
- ;; DEBUG: Log failure
- (cj/log-silently "DEBUG: yt-dlp failed with exit code %d" exit-code)
- (cj/log-silently "DEBUG: Error output: %s" (buffer-string))
- nil))))))
- ;; DEBUG: Log the result
- (cj/log-silently "DEBUG: Extracted URL: %s"
- (if output (truncate-string-to-width output 100) "nil"))
+ nil)))))
(when (and output (string-match-p "^https?://" output))
output)))
@@ -223,6 +221,15 @@ Note: Function name kept for backwards compatibility."
"Seconds to wait for a synchronous YouTube page fetch before giving up.
Without a timeout a hung request would block Emacs indefinitely.")
+(defun cj/--decode-html-entities (text)
+ "Decode the common HTML entities in TEXT.
+Handles & < > " ' and ' -- the entities YouTube's
+og:title meta tag emits. Decoded left-to-right, & first."
+ (let ((entities '(("&amp;" . "&") ("&lt;" . "<") ("&gt;" . ">")
+ ("&quot;" . "\"") ("&#39;" . "'") ("&#x27;" . "'"))))
+ (dolist (pair entities text)
+ (setq text (replace-regexp-in-string (car pair) (cdr pair) text)))))
+
(defun cj/youtube-to-elfeed-feed-format (url type)
"Convert YouTube URL to elfeed-feeds format.
@@ -274,13 +281,8 @@ TYPE should be either \='channel or \='playlist."
(goto-char (point-min))
(when (re-search-forward "<meta property=\"og:title\" content=\"\\([^\"]+\\)\"" nil t)
(setq title (match-string 1))
- ;; Simple HTML entity decoding
- (setq title (replace-regexp-in-string "&amp;" "&" title))
- (setq title (replace-regexp-in-string "&lt;" "<" title))
- (setq title (replace-regexp-in-string "&gt;" ">" title))
- (setq title (replace-regexp-in-string "&quot;" "\"" title))
- (setq title (replace-regexp-in-string "&#39;" "'" title))
- (setq title (replace-regexp-in-string "&#x27;" "'" title))))))
+ ;; Decode HTML entities in the extracted title
+ (setq title (cj/--decode-html-entities title))))))
;; Always kill the temporary URL buffer, even when extraction failed --
;; the old code only killed it when an ID was found, leaking it otherwise.
(when (buffer-live-p buffer)
@@ -308,5 +310,18 @@ TYPE should be either \='channel or \='playlist."
(insert result))
result))
+;; --------------------------- Search-Mode Keybindings -------------------------
+;; Bound here (not in use-package :bind) because these commands are defined in
+;; this file; a :bind autoload stub plus the defun triggers a "defined multiple
+;; times" byte-compile warning.
+
+(with-eval-after-load 'elfeed
+ (keymap-set elfeed-search-mode-map "w" #'cj/elfeed-eww-open) ;; opens in eww
+ (keymap-set elfeed-search-mode-map "b" #'cj/elfeed-browser-open) ;; opens in external browser
+ (keymap-set elfeed-search-mode-map "d" #'cj/elfeed-youtube-dl) ;; async download with yt-dlp and tsp
+ (keymap-set elfeed-search-mode-map "v" #'cj/play-with-video-player) ;; async play with mpv
+ (keymap-set elfeed-search-mode-map "R" #'cj/elfeed-mark-all-as-read) ;; capital R marks all read (lower case marks one)
+ (keymap-set elfeed-search-mode-map "U" #'cj/elfeed-mark-all-as-unread)) ;; capital U marks all unread (lower case marks one)
+
(provide 'elfeed-config)
;;; elfeed-config.el ends here.