From 7193b2f2699ae88ce4a3300b7b9c0e993b000444 Mon Sep 17 00:00:00 2001 From: SqrtMinusOne Date: Sat, 10 Dec 2022 12:34:50 +0300 Subject: [PATCH] feat: auto-tags seems to be done --- elfeed-summary.el | 98 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 77 insertions(+), 21 deletions(-) diff --git a/elfeed-summary.el b/elfeed-summary.el index b4741b7..a8b0b0e 100644 --- a/elfeed-summary.el +++ b/elfeed-summary.el @@ -129,12 +129,16 @@ (const auto-tags) (repeat :tag "Generate a tree from tags" (choice + (cons :tag "Source" + (const :tag "Source" :source) + (choice + (cons :tag "Query" + (const query) + elfeed-summary-query) + (const :tag "Misc feeds" :misc))) (cons :tag "Maximum tree level" (const :tag "Maximum tree level" :max-level) (number :tag "Value")) - (cons :tag "Use all feeds" - (const :tag "Use all feeds" :all-feeds) - (boolean :tag "Use all feeds")) (cons :tag "Original tag order" (const :tag "Original tag order" :original-order) (boolean :tag "Reorder tags")) @@ -214,11 +218,11 @@ Query examples: `' is an alist with the following keys: - `:max-level' - maximum level of the tree (default 2) -- `:all-feeds' - use all feeds (by default this excludes feeds that - are found by queries) +- `:source' - which feeds to use to build the tree. + Can be `:misc' (default) or `(query . )'. - `:original-order' - do not try to build a more concise tree by putting the most frequent tags closer to the root of the tree. -- `:Faces' - list of faces for groups. +- `:faces' - list of faces for groups. Available special forms: - `:misc' - print out feeds, not found by any query above. @@ -295,6 +299,16 @@ ordering." :group 'elfeed-summary :type 'function) +(defcustom elfeed-summary-auto-tags-group-title-fn + #'elfeed-summary--auto-tags-group-title + "Function to get the title of an autogenerated group. + +Accepts the only parameter, which is a tree node created by +`elfeed-summary--arrange-sequences-in-tree'. + +See `elfeed-summary--auto-tags-group-title' for the default +implementation.") + (defcustom elfeed-summary-refresh-on-each-update nil "Whether to refresh the elfeed summary buffer after each update. @@ -648,8 +662,31 @@ The root of the tree has the value of nil." (puthash sequence t processed-sequences))) tree)) +(defun elfeed-summary--auto-tags-group-title (child-tree) + "Default function to get the name of an auto-tags group. + +CHILD-TREE is a structure as defined in +`elfeed-summary--arrange-sequences-in-tree', with tag lists as +sequences." + (symbol-name (alist-get 'value child-tree))) + (defun elfeed-summary--build-tree-auto-tags-recursive (param tree feeds-by-tag-sequence unread-count total-count &optional level) + "Recursively create the auto-tags tree. + +PARAM is an `' form as described in +`elfeed-summary-settings'. TREE is the result of applying +`elfeed-summary--arrange-sequences-in-tree' onto the list of tags of +all feeds. + +FEEDS-BY-TAG-SEQUENCE is a hashmap with lists of tags as keys and +instances of `elfeed-feed' as values. This is used to figure out +feeds in a particular TREE node. + +UNREAD-COUNT and TOTAL-COUNT are hashmaps with feed ids as keys and +corresponding numbers of entries as values. + +LEVEL is the current level of recursion, which is 0 by default." (unless level (setq level 0)) (let ((max-level (or (alist-get :max-level (cdr param)) 2)) @@ -658,14 +695,18 @@ The root of the tree has the value of nil." (append ;; Just append all the feeds at the current level (cl-loop for sequence in (alist-get 'sequences tree) append - (cl-loop for feed in (gethash sequence feeds-by-tag-sequence) + (cl-loop for feed in (seq-sort + #'elfeed-summary--feed-sort-fn + (gethash sequence feeds-by-tag-sequence)) collect (elfeed-summary--build-tree-feed feed unread-count total-count))) ;; Go deeper if we can (when (< level max-level) (cl-loop for (value . child-tree) in (alist-get 'children tree) collect - `(group . ((params . ((:title . ,(prin1-to-string value)))) + `(group . ((params . ((:title + . ,(funcall elfeed-summary-auto-tags-group-title-fn + child-tree)))) (face . ,face) (children . ,(elfeed-summary--build-tree-auto-tags-recursive param child-tree feeds-by-tag-sequence @@ -679,17 +720,26 @@ The root of the tree has the value of nil." unread-count total-count (1+ level))))))) (defun elfeed-summary--build-tree-auto-tags (param unread-count total-count misc-feeds) - ;; TODO query, misc or all - (let ((feeds (if (alist-get :all-feeds (cdr param)) - (mapcar - (lambda (datum) (cons (elfeed-db-get-feed (car datum)) (cdr datum))) - elfeed-feeds) - (mapcar - (lambda (feed) - (cons feed (alist-get (elfeed-feed-id feed) elfeed-feeds - nil nil #'equal))) - misc-feeds))) - (reorder-tags (not (alist-get :original-order (cdr param))))) + "Create the auto-tags tree. + +PARAM is a cons cell `(auto-tags . )', where +`' is described in `elfeed-summary-settings'. + +UNREAD-COUNT and TOTAL-COUNT are hashmaps with feed ids as keys and +corresponding numbers of entries as values. + +MISC-FEEDS is a list of feeds that were not used in PARAMS." + (let* ((source (alist-get :source (cdr param))) + (feeds (mapcar + (lambda (feed) + (cons feed (alist-get (elfeed-feed-id feed) elfeed-feeds + nil nil #'equal))) + (cond ((or (eq source :misc) (null source)) + misc-feeds) + ((and (listp source) (eq (car source) 'query)) + (elfeed-summary--get-feeds (cdr source))) + (t (error "Invalid auto-tags source: %s" source))))) + (reorder-tags (not (alist-get :original-order (cdr param))))) (when reorder-tags (setq feeds (elfeed-summary--build-tree-auto-tags-reorder-tags feeds))) (let ((tree (elfeed-summary--arrange-sequences-in-tree @@ -730,7 +780,8 @@ The resulting form is described in `elfeed-summary--get-data'." append (elfeed-summary--build-tree-auto-tags param unread-count total-count misc-feeds) else if (eq param :misc) - append (cl-loop for feed in misc-feeds + append (cl-loop for feed in (seq-sort #'elfeed-summary--feed-sort-fn + misc-feeds) collect (elfeed-summary--build-tree-feed feed unread-count total-count)) else do (error "Can't parse: %s" (prin1-to-string param)))) @@ -744,7 +795,12 @@ PARAMS is a form as described in `elfeed-summary-settings'." append (elfeed-summary--extract-feeds (cdr (assoc :elements (cdr param)))) else if (and (listp param) (eq (car param) 'query)) - append (elfeed-summary--get-feeds (cdr param)))) + append (elfeed-summary--get-feeds (cdr param)) + else if (and (listp param) (eq (car param) 'auto-tags) + (eq (car-safe (alist-get :source (cdr param))) + 'query)) + append (elfeed-summary--get-feeds + (cdr (alist-get :source (cdr param)))))) (defun elfeed-summary--ensure () "Ensure that elfeed database is loaded and feeds are set up."