From e9b67c28f3918b630f0c115d9e5b62577a9ef043 Mon Sep 17 00:00:00 2001 From: Andreas Gerler Date: Sun, 26 Apr 2026 19:47:45 +0200 Subject: [PATCH] update elfeed --- elpa/elfeed-20260218.1306/README-elpa | 2 + .../README.md | 0 .../elfeed-autoloads.el | 36 +-- .../elfeed-csv.el | 0 .../elfeed-curl.el | 10 +- .../elfeed-db.el | 0 .../elfeed-lib.el | 0 .../elfeed-link.el | 0 .../elfeed-log.el | 0 .../elfeed-pkg.el | 6 +- .../elfeed-search.el | 0 .../elfeed-show.el | 0 .../elfeed.el | 13 +- elpa/elfeed-20260218.1306/xml-query.el | 232 ++++++++++++++++++ 14 files changed, 268 insertions(+), 31 deletions(-) create mode 100644 elpa/elfeed-20260218.1306/README-elpa rename elpa/{elfeed-20241202.22 => elfeed-20260218.1306}/README.md (100%) rename elpa/{elfeed-20241202.22 => elfeed-20260218.1306}/elfeed-autoloads.el (83%) rename elpa/{elfeed-20241202.22 => elfeed-20260218.1306}/elfeed-csv.el (100%) rename elpa/{elfeed-20241202.22 => elfeed-20260218.1306}/elfeed-curl.el (98%) rename elpa/{elfeed-20241202.22 => elfeed-20260218.1306}/elfeed-db.el (100%) rename elpa/{elfeed-20241202.22 => elfeed-20260218.1306}/elfeed-lib.el (100%) rename elpa/{elfeed-20241202.22 => elfeed-20260218.1306}/elfeed-link.el (100%) rename elpa/{elfeed-20241202.22 => elfeed-20260218.1306}/elfeed-log.el (100%) rename elpa/{elfeed-20241202.22 => elfeed-20260218.1306}/elfeed-pkg.el (70%) rename elpa/{elfeed-20241202.22 => elfeed-20260218.1306}/elfeed-search.el (100%) rename elpa/{elfeed-20241202.22 => elfeed-20260218.1306}/elfeed-show.el (100%) rename elpa/{elfeed-20241202.22 => elfeed-20260218.1306}/elfeed.el (99%) create mode 100644 elpa/elfeed-20260218.1306/xml-query.el diff --git a/elpa/elfeed-20260218.1306/README-elpa b/elpa/elfeed-20260218.1306/README-elpa new file mode 100644 index 00000000..78fde91d --- /dev/null +++ b/elpa/elfeed-20260218.1306/README-elpa @@ -0,0 +1,2 @@ +Elfeed is a web feed client for Emacs, inspired by notmuch. See +the README for full documentation. diff --git a/elpa/elfeed-20241202.22/README.md b/elpa/elfeed-20260218.1306/README.md similarity index 100% rename from elpa/elfeed-20241202.22/README.md rename to elpa/elfeed-20260218.1306/README.md diff --git a/elpa/elfeed-20241202.22/elfeed-autoloads.el b/elpa/elfeed-20260218.1306/elfeed-autoloads.el similarity index 83% rename from elpa/elfeed-20241202.22/elfeed-autoloads.el rename to elpa/elfeed-20260218.1306/elfeed-autoloads.el index 2bb64833..30749a4f 100644 --- a/elpa/elfeed-20241202.22/elfeed-autoloads.el +++ b/elpa/elfeed-20260218.1306/elfeed-autoloads.el @@ -11,18 +11,18 @@ ;;; Generated autoloads from elfeed.el -(autoload 'elfeed-update "elfeed" "\ -Update all the feeds in `elfeed-feeds'." t) -(autoload 'elfeed "elfeed" "\ -Enter elfeed." t) -(autoload 'elfeed-load-opml "elfeed" "\ -Load feeds from an OPML file into `elfeed-feeds'. +(autoload 'elfeed-update "elfeed" +"Update all the feeds in `elfeed-feeds'." t) +(autoload 'elfeed "elfeed" +"Enter elfeed." t) +(autoload 'elfeed-load-opml "elfeed" +"Load feeds from an OPML file into `elfeed-feeds'. When called interactively, the changes to `elfeed-feeds' are saved to your customization file. (fn FILE)" t) -(autoload 'elfeed-export-opml "elfeed" "\ -Export the current feed listing to OPML-formatted FILE. +(autoload 'elfeed-export-opml "elfeed" +"Export the current feed listing to OPML-formatted FILE. (fn FILE)" t) (register-definition-prefixes "elfeed" '("elfeed-")) @@ -50,8 +50,8 @@ Export the current feed listing to OPML-formatted FILE. ;;; Generated autoloads from elfeed-link.el -(autoload 'elfeed-link-store-link "elfeed-link" "\ -Store a link to an elfeed search or entry buffer. +(autoload 'elfeed-link-store-link "elfeed-link" +"Store a link to an elfeed search or entry buffer. When storing a link to an entry, automatically extract all the entry metadata. These can be used in the capture templates as @@ -88,8 +88,8 @@ List of available keywords, when store from an Elfeed entry: If `content` type is HTML, it is automatically embedded into an Org-mode HTML quote.") -(autoload 'elfeed-link-open "elfeed-link" "\ -Jump to an elfeed entry or search. +(autoload 'elfeed-link-open "elfeed-link" +"Jump to an elfeed entry or search. Depending on what FILTER-OR-ID looks like, we jump to either search buffer or show a concrete entry. @@ -105,12 +105,12 @@ search buffer or show a concrete entry. ;;; Generated autoloads from elfeed-search.el -(autoload 'elfeed-search-bookmark-handler "elfeed-search" "\ -Jump to an elfeed-search bookmarked location. +(autoload 'elfeed-search-bookmark-handler "elfeed-search" +"Jump to an elfeed-search bookmarked location. (fn RECORD)") -(autoload 'elfeed-search-desktop-restore "elfeed-search" "\ -Restore the state of an elfeed-search buffer on desktop restore. +(autoload 'elfeed-search-desktop-restore "elfeed-search" +"Restore the state of an elfeed-search buffer on desktop restore. (fn FILE-NAME BUFFER-NAME SEARCH-FILTER)") (add-to-list 'desktop-buffer-mode-handlers '(elfeed-search-mode . elfeed-search-desktop-restore)) @@ -119,8 +119,8 @@ Restore the state of an elfeed-search buffer on desktop restore. ;;; Generated autoloads from elfeed-show.el -(autoload 'elfeed-show-bookmark-handler "elfeed-show" "\ -Show the bookmarked entry saved in the `RECORD'. +(autoload 'elfeed-show-bookmark-handler "elfeed-show" +"Show the bookmarked entry saved in the `RECORD'. (fn RECORD)") (register-definition-prefixes "elfeed-show" '("elfeed-")) diff --git a/elpa/elfeed-20241202.22/elfeed-csv.el b/elpa/elfeed-20260218.1306/elfeed-csv.el similarity index 100% rename from elpa/elfeed-20241202.22/elfeed-csv.el rename to elpa/elfeed-20260218.1306/elfeed-csv.el diff --git a/elpa/elfeed-20241202.22/elfeed-curl.el b/elpa/elfeed-20260218.1306/elfeed-curl.el similarity index 98% rename from elpa/elfeed-20241202.22/elfeed-curl.el rename to elpa/elfeed-20260218.1306/elfeed-curl.el index c8016960..4193b5b8 100644 --- a/elpa/elfeed-20241202.22/elfeed-curl.el +++ b/elpa/elfeed-20260218.1306/elfeed-curl.el @@ -468,9 +468,13 @@ in the same curl invocation." (queue-out ())) (dolist (entry queue-in) (cl-destructuring-bind (url _ headers method data) entry - (let* ((key (elfeed-curl--request-key url headers method data))) - (push key keys) - (push entry (gethash key table nil))))) + (if (listp url) + ;; Already-consolidated entry, pass through unchanged to + ;; avoid wrapping its URL list in another list layer. + (push entry queue-out) + (let* ((key (elfeed-curl--request-key url headers method data))) + (push key keys) + (push entry (gethash key table nil)))))) (dolist (key (nreverse keys)) (let ((entry (gethash key table))) (when entry diff --git a/elpa/elfeed-20241202.22/elfeed-db.el b/elpa/elfeed-20260218.1306/elfeed-db.el similarity index 100% rename from elpa/elfeed-20241202.22/elfeed-db.el rename to elpa/elfeed-20260218.1306/elfeed-db.el diff --git a/elpa/elfeed-20241202.22/elfeed-lib.el b/elpa/elfeed-20260218.1306/elfeed-lib.el similarity index 100% rename from elpa/elfeed-20241202.22/elfeed-lib.el rename to elpa/elfeed-20260218.1306/elfeed-lib.el diff --git a/elpa/elfeed-20241202.22/elfeed-link.el b/elpa/elfeed-20260218.1306/elfeed-link.el similarity index 100% rename from elpa/elfeed-20241202.22/elfeed-link.el rename to elpa/elfeed-20260218.1306/elfeed-link.el diff --git a/elpa/elfeed-20241202.22/elfeed-log.el b/elpa/elfeed-20260218.1306/elfeed-log.el similarity index 100% rename from elpa/elfeed-20241202.22/elfeed-log.el rename to elpa/elfeed-20260218.1306/elfeed-log.el diff --git a/elpa/elfeed-20241202.22/elfeed-pkg.el b/elpa/elfeed-20260218.1306/elfeed-pkg.el similarity index 70% rename from elpa/elfeed-20241202.22/elfeed-pkg.el rename to elpa/elfeed-20260218.1306/elfeed-pkg.el index 388557ad..6efd7b1f 100644 --- a/elpa/elfeed-20241202.22/elfeed-pkg.el +++ b/elpa/elfeed-20260218.1306/elfeed-pkg.el @@ -1,9 +1,9 @@ ;; -*- no-byte-compile: t; lexical-binding: nil -*- -(define-package "elfeed" "20241202.22" +(define-package "elfeed" "20260218.1306" "An Emacs Atom/RSS feed reader." '((emacs "24.3")) :url "https://github.com/skeeto/elfeed" - :commit "a39fb78e34ee25dc8baea83376f929d7c128344f" - :revdesc "a39fb78e34ee" + :commit "bbb3cac27b0412d80b327b5cfaab83683c96a2a1" + :revdesc "bbb3cac27b04" :authors '(("Christopher Wellons" . "wellons@nullprogram.com")) :maintainers '(("Christopher Wellons" . "wellons@nullprogram.com"))) diff --git a/elpa/elfeed-20241202.22/elfeed-search.el b/elpa/elfeed-20260218.1306/elfeed-search.el similarity index 100% rename from elpa/elfeed-20241202.22/elfeed-search.el rename to elpa/elfeed-20260218.1306/elfeed-search.el diff --git a/elpa/elfeed-20241202.22/elfeed-show.el b/elpa/elfeed-20260218.1306/elfeed-show.el similarity index 100% rename from elpa/elfeed-20241202.22/elfeed-show.el rename to elpa/elfeed-20260218.1306/elfeed-show.el diff --git a/elpa/elfeed-20241202.22/elfeed.el b/elpa/elfeed-20260218.1306/elfeed.el similarity index 99% rename from elpa/elfeed-20241202.22/elfeed.el rename to elpa/elfeed-20260218.1306/elfeed.el index 81ab1d66..79a7a7e0 100644 --- a/elpa/elfeed-20241202.22/elfeed.el +++ b/elpa/elfeed-20260218.1306/elfeed.el @@ -3,8 +3,8 @@ ;; This is free and unencumbered software released into the public domain. ;; Author: Christopher Wellons -;; Package-Version: 20241202.22 -;; Package-Revision: a39fb78e34ee +;; Package-Version: 20260218.1306 +;; Package-Revision: bbb3cac27b04 ;; URL: https://github.com/skeeto/elfeed ;;; Commentary: @@ -657,11 +657,10 @@ saved to your customization file." (provide 'elfeed) -(cl-eval-when (load eval) +(unless nil ;; run-time only, so don't load when compiling other files - (unless byte-compile-root-dir - (require 'elfeed-csv) - (require 'elfeed-show) - (require 'elfeed-search))) + (require 'elfeed-csv) + (require 'elfeed-show) + (require 'elfeed-search)) ;;; elfeed.el ends here diff --git a/elpa/elfeed-20260218.1306/xml-query.el b/elpa/elfeed-20260218.1306/xml-query.el new file mode 100644 index 00000000..875e5e70 --- /dev/null +++ b/elpa/elfeed-20260218.1306/xml-query.el @@ -0,0 +1,232 @@ +;; -*- lexical-binding: t; -*- +;;; xml-query.el --- query engine complimenting the xml package + +;; This is free and unencumbered software released into the public domain. + +;;; Commentary: + +;; This provides a very rudimentary, jQuery-like, XML selector +;; s-expression language. It operates on the output of the xml +;; package, such as `xml-parse-region' and `xml-parse-file'. It was +;; written to support Elfeed. + +;; See the docstring for `xml-query-all'. + +;; The macro forms, `xml-query*' and `xml-query-all*', are an order of +;; magnitude faster, but only work on static selectors and need the +;; namespaces to be pre-stripped. + +;; Examples: + +;; This query grabs the top-level paragraph content from XHTML. + +;; (xml-query-all '(html body p *) xhtml) + +;; This query extracts all the links from an Atom feed. + +;; (xml-query-all '(feed entry link [rel "alternate"] :href) xml) + +;;; Code: + +(require 'cl-lib) + +(defun xml-query-strip-ns (tag) + "Remove the namespace, if any, from TAG." + (when (symbolp tag) + (let ((name (symbol-name tag))) + (if (cl-find ?\: name) + (intern (replace-regexp-in-string "^.+:" "" name)) + tag)))) + +(defun xml-query--tag-all (match xml) + (cl-loop for (tag attribs . content) in (cl-remove-if-not #'listp xml) + when (or (eq tag match) (eq (xml-query-strip-ns tag) match)) + collect (cons tag (cons attribs content)))) + +(defun xml-query--attrib-all (attrib value xml) + (cl-loop for (tag attribs . content) in (cl-remove-if-not #'listp xml) + when (equal (cdr (assoc attrib attribs)) value) + collect (cons tag (cons attribs content)))) + +(defun xml-query--keyword (matcher xml) + (cl-loop with match = (intern (substring (symbol-name matcher) 1)) + for (tag attribs . content) in (cl-remove-if-not #'listp xml) + when (cdr (assoc match attribs)) + collect it)) + +(defun xml-query--symbol (matcher xml) + (xml-query--tag-all matcher xml)) + +(defun xml-query--vector (matcher xml) + (let ((attrib (aref matcher 0)) + (value (aref matcher 1))) + (xml-query--attrib-all attrib value xml))) + +(defun xml-query--list (matchers xml) + (cl-loop for matcher in matchers + append (xml-query-all (if (listp matcher) + matcher + (list matcher)) xml))) + +(defun xml-query--append (xml) + (cl-loop for (tag attribs . content) in (cl-remove-if-not #'listp xml) + append content)) + +(defun xml-query--stringp (thing) + "Return non-nil of THING is a non-blank string." + (and (stringp thing) (string-match "[^ \t\r\n]" thing))) + +(defun xml-query-all (query xml) + "Given a list of tags, XML, apply QUERY and return a list of +matching tags. + +A query is a list of matchers. + - SYMBOL: filters to matching tags + - LIST: each element is a full sub-query, whose results are concatenated + - VECTOR: filters to tags with matching attribute, [tag attrib value] + - KEYWORD: filters to an attribute value (must be last) + - * (an asterisk symbol): filters to content strings (must be last) + +For example, to find all the \"alternate\" link URL in a typical +Atom feed: + + (xml-query-all \\='(feed entry link [rel \"alternate\"] :href) xml)" + (if (null query) + xml + (cl-destructuring-bind (matcher . rest) query + (cond + ((keywordp matcher) (xml-query--keyword matcher xml)) + ((eq matcher '*) + (cl-remove-if-not #'xml-query--stringp (xml-query--append xml))) + (:else + (let ((matches + (cl-etypecase matcher + (symbol (xml-query--symbol matcher xml)) + (vector (xml-query--vector matcher xml)) + (list (xml-query--list matcher xml))))) + (cond + ((null rest) matches) + ((and (or (symbolp (car rest)) + (listp (car rest))) + (not (keywordp (car rest))) + (not (eq '* (car rest)))) + (xml-query-all (cdr query) (xml-query--append matches))) + (:else (xml-query-all rest matches))))))))) + +(defun xml-query (query xml) + "Like `xml-query-all' but only return the first result." + (let ((result (xml-query-all query xml))) + (if (xml-query--stringp result) + result + (car (xml-query-all query xml))))) + +;; Macro alternatives: + +;; This is a slightly less capable alternative with significantly +;; better performance (x10 speedup) that requires a static selector. +;; The selector is compiled into Lisp code via macro at compile-time, +;; which is then carried through to byte-code by the compiler. In +;; byte-code form, the macro performs no function calls other than +;; `throw' in the case of `xml-query*', where it's invoked less than +;; once per evaluation (only on success). + +;; Queries are compiled tail-to-head with a result handler at the +;; deepest level. The generated code makes multiple bindings of the +;; variable "v" as it dives deeper into the query, using the layers of +;; bindings as a breadcrumb stack. + +;; For `xml-query*', which has a single result, the whole expression +;; is wrapped in a catch, and the first successful match is thrown to +;; it from the result handler. + +;; For `xml-query-all*', the result is pushed into an output list. + +(defun xml-query--compile-tag (tag subexp subloop-p) + `(when (and (consp v) (eq (car v) ',tag)) + ,(if subloop-p + `(dolist (v (cddr v)) + ,subexp) + subexp))) + +(defun xml-query--compile-attrib (pair subexp subloop-p) + `(let ((value (cdr (assq ',(aref pair 0) (cadr v))))) + (when (equal value ,(aref pair 1)) + ,(if subloop-p + `(dolist (v (cddr v)) + ,subexp) + subexp)))) + +(defun xml-query--compile-keyword (keyword subexp) + (let ((attrib (intern (substring (symbol-name keyword) 1)))) + `(let ((v (cdr (assq ',attrib (cadr v))))) + (when v + ,subexp)))) + +(defun xml-query--compile-star (subexp) + `(when (and (stringp v) (string-match "[^ \t\r\n]" v)) + ,subexp)) + +(defun xml-query--compile-top (query input subexp) + (let* ((rquery (reverse query)) + (prev nil)) + (while rquery + (let ((matcher (pop rquery)) + ;; Should the next item loop over its children? + (subloop-p (and (not (null prev)) + (not (keywordp prev)) + (symbolp prev)))) + (cond + ((eq '* matcher) + (setf subexp (xml-query--compile-star subexp))) + ((keywordp matcher) + (setf subexp (xml-query--compile-keyword matcher subexp))) + ((symbolp matcher) + (setf subexp (xml-query--compile-tag matcher subexp subloop-p))) + ((vectorp matcher) + (setf subexp (xml-query--compile-attrib matcher subexp subloop-p))) + ((error "Bad query: %S" query))) + (setf prev matcher))) + `(dolist (v ,input) + ,subexp))) + +(defun xml-query--compile (query input) + (let ((tag (make-symbol "done"))) + `(catch ',tag + ,(xml-query--compile-top query input `(throw ',tag v))))) + +(defmacro xml-query* (query sexp) + "Like `xml-query' but generate code to execute QUERY on SEXP. + +Unlike `xml-query', QUERY must be a static, compile-time +s-expression. See `xml-query-all*' for more information. + +QUERY is *not* evaluated, so it should not be quoted." + (xml-query--compile query sexp)) + +(defun xml-query-all--compile (query input) + (let ((output (make-symbol "output"))) + `(let ((,output ())) + ,(xml-query--compile-top query input `(push v ,output)) + (nreverse ,output)))) + +(defmacro xml-query-all* (query sexp) + "Like `xml-query-all' but generate code to execute QUERY on SEXP. + +Unlike `xml-query-all', QUERY must be a static, compile-time +s-expression. This macro compiles the query into actual code. The +result is faster since the query will be compiled into byte-code +rather than \"interpreted\" at run time. + +Also unlike `xml-query-all', the parsed XML s-expression must +also have its namespace pre-stripped. This is accomplished by +setting the optional PARSE-NS argument of `xml-parse-region' to +symbol-qnames. + +Sub-expression lists are not supported by this macro. + +QUERY is *not* evaluated, so it should not be quoted." + (xml-query-all--compile query sexp)) + +(provide 'xml-query) + +;;; xml-query.el ends here -- 2.47.3