Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: Read entry properties, assign to feed meta #48

Open
alphapapa opened this issue Sep 2, 2018 · 1 comment
Open

Feature request: Read entry properties, assign to feed meta #48

alphapapa opened this issue Sep 2, 2018 · 1 comment

Comments

@alphapapa
Copy link
Contributor

Hi,

It would be nice if elfeed-org would read Org properties on entries using org-entry-get-with-inheritance and assign selected properties to feeds' meta slot. I'm using this with some custom code to set face properties for feeds, which I then draw with some custom code. For example, I have an entry like this in the Org file:

**** Emacs                                                         :Emacs:
:PROPERTIES:
:foreground: white
:background: #7F5AB6
:END:

***** [[http://planet.emacsen.org/atom.xml][Planet Emacs]]                                           :aggregator:
***** [[https://www.reddit.com/r/emacs/.rss][/r/Emacs]]                                                   :Reddit:

Then after reading that Org file with my code, those feeds' meta slots have :background and :foreground properties. Then I draw the feed items, applying the colors to the feed title, which looks something like this:
out1

I wanted to add this feature to elfeed-org myself, but I got a bit lost in the code while looking for the right way to add it, so I ended up writing a function to read the Org file myself (without duplicating all of elfeed-org's features). But it would be preferable to have this implemented in elfeed-org itself. :)

In case anyone else finds the code useful, here it is:

(require 'org)

(require 'dash)
(require 'kv)

(require 'elfeed-db)

(cl-defstruct org-link
  protocol path description)

(defun org-match-link (&optional s)
  "Return an `org-link' struct if an Org link is matched in string S or at point.
Matches with `org-bracket-link-analytic-regexp'."
  ;; NOTE: HTTP paths will start with two slashes.
  (cond (s (when (string-match org-bracket-link-analytic-regexp s)
             (make-org-link :protocol (match-string-no-properties 2 s)
                            :path (match-string-no-properties 3 s)
                            :description (match-string-no-properties 5 s))))
        (t (when (looking-at org-bracket-link-analytic-regexp)
             (make-org-link :protocol (match-string-no-properties 2)
                            :path (match-string-no-properties 3)
                            :description (match-string-no-properties 5))))))

(defun ap/elfeed-org--feeds-in (buffer)
  "Return list of feeds in Org BUFFER."
  (with-current-buffer buffer
    (org-with-wide-buffer
     (let ((org-use-tag-inheritance t)
           (org-use-property-inheritance t))
       (goto-char (point-min))
       (when (org-before-first-heading-p)
         (outline-next-heading))
       (cl-loop while (re-search-forward org-complex-heading-regexp nil t)
                collect (save-excursion
                          (goto-char (match-beginning 0))
                          (let* ((heading (substring-no-properties (org-get-heading t t)))
                                 url title tags meta)
                            (when (cond ((string-match (rx bos "http" (optional "s") "://") heading)
                                         (setq url heading))
                                        ((when-let* ((link (org-match-link heading)))
                                           (setq url (concat (org-link-protocol link) ":"
                                                             (org-link-path link))
                                                 title (org-link-description link)))))
                              (setq tags (->> (org-get-tags-at)
                                              (--map (->> it substring-no-properties intern))
                                              (delq 'elfeed))
                                    meta (ap/elfeed-org--entry-properties))
                              (let ((feed (elfeed-db-get-feed url)))
                                (setf (elfeed-feed-meta feed)
                                      (kvplist-merge (elfeed-feed-meta feed) meta))
                                (setf (elfeed-meta feed :title) title)
                                (setf (elfeed-meta feed :tags) tags)
                                feed)))))))))

(defcustom ap/elfeed-org-properties '("background" "foreground" "face")
  "List of properties to read from entries, which will be applied to the feed's metadata."
  :type '(repeat string))

(defun ap/elfeed-org--entry-properties ()
  "Return plist of selected properties in current entry."
  (cl-loop for property in ap/elfeed-org-properties
           for value = (org-entry-get-with-inheritance property)
           for keyword = (intern (concat ":" property))
           append (list keyword value)))

The Org file is read like this:

  (when-let* ((feeds (-non-nil (ap/elfeed-org--feeds-in (get-buffer "elfeed.org")))))
    (setq elfeed-feeds
          (--map (cons (elfeed-feed-url it)
                       (elfeed-meta it :tags))
                 feeds)))
@jackmac92
Copy link

+1 I think something like this is necessary for integration with elfeed-protocol e.g.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants