From 012670274e242143eccdc12dd58065d8126a4e28 Mon Sep 17 00:00:00 2001 From: SqrtMinusOne Date: Sat, 19 Mar 2022 22:16:39 +0300 Subject: [PATCH] docs: docstrings --- elfeed-summary.el | 184 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 149 insertions(+), 35 deletions(-) diff --git a/elfeed-summary.el b/elfeed-summary.el index c97d206..44245b5 100644 --- a/elfeed-summary.el +++ b/elfeed-summary.el @@ -1,4 +1,4 @@ -;;; elfeed-summary.el --- TODO -*- lexical-binding: t -*- +;;; elfeed-summary.el --- Feed summary interface for elfeed -*- lexical-binding: t -*- ;; Copyright (C) 2022 Korytov Pavel @@ -24,7 +24,16 @@ ;; along with this program. If not, see . ;;; Commentary: -;; TODO +;; An extension for elfeed that provides a feed summary interface, +;; inspired by newsboat but tree-based. +;; +;; `elfeed-summary' pops up the summary buffer. The buffer shows +;; individual feeds and searches, combined into groups. This is +;; determined by the `elfeed-summary-settings' variable. +;; +;; Also take a look at the package README at +;; for more +;; information. ;;; Code: (require 'cl-lib) @@ -40,9 +49,8 @@ ;; the code. (declare-function evil-define-key* "evil-core") - (define-widget 'elfeed-summary-query 'lazy - "A query to extract a subset of elfeed feeds." + "Type widget for the query part of `elfeed-summary-settings'." :offset 4 :tag "Extract subset of elfeed feed list" :type '(choice (symbol :tag "One tag") @@ -88,7 +96,7 @@ (face :tag "Face")) (cons (const :tag "Hide" :hide) - (boleean :tag "Hide")) + (boolean :tag "Hide")) (cons (const :tag "Elements" :elements) elfeed-summary-setting-elements)))) @@ -124,7 +132,7 @@ (search (:filter . "@6-months-ago emacs") (:title . "Something about Emacs"))))) - "Elfeed summary buffer settings. + "Elfeed summary settings. This is a list of these possible items: - Group `(group . )' @@ -182,22 +190,31 @@ Available special forms: :type 'elfeed-summary-setting-elements) (defcustom elfeed-summary-look-back (* 60 60 24 180) - "TODO" + "Timespan for which to count entries in the feed list. + +The default value is 180 days, which means that only entries less than +180 days old will be counted. + +This has to be set up for efficiency because the elfeed database is +time-based, so this allows queirying only the most recent part of the +database. + +The value is in seconds." :group 'elfeed-summary :type 'integer) (defcustom elfeed-summary-default-filter "@6-months-ago " - "TODO" + "Default filter when switching to search buffer for a feed." :group 'elfeed-summary :type 'integer) (defcustom elfeed-summary-unread-tag 'unread - "Unread tag" + "Tag with which to consider the entry unread." :group 'elfeed-summary :type 'symbol) (defcustom elfeed-summary-feed-face-fn #'elfeed-summary--feed-face-fn - "Function to get the face of the feed. + "Function to get the face of the feed entry. Accepts two arguments: - The corresponding instance of `elfeed-feed'. @@ -209,7 +226,7 @@ The default implementation, `elfeed-summary--feed-face-fn', calls :type 'function) (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 entry. Accepts the following arguments: - `', as described in `elfeed-summary-settings'. @@ -226,33 +243,34 @@ greater than zero." (defcustom elfeed-summary-feed-sort-fn #'elfeed-summary--feed-sort-fn "Function to sort feeds in query. -Receives TODO" +Receives two instances of `elfeed-feed'." :group 'elfeed-summary :type 'function) (defconst elfeed-summary-buffer "*elfeed-summary*" - "Elfeed summary buffer name") + "Elfeed summary buffer name.") (defface elfeed-summary-group-face '((t (:inherit magit-section-heading))) - "Default face for the elfeed-summary group." + "Default face for the elfeed summary group." :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" + "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" + "Face for the number of entries of an unread feed or search." :group 'elfeed-summary) ;;; Logic (cl-defun elfeed-summary--match-tag (query &key tags title url author title-meta) "Check if attributes of elfeed feed match QUERY. -QUERY is a form as described in `elfeed-summary-settings'. +QUERY is a `' form as described in +`elfeed-summary-settings'. TAGS is a list of tags from `elfeed-feeds', TITLE, URL, AUTHOR and TITLE-META are attributes of the `elfeed-db-feed'." @@ -332,7 +350,9 @@ and TITLE-META are attributes of the `elfeed-db-feed'." query))))) (defun elfeed-summary--feed-sort-fn (feed-1 feed-2) - "TODO" + "The default implementation of a feed sorting function. + +FEED-1 and FEED-2 are instances of `elfeed-feed'." (string-lessp (downcase (or (plist-get (elfeed-feed-meta feed-1) :title) @@ -362,18 +382,19 @@ QUERY is described in `elfeed-summary-settings'." :author (plist-get (car (elfeed-feed-author feed)) :name)) collect feed))) -(defun elfeed-summary--extract-feeds (params) - (cl-loop for param in params - if (and (listp param) (eq (car param) 'group)) - 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)))) - (defun elfeed-summary--feed-face-fn (_feed tags) + "The default implementation of the feed face function. + +FEED is an instance of `elfeed-feed', TAGS is a list of tags from +`elfeed-feeds'." (elfeed-search--faces tags)) (defun elfeed-summary--build-tree-feed (feed unread-count total-count) + "Create a feed entry for the summary details tree. + +FEED is an instance of `elfeed-feed'. UNREAD-COUNT and TOTAL-COUNT +are hashmaps with feed ids as keys and corresponding numbers of +entries as values." (let* ((unread (or (gethash (elfeed-feed-id feed) unread-count) 0)) (tags (alist-get (elfeed-feed-id feed) elfeed-feeds nil nil #'equal)) @@ -387,6 +408,13 @@ QUERY is described in `elfeed-summary-settings'." (tags . ,all-tags))))) (defun elfeed-summary--search-face-fn (search unread _total) + "The default implementation of the search entry face function. + +SEARCH is a `' form as described in +`elfeed-summary-settings'. + +UNREAD is the number of unread entries, TOTAL is the total number of +entries." (let ((tags (append (alist-get :tags search) (when (< 0 unread) @@ -394,7 +422,10 @@ QUERY is described in `elfeed-summary-settings'." (elfeed-search--faces tags))) (defun elfeed-summary--build-search (search) - "TODO + "Create a search entry for the summary details tree. + +SEARCH is a `' form as described in +`elfeed-summary-settings'. Implented the same way as `elfeed-search--update-list'." (let* ((filter (elfeed-search-parse-filter (alist-get :filter search))) @@ -429,6 +460,16 @@ Implented the same way as `elfeed-search--update-list'." (total . ,total))))) (defun elfeed-summary--build-tree (params unread-count total-count misc-feeds) + "Recursively create the summary details tree. + +PARAMS is a form as 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 was not used in PARAMS. + +The resulting form is described in `elfeed-summary--get-data'." (cl-loop for param in params if (and (listp param) (eq (car param) 'group)) collect `(group . ((params . ,(cdr param)) @@ -449,7 +490,47 @@ Implented the same way as `elfeed-search--update-list'." feed unread-count total-count)) else do (error "Can't parse: %s" (prin1-to-string param)))) +(defun elfeed-summary--extract-feeds (params) + "Extract feeds from PARAMS. + +PARAMS is a form as described in `elfeed-summary-settings'." + (cl-loop for param in params + if (and (listp param) (eq (car param) 'group)) + 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)))) + (defun elfeed-summary--get-data () + "Create the summary details tree from scratch. + +The summary tree is created by extending `elfeed-summary-settings' +with the data from the elfeed database. + +The return value is a list of alists of the following elements: +- `(group . )' +- `(feed . )' +- `(search . )' + +`' is an alist with the following keys: +- `params' - `' as described in + `elfeed-summary-settings'. +- `face' - face for the group. +- `children' - list of children, same structure as the root form. + +`' is an alist with the following keys: +- `feed' - instance of `elfeed-feed'. +- `tags' - feed tags. +- `faces' - list of faces for the search entry. +- `unread' - number of unread entries in the feed. +- `total' - total number of entries in the feed. + +`' is an alist with the following keys: +- `params' - `' as described in + `elfeed-summary-settings'. +- `faces' - list of faces for the search entry. +- `unread' - number of unread entries in the search results. +- `total' - total number of entries in the search results." (let* ((feeds (elfeed-summary--extract-feeds elfeed-summary-settings)) (all-feeds (mapcar #'car elfeed-feeds)) @@ -478,19 +559,19 @@ Implented the same way as `elfeed-search--update-list'." ;;; View (defvar-local elfeed-summary--tree nil - "TODO") + "The current value of the elfeed summary tree.") (defvar elfeed-summary--unread-padding 3 - "TODO") + "Padding for the unread column in the elfeed summary buffer.") (defvar elfeed-summary--total-padding 3 - "TODO") + "Padding for the total column in the elfeed summary buffer.") (defvar elfeed-summary--only-unread nil - "TODO") + "Only show items with unread entries in the elfeed summary buffer.") (defvar elfeed-summary--search-show-read nil - "TODO") + "Do not filter +unread when switching to the elfeed search buffer.") (defvar elfeed-summary-mode-map (let ((map (make-sparse-keymap))) @@ -517,7 +598,7 @@ Implented the same way as `elfeed-search--update-list'." "A keymap for `elfeed-summary-mode-map'.") (define-derived-mode elfeed-summary-mode magit-section "Elfeed Summary" - "TODO" + "A major mode to display the elfeed summary data." :group 'org-journal-tags (setq-local buffer-read-only t)) @@ -525,11 +606,18 @@ Implented the same way as `elfeed-search--update-list'." ((group :initform nil))) (defun elfeed-summary--widget-press-show-read (pos &optional event) + "Press a button with `elfeed-summary--search-show-read' set to t. + +POS and EVENT are forwarded to `widget-button-press'." (interactive "@d") (let ((elfeed-summary--search-show-read t)) (widget-button-press pos event))) (defun elfeed-summary--render-feed (data) + "Render a feed item for the elfeed summary buffer. + +DATA is a `' form as described in +`elfeed-summary--get-data'." (let* ((feed (alist-get 'feed data)) (title (or (plist-get (elfeed-feed-meta feed) :title) (elfeed-feed-title feed) @@ -567,6 +655,10 @@ Implented the same way as `elfeed-search--update-list'." (insert "\n"))) (defun elfeed-summary--render-search (data) + "Render a search item for the elfeed summary buffer. + +DATA is a `' form as described in the +`elfeed-summary--get-data'." (let* ((search-data (alist-get 'params data)) (text (concat (propertize @@ -588,6 +680,10 @@ Implented the same way as `elfeed-search--update-list'." (widget-insert "\n"))) (defun elfeed-summary--render-group (data) + "Render a group item for the elfeed summary buffer. + +DATA is a `' from as described in +`elfeed-summary-get-data'." (let ((group-data (alist-get 'params data))) (magit-insert-section group (elfeed-summary-group-section nil (alist-get :hide group-data)) @@ -602,6 +698,9 @@ Implented the same way as `elfeed-search--update-list'." do (elfeed-summary--render-item child))))) (defun elfeed-summary--render-item (item) + "Render one item for the elfeed summary buffer. + +ITEM is one alist as returned by `elfeed-summary--get-data'." (let ((data (cdr item))) (pcase (car item) ('group @@ -613,6 +712,11 @@ Implented the same way as `elfeed-search--update-list'." (_ (error "Unknown tree item: %s" (prin1-to-string (car item))))))) (defun elfeed-summary--render-params (tree &optional max-unread max-total) + "Get rendering parameters from the summary tree. + +TREE is a form such as returned by `elfeed-summary--get-data'. + +MAX-UNREAD and MAX-TOTAL are paramenters for the recursive descent." (unless max-unread (setq max-unread 0 max-total 0)) @@ -632,6 +736,9 @@ Implented the same way as `elfeed-search--update-list'." (list max-unread max-total)) (defun elfeed-summary--leave-only-unread (tree) + "Leave only items that have unread elfeed entries in them. + +TREE is a form such as returned by `elfeed-summary--get-data'." (cl-loop for item in tree for type = (car item) if (and (eq type 'group) @@ -646,7 +753,9 @@ Implented the same way as `elfeed-search--update-list'." collect item)) (defun elfeed-summary--render (tree) - "TODO" + "Render the elfeed summary tree. + +TREE is a form such as returned by `elfeed-summary--get-data'." (when elfeed-summary--only-unread (setq tree (elfeed-summary--leave-only-unread tree))) (setq-local widget-push-button-prefix "") @@ -667,6 +776,7 @@ Implented the same way as `elfeed-search--update-list'." (widget-setup))) (defun elfeed-summary--refresh () + "Refresh the elfeed summary tree." (interactive) (when (eq (buffer-name) elfeed-summary-buffer) (let ((inhibit-read-only t)) @@ -679,13 +789,17 @@ Implented the same way as `elfeed-search--update-list'." (elfeed-summary--get-data)))))) (defun elfeed-summary-toggle-only-unread () + "Toggle displaying only items with unread elfeed entries." (interactive) (setq-local elfeed-summary--only-unread (not elfeed-summary--only-unread)) (elfeed-summary--refresh)) (defun elfeed-summary () - "TODO" + "Display a feed summary for elfeed. + +The buffer displays a list of feeds, as set up by the +`elfeed-summary-settings' variable." (interactive) (add-hook 'elfeed-update-init-hooks 'elfeed-summary--refresh) (when-let ((buffer (get-buffer elfeed-summary-buffer)))