mirror of
https://github.com/SqrtMinusOne/elfeed-summary.git
synced 2025-12-11 18:13:03 +03:00
feat: looks like final version of rendering
This commit is contained in:
parent
0b40a84357
commit
f8bfe194fc
1 changed files with 135 additions and 40 deletions
|
|
@ -83,14 +83,12 @@
|
||||||
(cons
|
(cons
|
||||||
(const :tag "Title" :title)
|
(const :tag "Title" :title)
|
||||||
(string :tag "Title"))
|
(string :tag "Title"))
|
||||||
(cons
|
|
||||||
(const :tag "Sort function" :sort-fn)
|
|
||||||
(choice
|
|
||||||
function
|
|
||||||
(const :tag "None" nil)))
|
|
||||||
(cons
|
(cons
|
||||||
(const :tag "Face" :face)
|
(const :tag "Face" :face)
|
||||||
(face :tag "Face"))
|
(face :tag "Face"))
|
||||||
|
(cons
|
||||||
|
(const :tag "Hide" :hide)
|
||||||
|
(boleean :tag "Hide"))
|
||||||
(cons
|
(cons
|
||||||
(const :tag "Elements" :elements)
|
(const :tag "Elements" :elements)
|
||||||
elfeed-summary-setting-elements))))
|
elfeed-summary-setting-elements))))
|
||||||
|
|
@ -118,7 +116,6 @@
|
||||||
|
|
||||||
(defcustom elfeed-summary-settings
|
(defcustom elfeed-summary-settings
|
||||||
'((group (:title . "All feeds")
|
'((group (:title . "All feeds")
|
||||||
(:sort-fn . string-lessp)
|
|
||||||
(:elements (query . :all)))
|
(:elements (query . :all)))
|
||||||
(group (:title . "Searches")
|
(group (:title . "Searches")
|
||||||
(:elements (search
|
(:elements (search
|
||||||
|
|
@ -142,9 +139,10 @@ This is a list of these possible items:
|
||||||
`<group-params>' is an alist with the following keys:
|
`<group-params>' is an alist with the following keys:
|
||||||
- `:title' (mandatory)
|
- `:title' (mandatory)
|
||||||
- `:elements' (mandatory) - also a list of groups and queries
|
- `:elements' (mandatory) - also a list of groups and queries
|
||||||
- `:sort-fn' - function used to sort titles of feeds, found by queries
|
queries
|
||||||
in `:elements'. E.g. `string-greaterp' for alphabetical order.
|
in `:elements'. E.g. `string-greaterp' for alphabetical order.
|
||||||
- `:face' - group face. The default face if `elfeed-summary-group-face'.
|
- `:face' - group face. The default face if `elfeed-summary-group-face'.
|
||||||
|
- `:hide' - if non-nil, collapse by default.
|
||||||
|
|
||||||
`<query-params>' can be:
|
`<query-params>' can be:
|
||||||
- A symbol of a tag.
|
- A symbol of a tag.
|
||||||
|
|
@ -208,8 +206,9 @@ The default implementation, `elfeed-summary--feed-face-fn', calls
|
||||||
(defcustom elfeed-summary-search-face-fn #'elfeed-summary--search-face-fn
|
(defcustom elfeed-summary-search-face-fn #'elfeed-summary--search-face-fn
|
||||||
"Function to get the face of the search.
|
"Function to get the face of the search.
|
||||||
|
|
||||||
Accepts two-arguments:
|
Accepts the following arguments:
|
||||||
- `<search-params>', as described in `elfeed-summary-settings'.
|
- `<search-params>', as described in `elfeed-summary-settings'.
|
||||||
|
- The number of found unread items.
|
||||||
- The number of found items.
|
- The number of found items.
|
||||||
|
|
||||||
The default implementation, `elfeed-summary--search-face-fn', calls
|
The default implementation, `elfeed-summary--search-face-fn', calls
|
||||||
|
|
@ -219,6 +218,13 @@ greater than zero."
|
||||||
:group 'elfeed-summary
|
:group 'elfeed-summary
|
||||||
:type 'function)
|
:type 'function)
|
||||||
|
|
||||||
|
(defcustom elfeed-summary-feed-sort-fn #'elfeed-summary--feed-sort-fn
|
||||||
|
"Function to sort feeds in query.
|
||||||
|
|
||||||
|
Receives TODO"
|
||||||
|
:group 'elfeed-summary
|
||||||
|
:type 'function)
|
||||||
|
|
||||||
(defconst elfeed-summary-buffer "*elfeed-summary*"
|
(defconst elfeed-summary-buffer "*elfeed-summary*"
|
||||||
"Elfeed summary buffer name")
|
"Elfeed summary buffer name")
|
||||||
|
|
||||||
|
|
@ -227,6 +233,16 @@ greater than zero."
|
||||||
"Default face for the elfeed-summary group."
|
"Default face for the elfeed-summary group."
|
||||||
:group 'elfeed-summary)
|
:group 'elfeed-summary)
|
||||||
|
|
||||||
|
(defface elfeed-summary-count-face
|
||||||
|
'((t (:inherit elfeed-search-title-face)))
|
||||||
|
"Face for the number of entries of a read feed or search"
|
||||||
|
:group 'elfeed-summary)
|
||||||
|
|
||||||
|
(defface elfeed-summary-count-face-unread
|
||||||
|
'((t (:inherit elfeed-search-unread-title-face)))
|
||||||
|
"Face for the number of entries of an unread feed or search"
|
||||||
|
:group 'elfeed-summary)
|
||||||
|
|
||||||
;;; Logic
|
;;; Logic
|
||||||
(cl-defun elfeed-summary--match-tag (query &key tags title url author title-meta)
|
(cl-defun elfeed-summary--match-tag (query &key tags title url author title-meta)
|
||||||
"Check if attributes of elfeed feed match QUERY.
|
"Check if attributes of elfeed feed match QUERY.
|
||||||
|
|
@ -310,22 +326,36 @@ and TITLE-META are attributes of the `elfeed-db-feed'."
|
||||||
(cdr query)
|
(cdr query)
|
||||||
query)))))
|
query)))))
|
||||||
|
|
||||||
|
(defun elfeed-summary--feed-sort-fn (feed-1 feed-2)
|
||||||
|
"TODO"
|
||||||
|
(string-lessp
|
||||||
|
(downcase
|
||||||
|
(or (plist-get (elfeed-feed-meta feed-1) :title)
|
||||||
|
(elfeed-feed-title feed-1)
|
||||||
|
(elfeed-feed-id feed-1)))
|
||||||
|
(downcase
|
||||||
|
(or (plist-get (elfeed-feed-meta feed-2) :title)
|
||||||
|
(elfeed-feed-title feed-2)
|
||||||
|
(elfeed-feed-id feed-2)))))
|
||||||
|
|
||||||
(defun elfeed-summary--get-feeds (query)
|
(defun elfeed-summary--get-feeds (query)
|
||||||
"Get elfeed feeds that match QUERY.
|
"Get elfeed feeds that match QUERY.
|
||||||
|
|
||||||
QUERY is described in `elfeed-summary-settings'."
|
QUERY is described in `elfeed-summary-settings'."
|
||||||
(cl-loop for feed in elfeed-feeds
|
(seq-sort
|
||||||
for url = (car feed)
|
elfeed-summary-feed-sort-fn
|
||||||
for tags = (cdr feed)
|
(cl-loop for feed in elfeed-feeds
|
||||||
for feed = (elfeed-db-get-feed url)
|
for url = (car feed)
|
||||||
if (elfeed-summary--match-tag
|
for tags = (cdr feed)
|
||||||
query
|
for feed = (elfeed-db-get-feed url)
|
||||||
:tags tags
|
if (elfeed-summary--match-tag
|
||||||
:title (elfeed-feed-title feed)
|
query
|
||||||
:title-meta (plist-get (elfeed-feed-meta feed) :title)
|
:tags tags
|
||||||
:url url
|
:title (elfeed-feed-title feed)
|
||||||
:author (plist-get (car (elfeed-feed-author feed)) :name))
|
:title-meta (plist-get (elfeed-feed-meta feed) :title)
|
||||||
collect feed))
|
:url url
|
||||||
|
:author (plist-get (car (elfeed-feed-author feed)) :name))
|
||||||
|
collect feed)))
|
||||||
|
|
||||||
(defun elfeed-summary--extract-feeds (params)
|
(defun elfeed-summary--extract-feeds (params)
|
||||||
(cl-loop for param in params
|
(cl-loop for param in params
|
||||||
|
|
@ -351,10 +381,10 @@ QUERY is described in `elfeed-summary-settings'."
|
||||||
(faces . ,(funcall elfeed-summary-feed-face-fn feed all-tags))
|
(faces . ,(funcall elfeed-summary-feed-face-fn feed all-tags))
|
||||||
(tags . ,all-tags)))))
|
(tags . ,all-tags)))))
|
||||||
|
|
||||||
(defun elfeed-summary--search-face-fn (search count)
|
(defun elfeed-summary--search-face-fn (search unread _total)
|
||||||
(let ((tags (append
|
(let ((tags (append
|
||||||
(alist-get :tags search)
|
(alist-get :tags search)
|
||||||
(when (< 0 count)
|
(when (< 0 unread)
|
||||||
'(unread)))))
|
'(unread)))))
|
||||||
(elfeed-search--faces tags)))
|
(elfeed-search--faces tags)))
|
||||||
|
|
||||||
|
|
@ -365,7 +395,8 @@ Implented the same way as `elfeed-search--update-list'."
|
||||||
(let* ((filter (elfeed-search-parse-filter (alist-get :filter search)))
|
(let* ((filter (elfeed-search-parse-filter (alist-get :filter search)))
|
||||||
(head (list nil))
|
(head (list nil))
|
||||||
(tail head)
|
(tail head)
|
||||||
(count 0))
|
(unread 0)
|
||||||
|
(total 0))
|
||||||
(if elfeed-search-compile-filter
|
(if elfeed-search-compile-filter
|
||||||
;; Force lexical bindings regardless of the current
|
;; Force lexical bindings regardless of the current
|
||||||
;; buffer-local value. Lexical scope uses the faster
|
;; buffer-local value. Lexical scope uses the faster
|
||||||
|
|
@ -373,18 +404,24 @@ Implented the same way as `elfeed-search--update-list'."
|
||||||
(let ((lexical-binding t)
|
(let ((lexical-binding t)
|
||||||
(func (byte-compile (elfeed-search-compile-filter filter))))
|
(func (byte-compile (elfeed-search-compile-filter filter))))
|
||||||
(with-elfeed-db-visit (entry feed)
|
(with-elfeed-db-visit (entry feed)
|
||||||
(when (funcall func entry feed count)
|
(when (funcall func entry feed total)
|
||||||
(setf (cdr tail) (list entry)
|
(setf (cdr tail) (list entry)
|
||||||
tail (cdr tail)
|
tail (cdr tail)
|
||||||
count (1+ count)))))
|
total (1+ total))
|
||||||
|
(when (member elfeed-summary-unread-tag (elfeed-entry-tags entry))
|
||||||
|
(setq unread (1+ unread))))))
|
||||||
(with-elfeed-db-visit (entry feed)
|
(with-elfeed-db-visit (entry feed)
|
||||||
(when (elfeed-search-filter filter entry feed count)
|
(when (elfeed-search-filter filter entry feed total)
|
||||||
(setf (cdr tail) (list entry)
|
(setf (cdr tail) (list entry)
|
||||||
tail (cdr tail)
|
tail (cdr tail)
|
||||||
count (1+ count)))))
|
total (1+ total))
|
||||||
|
(when (member elfeed-summary-unread-tag (elfeed-entry-tags entry))
|
||||||
|
(setq unread (1+ unread))))))
|
||||||
`(search . ((params . ,(cdr search))
|
`(search . ((params . ,(cdr search))
|
||||||
(faces . ,(funcall elfeed-summary-search-face-fn (cdr search) count))
|
(faces . ,(funcall elfeed-summary-search-face-fn
|
||||||
(count . ,count)))))
|
(cdr search) unread total))
|
||||||
|
(unread . ,unread)
|
||||||
|
(total . ,total)))))
|
||||||
|
|
||||||
(defun elfeed-summary--build-tree (params unread-count total-count misc-feeds)
|
(defun elfeed-summary--build-tree (params unread-count total-count misc-feeds)
|
||||||
(cl-loop for param in params
|
(cl-loop for param in params
|
||||||
|
|
@ -438,6 +475,12 @@ Implented the same way as `elfeed-search--update-list'."
|
||||||
(defvar-local elfeed-summary--tree nil
|
(defvar-local elfeed-summary--tree nil
|
||||||
"TODO")
|
"TODO")
|
||||||
|
|
||||||
|
(defvar elfeed-summary--unread-padding 3
|
||||||
|
"TODO")
|
||||||
|
|
||||||
|
(defvar elfeed-summary--total-padding 3
|
||||||
|
"TODO")
|
||||||
|
|
||||||
(defvar elfeed-summary-mode-map
|
(defvar elfeed-summary-mode-map
|
||||||
(let ((map (make-sparse-keymap)))
|
(let ((map (make-sparse-keymap)))
|
||||||
(set-keymap-parent map magit-section-mode-map)
|
(set-keymap-parent map magit-section-mode-map)
|
||||||
|
|
@ -466,25 +509,52 @@ Implented the same way as `elfeed-search--update-list'."
|
||||||
(let* ((feed (alist-get 'feed data))
|
(let* ((feed (alist-get 'feed data))
|
||||||
(title (or (plist-get (elfeed-feed-meta feed) :title)
|
(title (or (plist-get (elfeed-feed-meta feed) :title)
|
||||||
(elfeed-feed-title feed)
|
(elfeed-feed-title feed)
|
||||||
(elfeed-feed-id feed))))
|
(elfeed-feed-id feed)))
|
||||||
(insert (propertize title 'face (alist-get 'faces data)))
|
(text (concat
|
||||||
|
(propertize
|
||||||
|
(format (concat "%" (number-to-string
|
||||||
|
elfeed-summary--unread-padding)
|
||||||
|
"d / %-" (number-to-string
|
||||||
|
elfeed-summary--total-padding)
|
||||||
|
"d ")
|
||||||
|
(alist-get 'unread data) (alist-get 'total data))
|
||||||
|
'face
|
||||||
|
(if (< 0 (alist-get 'unread data))
|
||||||
|
'elfeed-summary-count-face-unread
|
||||||
|
'elfeed-summary-count-face))
|
||||||
|
(propertize title 'face (alist-get 'faces data)))))
|
||||||
|
(insert text)
|
||||||
(insert "\n")))
|
(insert "\n")))
|
||||||
|
|
||||||
(defun elfeed-summary--render-search (data)
|
(defun elfeed-summary--render-search (data)
|
||||||
(let ((search-data (alist-get 'params data)))
|
(let* ((search-data (alist-get 'params data))
|
||||||
(insert (propertize
|
(text (concat
|
||||||
(alist-get :title search-data)
|
(propertize
|
||||||
'face
|
(format (concat "%" (number-to-string
|
||||||
(alist-get :face search-data)))
|
elfeed-summary--unread-padding)
|
||||||
|
"d / %-" (number-to-string
|
||||||
|
elfeed-summary--total-padding)
|
||||||
|
"d ")
|
||||||
|
(alist-get 'unread data) (alist-get 'total data))
|
||||||
|
'face
|
||||||
|
(if (< 0 (alist-get 'unread data))
|
||||||
|
'elfeed-summary-count-face-unread
|
||||||
|
'elfeed-summary-count-face))
|
||||||
|
(propertize
|
||||||
|
(alist-get :title search-data)
|
||||||
|
'face
|
||||||
|
(alist-get 'faces data)))))
|
||||||
|
(insert text)
|
||||||
(insert "\n")))
|
(insert "\n")))
|
||||||
|
|
||||||
(defun elfeed-summary--render-group (data)
|
(defun elfeed-summary--render-group (data)
|
||||||
(let ((group-data (alist-get 'params data)))
|
(let ((group-data (alist-get 'params data)))
|
||||||
(magit-insert-section group (elfeed-summary-group-section)
|
(magit-insert-section group (elfeed-summary-group-section
|
||||||
|
nil (alist-get :hide group-data))
|
||||||
(insert (propertize
|
(insert (propertize
|
||||||
(alist-get :title group-data)
|
(alist-get :title group-data)
|
||||||
'face
|
'face
|
||||||
(alist-get :face group-data)))
|
(alist-get 'face data)))
|
||||||
(insert "\n")
|
(insert "\n")
|
||||||
(magit-insert-heading)
|
(magit-insert-heading)
|
||||||
(oset group group data)
|
(oset group group data)
|
||||||
|
|
@ -502,14 +572,39 @@ Implented the same way as `elfeed-search--update-list'."
|
||||||
(elfeed-summary--render-search data))
|
(elfeed-summary--render-search data))
|
||||||
(_ (error "Unknown tree item: %s" (prin1-to-string (car item)))))))
|
(_ (error "Unknown tree item: %s" (prin1-to-string (car item)))))))
|
||||||
|
|
||||||
|
(defun elfeed-summary--render-params (tree &optional max-unread max-total)
|
||||||
|
(unless max-unread
|
||||||
|
(setq max-unread 0
|
||||||
|
max-total 0))
|
||||||
|
(cl-loop for item in tree
|
||||||
|
for type = (car item)
|
||||||
|
if (eq type 'group)
|
||||||
|
do (let ((data (elfeed-summary--render-params
|
||||||
|
(alist-get 'children (cdr item))
|
||||||
|
max-unread max-total)))
|
||||||
|
(setq max-unread (max max-unread (nth 0 data))
|
||||||
|
max-total (max max-total (nth 1 data))))
|
||||||
|
else if (or (eq type 'feed) (eq type 'search))
|
||||||
|
do (setq max-unread
|
||||||
|
(max max-unread (alist-get 'unread (cdr item)))
|
||||||
|
max-total
|
||||||
|
(max max-total (alist-get 'total (cdr item)))))
|
||||||
|
(list max-unread max-total))
|
||||||
|
|
||||||
(defun elfeed-summary--render (tree)
|
(defun elfeed-summary--render (tree)
|
||||||
"TODO"
|
"TODO"
|
||||||
(let ((inhibit-read-only t))
|
(let* ((inhibit-read-only t)
|
||||||
|
(render-data (elfeed-summary--render-params tree))
|
||||||
|
(elfeed-summary--unread-padding
|
||||||
|
(length (number-to-string (nth 0 render-data))))
|
||||||
|
(elfeed-summary--total-padding
|
||||||
|
(length (number-to-string (nth 1 render-data)))))
|
||||||
(erase-buffer)
|
(erase-buffer)
|
||||||
(setq-local elfeed-summary--tree tree)
|
(setq-local elfeed-summary--tree tree)
|
||||||
(unless (eq major-mode 'elfeed-summary-mode)
|
(unless (eq major-mode 'elfeed-summary-mode)
|
||||||
(elfeed-summary-mode))
|
(elfeed-summary-mode))
|
||||||
(mapc #'elfeed-summary--render-item tree)))
|
(mapc #'elfeed-summary--render-item tree)
|
||||||
|
(goto-char (point-min))))
|
||||||
|
|
||||||
(defun elfeed-summary ()
|
(defun elfeed-summary ()
|
||||||
"TODO"
|
"TODO"
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue