feat: auto-tags seems to be done

This commit is contained in:
Pavel Korytov 2022-12-10 12:34:50 +03:00
parent d302c10be3
commit 7193b2f269

View file

@ -129,12 +129,16 @@
(const auto-tags) (const auto-tags)
(repeat :tag "Generate a tree from tags" (repeat :tag "Generate a tree from tags"
(choice (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" (cons :tag "Maximum tree level"
(const :tag "Maximum tree level" :max-level) (const :tag "Maximum tree level" :max-level)
(number :tag "Value")) (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" (cons :tag "Original tag order"
(const :tag "Original tag order" :original-order) (const :tag "Original tag order" :original-order)
(boolean :tag "Reorder tags")) (boolean :tag "Reorder tags"))
@ -214,11 +218,11 @@ Query examples:
`<auto-tags-params>' is an alist with the following keys: `<auto-tags-params>' is an alist with the following keys:
- `:max-level' - maximum level of the tree (default 2) - `:max-level' - maximum level of the tree (default 2)
- `:all-feeds' - use all feeds (by default this excludes feeds that - `:source' - which feeds to use to build the tree.
are found by queries) Can be `:misc' (default) or `(query . <query-params>)'.
- `:original-order' - do not try to build a more concise tree by - `:original-order' - do not try to build a more concise tree by
putting the most frequent tags closer to the root of the tree. 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: Available special forms:
- `:misc' - print out feeds, not found by any query above. - `:misc' - print out feeds, not found by any query above.
@ -295,6 +299,16 @@ ordering."
:group 'elfeed-summary :group 'elfeed-summary
:type 'function) :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 (defcustom elfeed-summary-refresh-on-each-update nil
"Whether to refresh the elfeed summary buffer after each update. "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))) (puthash sequence t processed-sequences)))
tree)) 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 (defun elfeed-summary--build-tree-auto-tags-recursive
(param tree feeds-by-tag-sequence unread-count total-count &optional level) (param tree feeds-by-tag-sequence unread-count total-count &optional level)
"Recursively create the auto-tags tree.
PARAM is an `<auto-tags-params>' 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 (unless level
(setq level 0)) (setq level 0))
(let ((max-level (or (alist-get :max-level (cdr param)) 2)) (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 (append
;; Just append all the feeds at the current level ;; Just append all the feeds at the current level
(cl-loop for sequence in (alist-get 'sequences tree) append (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 collect (elfeed-summary--build-tree-feed
feed unread-count total-count))) feed unread-count total-count)))
;; Go deeper if we can ;; Go deeper if we can
(when (< level max-level) (when (< level max-level)
(cl-loop (cl-loop
for (value . child-tree) in (alist-get 'children tree) collect 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) (face . ,face)
(children . ,(elfeed-summary--build-tree-auto-tags-recursive (children . ,(elfeed-summary--build-tree-auto-tags-recursive
param child-tree feeds-by-tag-sequence param child-tree feeds-by-tag-sequence
@ -679,16 +720,25 @@ The root of the tree has the value of nil."
unread-count total-count (1+ level))))))) unread-count total-count (1+ level)))))))
(defun elfeed-summary--build-tree-auto-tags (param unread-count total-count misc-feeds) (defun elfeed-summary--build-tree-auto-tags (param unread-count total-count misc-feeds)
;; TODO query, misc or all "Create the auto-tags tree.
(let ((feeds (if (alist-get :all-feeds (cdr param))
(mapcar PARAM is a cons cell `(auto-tags . <auto-tags-params>)', where
(lambda (datum) (cons (elfeed-db-get-feed (car datum)) (cdr datum))) `<auto-tags-params>' is described in `elfeed-summary-settings'.
elfeed-feeds)
(mapcar 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) (lambda (feed)
(cons feed (alist-get (elfeed-feed-id feed) elfeed-feeds (cons feed (alist-get (elfeed-feed-id feed) elfeed-feeds
nil nil #'equal))) nil nil #'equal)))
misc-feeds))) (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))))) (reorder-tags (not (alist-get :original-order (cdr param)))))
(when reorder-tags (when reorder-tags
(setq feeds (elfeed-summary--build-tree-auto-tags-reorder-tags feeds))) (setq feeds (elfeed-summary--build-tree-auto-tags-reorder-tags feeds)))
@ -730,7 +780,8 @@ The resulting form is described in `elfeed-summary--get-data'."
append (elfeed-summary--build-tree-auto-tags append (elfeed-summary--build-tree-auto-tags
param unread-count total-count misc-feeds) param unread-count total-count misc-feeds)
else if (eq param :misc) 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 collect (elfeed-summary--build-tree-feed
feed unread-count total-count)) feed unread-count total-count))
else do (error "Can't parse: %s" (prin1-to-string param)))) 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 append (elfeed-summary--extract-feeds
(cdr (assoc :elements (cdr param)))) (cdr (assoc :elements (cdr param))))
else if (and (listp param) (eq (car param) 'query)) 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 () (defun elfeed-summary--ensure ()
"Ensure that elfeed database is loaded and feeds are set up." "Ensure that elfeed database is loaded and feeds are set up."