Coder Social home page Coder Social logo

elfeed's Introduction

Elfeed Emacs Web Feed Reader

Elfeed is an extensible web feed reader for Emacs, supporting both Atom and RSS. It requires Emacs 24.3 and is available for download from MELPA or el-get. Elfeed was inspired by notmuch.

For a longer overview,

The database format is stable and is never expected to change.

Prerequisites

It is strongly recommended you have cURL installed, either in your PATH or configured via elfeed-curl-program-name. Elfeed will prefer it to Emacs' own URL-fetching mechanism, url-retrieve. It's also essential for running Elfeed on Windows, where url-retrieve is broken. Updates using cURL are significantly faster than the built-in method, both for you and the feed hosts.

If this is giving you problems, fetching with cURL can be disabled by setting elfeed-use-curl to nil.

Extensions

These projects extend Elfeed with additional features:

Getting Started

Elfeed is broken into a multiple source files, so if you manually install it you will need to add the Elfeed package directory to your load-path. If installed via package.el or el-get, this will be done automatically.

It is recommended that you make a global binding for elfeed.

(global-set-key (kbd "C-x w") 'elfeed)

Running the interactive function elfeed will pop up the *elfeed-search* buffer, which will display feed items.

  • g: refresh view of the feed listing
  • G: fetch feed updates from the servers
  • s: update the search filter (see tags)
  • c: clear the search filter

This buffer will be empty until you add your feeds to the elfeed-feeds list and initiate an update with M-x elfeed-update (or G in the Elfeed buffer). This will populate the Elfeed database with entries.

;; Somewhere in your .emacs file
(setq elfeed-feeds
      '("http://nullprogram.com/feed/"
        "https://planet.emacslife.com/atom.xml"))

Another option for providing a feed list is with an OPML file. Running M-x elfeed-load-opml will fill elfeed-feeds with feeds listed in an OPML file. When elfeed-load-opml is called interactively, it will automatically save the feedlist to your customization file, so you will only need to do this once.

If there are a lot of feeds, the initial update will take noticeably longer than normal operation because of the large amount of information being written the database. Future updates will only need to write new or changed data. If updating feeds slows down Emacs too much for you, reduce the number of concurrent fetches via elfeed-set-max-connections.

If you're getting many "Queue timeout exceeded" errors, increase the fetch timeout via elfeed-set-timeout.

(setf url-queue-timeout 30)

From the search buffer there are a number of ways to interact with entries. Entries are selected by placing the point over an entry. Multiple entries are selected at once by using an active region.

  • RET: view selected entry in a buffer
  • b: open selected entries in your browser (browse-url)
  • y: copy selected entries URL to the clipboard
  • r: mark selected entries as read
  • u: mark selected entries as unread
  • +: add a specific tag to selected entries
  • -: remove a specific tag from selected entries

Tags

Elfeed maintains a list of arbitrary tags -- symbols attached to an entry. The tag unread is treated specially by default, with unread entries appearing in bold.

Autotagging

Tags can automatically be applied to entries discovered in specific feeds through extra syntax in elfeed-feeds. Normally this is a list of strings, but an item can also be a list, providing set of "autotags" for a feed's entries.

(setq elfeed-feeds
      '(("http://nullprogram.com/feed/" blog emacs)
        "http://www.50ply.com/atom.xml"  ; no autotagging
        ("http://nedroid.com/feed/" webcomic)))

Filter Syntax

To make tags useful, the Elfeed entry listing buffer can be filtered by tags. Use elfeed-search-set-filter (or s) to update the filter. Use elfeed-search-clear-filter to restore the default.

Any component of the search string beginning with a + or a - is treated like a tag. + means the tag is required, - means the tag must not be present.

A component beginning with a @ indicates an age or a date range. An age is a relative time expression or an absolute date expression. Entries older than this age are filtered out. The age description accepts plain English, but cannot have spaces, so use dashes. For example, "@2-years-old", "@3-days-ago" or "@2019-06-24". A date range are two ages seperated by a --, e.g. "@2019-06-20--2019-06-24" or "@5-days-ago--1-day-ago". The entry must be newer than the first expression but older than the second. The database is date-oriented, so filters that include an age restriction are significantly more efficient.

A component beginning with a ! is treated as an "inverse" regular expression. This means that any entry matching this regular expression will be filtered out. The regular expression begins after the ! character. You can read this as "entry not matching foo".

A component beginning with a # limits the total number of entries displayed to the number immediately following the symbol. For example, to limit the display to 20 entries: #20.

A component beginning with a = is a regular expression matching the entry's feed (title or URL). Only entries belonging to a feed that matches at least one of the = expressions will be shown.

A component beginning with a ~ is a regular expression matching the entry's feed (title or URL). Only entries belonging to a feed that matches none of the ~ expressions will be shown.

All other components are treated as a regular expression, and only entries matching it (title or URL) will be shown.

Here are some example filters.

  • @6-months-ago +unread

Only show unread entries of the last six months. This is the default filter.

  • linu[xs] @1-year-old

Only show entries about Linux or Linus from the last year.

  • -unread +youtube #10

Only show the most recent 10 previously-read entries tagged as youtube.

  • +unread !x?emacs

Only show unread entries not having emacs or xemacs in the title or link.

  • +emacs =http://example.org/feed/

Only show entries tagged as emacs from a specific feed.

Default Search Filter

You can set your default search filter by changing the default value of elfeed-search-filter. It only changes buffer-locally when you're adjusting the filter within Elfeed. For example, some users prefer to have a space on the end for easier quick searching.

(setq-default elfeed-search-filter "@1-week-ago +unread ")

Tag Hooks

The last example assumes you've tagged posts with youtube. You probably want to do this sort of thing automatically, either through the "autotags" feature mentioned above, or with the elfeed-new-entry-hook. Functions in this hook are called with new entries, allowing them to be manipulated, such as adding tags.

;; Mark all YouTube entries
(add-hook 'elfeed-new-entry-hook
          (elfeed-make-tagger :feed-url "youtube\\.com"
                              :add '(video youtube)))

Avoiding tagging old entries as unread:

;; Entries older than 2 weeks are marked as read
(add-hook 'elfeed-new-entry-hook
          (elfeed-make-tagger :before "2 weeks ago"
                              :remove 'unread))

Or building your own subset feeds:

(add-hook 'elfeed-new-entry-hook
          (elfeed-make-tagger :feed-url "example\\.com"
                              :entry-title '(not "something interesting")
                              :add 'junk
                              :remove 'unread))

Use M-x elfeed-apply-hooks-now to apply elfeed-new-entry-hook to all existing entries. Otherwise hooks will only apply to new entries on discovery.

Custom Tag Faces

By default, entries marked unread will have bolded titles in the *elfeed-search* listing. You can customize how tags affect an entry's appearance by customizing elfeed-search-face-alist. For example, this configuration makes entries tagged important stand out in red.

(defface important-elfeed-entry
  '((t :foreground "#f77"))
  "Marks an important Elfeed entry.")

(push '(important important-elfeed-entry)
      elfeed-search-face-alist)

All faces from all tags will be applied to the entry title. The faces will be ordered as they appear in elfeed-search-face-alist.

Bookmarks

Filters can be saved and restored using Emacs' built-in bookmarks feature. While in the search buffer, use M-x bookmark-set to save the current filter, and M-x bookmark-jump to restore a saved filter. Emacs automatically persists bookmarks across sessions.

Metadata Plist

All feed and entry objects have plist where you can store your own arbitrary, readable values. These values are automatically persisted in the database. This metadata is accessed using the polymorphic elfeed-meta function. It's setf-able.

(setf (elfeed-meta entry :rating) 4)
(elfeed-meta entry :rating)
;; => 4

(setf (elfeed-meta feed :title) "My Better Title")

Elfeed itself adds some entries to this plist, some for your use, some for its own use. Here are the properties that Elfeed uses:

  • :authors : A list of author plists (:name, :uri, :email).
  • :canonical-url : The final URL for the feed after all redirects.
  • :categories : The feed-supplied categories for this entry.
  • :etag : HTTP Etag header, for conditional GETs.
  • :failures : Number of times this feed has failed to update.
  • :last-modified : HTTP Last-Modified header, for conditional GETs.
  • :title : Overrides the feed-supplied title for display purposes, both for feeds and entries. See also elfeed-search-set-feed-title and elfeed-search-set-entry-title.

This list will grow in time, so you might consider namespacing your own properties to avoid collisions (e.g. :xyz/rating), or simply not using keywords as keys. Elfeed will always use keywords without a slash.

Hooks

A number of hooks are available to customize the behavior of Elfeed at key points without resorting to advice.

  • elfeed-new-entry-hook : Called each time a new entry it added to the database, allowing for automating tagging and such.
  • elfeed-new-entry-parse-hook : Called with each new entry and the full XML structure from which it was parsed, allowing for additional information to be drawn from the original feed XML.
  • elfeed-http-error-hooks : Allows for special behavior when HTTP errors occur, beyond simply logging the error to *elfeed-log* .
  • elfeed-parse-error-hooks : Allows for special behavior when feed parsing fails, beyond logging.
  • elfeed-db-update-hook : Called any time the database has had a major modification.

Viewing Entries

Entries are viewed locally in Emacs by typing RET while over an entry in the search listing. The content will be displayed in a separate buffer using elfeed-show-mode, rendered using Emacs' built-in shr package. This requires an Emacs compiled with libxml2 bindings, which provides the necessary HTML parser.

Sometimes displaying images can slow down or even crash Emacs. Set shr-inhibit-images to disable images if this is a problem.

Web Interface

Elfeed includes a demonstration/toy web interface for remote network access. It's a single-page web application that follows the database live as new entries arrive. It's packaged separately as elfeed-web. To fire it up, run M-x elfeed-web-start and visit http://localhost:8080/elfeed/ (check your httpd-port) with a browser. See the elfeed-web.el header for endpoint documentation if you'd like to access the Elfeed database through the web API.

It's rough and unfinished -- no keyboard shortcuts, read-only, no authentication, and a narrow entry viewer. This is basically Elfeed's "mobile" interface. Patches welcome.

Platform Support

Summary: Install cURL and most problems disappear for all platforms.

I personally only use Elfeed on Linux, but it's occasionally tested on Windows. Unfortunately the Windows port of Emacs is a bit too unstable for parallel feed downloads with url-retrieve, not to mention the tiny, hard-coded, 512 open descriptor limitation, so it limits itself to one feed at a time on this platform.

If you fetch HTTPS feeds without cURL on any platform, it's essential that Emacs is built with the --with-gnutls option. Otherwise Emacs runs gnutls in an inferior process, which rarely works well.

Database Management

The database should keep itself under control without any manual intervention, but steps can be taken to minimize the database size if desired. The simplest option is to run the elfeed-db-compact command, which will pack the loose-file content database into a single compressed file. This function works well in kill-emacs-hook.

Going further, a function could be added to elfeed-new-entry-hook to strip unwanted/unneeded content from select entries before being stored in the database. For example, for YouTube videos only the entry link is of interest and the regularly-changing entry content could be tossed to save time and storage.

Status and Roadmap

Elfeed is to the point where it can serve 100% of my own web feed needs. My personal selection of about 150 feeds has been acting as my test case as I optimize and add features.

Some things I still might want to add:

  • Database synchronization between computers
  • Parallel feed fetching via separate Emacs subprocesses

Motivation

As far as I know, outside of Elfeed there does not exist an extensible, text-file configured, power-user web feed client that can handle a reasonable number of feeds. The existing clients I've tried are missing some important capability that limits its usefulness to me.

elfeed's People

Contributors

algernon avatar ambrevar avatar atheriel avatar br0cco1i avatar cellscape avatar cowile avatar fuco1 avatar groks avatar herrsimon avatar holomorph avatar ieure avatar jinnovation avatar ksjogo avatar mnp avatar pierre-lecocq avatar polaris64 avatar progfolio avatar psub avatar remyhonig avatar rksm avatar rnkn avatar seblemaguer avatar sinic avatar skeeto avatar stardiviner avatar thisirs avatar tsdh avatar tvraman avatar utkarsh181 avatar zharmeny avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

elfeed's Issues

error Stack overflow in regexp matcher

I get many SO in regexp matcher errors:

Elfeed update failed for http://blog.datomic.com/feeds/posts/default: (error Stack overflow in regexp matcher)

Elfeed update failed for http://gbracha.blogspot.com/feeds/posts/default: (error Stack overflow in regexp matcher)

Elfeed update failed for http://gdata.youtube.com/feeds/api/playlists/1CA6335E0D3699B6: (error Stack overflow in regexp matcher)

Tested with master.

Odd number of elements in hashtable data on emacs close

In emacs 24.3 and in emacs snapshot

Debugger entered--Lisp error: (error "Odd number of elements in hashtable data")
  read(#<buffer index>)
  (setq elfeed-db (read (current-buffer)))
  (save-current-buffer (set-buffer (find-file-noselect index)) (goto-char (point-min)) (setq elfeed-db (read (current-buffer))) (kill-buffer))
  (if (not (file-exists-p index)) (let ((db (setq elfeed-db (list :version elfeed-db-version)))) (plist-put db :feeds (make-hash-table :test (quote equal))) (plist-put db :entries (make-hash-table :test (quote equal))) (plist-put db :index (let ((cmpfun (function elfeed-db-compare))) (progn (vector (quote cl-struct-avl-tree-) (progn (vector nil nil nil 0)) (function elfeed-db-compare)))))) (save-current-buffer (set-buffer (find-file-noselect index)) (goto-char (point-min)) (setq elfeed-db (read (current-buffer))) (kill-buffer)))
  (let ((index (expand-file-name "index" elfeed-db-directory))) (if (not (file-exists-p index)) (let ((db (setq elfeed-db (list :version elfeed-db-version)))) (plist-put db :feeds (make-hash-table :test (quote equal))) (plist-put db :entries (make-hash-table :test (quote equal))) (plist-put db :index (let ((cmpfun (function elfeed-db-compare))) (progn (vector (quote cl-struct-avl-tree-) (progn ...) (function elfeed-db-compare)))))) (save-current-buffer (set-buffer (find-file-noselect index)) (goto-char (point-min)) (setq elfeed-db (read (current-buffer))) (kill-buffer))) (progn (setq elfeed-db-feeds (plist-get elfeed-db :feeds)) (setq elfeed-db-entries (plist-get elfeed-db :entries)) (setq elfeed-db-index (plist-get elfeed-db :index)) (progn (or (and (memq (aref elfeed-db-index 0) cl-struct-avl-tree--tags)) (error "%s accessing a non-%s" (quote avl-tree--cmpfun) (quote avl-tree-))) (let* ((v elfeed-db-index)) (aset v 2 (function elfeed-db-compare))))))
  elfeed-db-load()
  (progn (elfeed-db-load))
  (if (null elfeed-db) (progn (elfeed-db-load)))
  elfeed-db-ensure()
  elfeed-db-save()
  kill-emacs()
  save-buffers-kill-emacs()
  handle-delete-frame((delete-frame (#<frame *scratch* 0x119b7a0>)))
  dframe-handle-delete-frame((delete-frame (#<frame *scratch* 0x119b7a0>)))
  call-interactively(dframe-handle-delete-frame nil [(delete-frame (#<frame *scratch* 0x119b7a0>))])

Error message on elfeed-add-feed on OS X

First of all, thank you for your great alternative feed reader. It seems like minimalistic newsbeuter done right. Second, I'm totally noob to Emacs, and try using its great addons before I learnt the editor itself.

When I call elfeed-add-feed function the error message says "Symbol's function definition is void: x-get-selection-value". Maybe it's because of the absence of X11-related functions on Emacs for OS X.

URL safety/validation - http://www.dilbert.com/rss/

Scenario:
Boring day 1.
I want to add some daily humor feed and I go to http://www.dilbert.com/
I see a standard RSS img link (http://www.dilbert.com/rss/).
I copy it and paste directly to my elfeed-feeds-alist.

Regular day 2.
I open my beloved elfeed and want to update my feeds,
but in the middle of the update process my CPU workload goes to 100% and my available RAM is gradually smaller and smaller - after 3GB nothing left.

And I totally forget about new feed addition. Anyway - what can be wrong with
http://www.dilbert.com/rss/?

But it reality - everything is wrong.
http://www.dilbert.com/rss/ is an address where you can find proper RSS links :)
Not a real feed url.

After update I get "odd number" #13 surprise.
Fortunately I have a cronjob for .elfeed dir backup.
Great success! I do not lost my data.

In conclusion:
Elfeed should be able to detect invalid feeds/formats and for sure do not kill RAM and CPU, b/c of them, during update.

Now I will always check URL manually, but such safety mechanism would be nice addition.

Tested with:
URL: http://www.dilbert.com/rss/
Emacs 24.3, emacs 24.4
Elfeed from master HEAD.

Feeds update not so fast

Currently I'm subscribed to 78 feeds. The elfeed-update takes 2m 45s to fetch them all one by one.

My initial workflow for feed updating was: 1) Got time to read new feeds, 2) If there are no new feeds, start elfeed-update. 3) Wait almost 3 minutes. 4) Read. Then I became familiar with run-at-time function, and set up auto-update. So the updating is still long, but it runs in background.

Still, is there any chance to make it faster? What is the bottleneck of this process: fetching, parsing, or storing? If first is the problem, than may be it could be better to use curl/wget, if available?

Feature request: Fetch linked page

I'm fairly new to elfeed and really like it, so far, but it's missing a feature I really liked in gnus. Gnus can be configured to use the rss-blogs shimbun to fetch the page linked to by a feed entry and use regex to pull out just the content. This is especially useful for feeds that do not include the full content in the feed entry.

It looks like this could be accomplished through an elfeed-new-entry-hook but my lisp-fu is really weak. It may even be possible to use shimbun itself but converting the result to something that elfeed can use might be more trouble that it's worth.

Thank you for your time and the excellent app.

Problem with https://www.mnot.net/blog/index.atom

After elfeed-update-feed we get:

Elfeed update failed for https://www.mnot.net/blog/index.atom: (:error (error http 403))
gnutls.c: [0] (Emacs) fatal error: The TLS connection was non-properly terminated.

In browser https://www.mnot.net/blog/index.atom loads without problem.

After curl -v -o test https://www.mnot.net/blog/index.atom we have:

* Hostname was NOT found in DNS cache
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0*   Trying 119.9.43.241...

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* Connected to www.mnot.net (119.9.43.241) port 443 (#0)
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: none
* SSLv3, TLS handshake, Client hello (1):
} [data not shown]
* SSLv3, TLS handshake, Server hello (2):
{ [data not shown]
* SSLv3, TLS handshake, CERT (11):
{ [data not shown]
* SSLv3, TLS handshake, Server key exchange (12):
{ [data not shown]
* SSLv3, TLS handshake, Server finished (14):
{ [data not shown]
* SSLv3, TLS handshake, Client key exchange (16):
} [data not shown]
* SSLv3, TLS change cipher, Client hello (1):
} [data not shown]
* SSLv3, TLS handshake, Finished (20):
} [data not shown]
* SSLv3, TLS change cipher, Client hello (1):
{ [data not shown]
* SSLv3, TLS handshake, Finished (20):
{ [data not shown]
* SSL connection using TLSv1.2 / DHE-RSA-AES256-GCM-SHA384
* Server certificate:
*    subject: OU=Domain Control Validated; OU=Gandi Standard SSL; CN=mnot.net
*    start date: 2014-03-14 00:00:00 GMT
*    expire date: 2015-03-14 23:59:59 GMT
*    subjectAltName: www.mnot.net matched
*    issuer: C=FR; O=GANDI SAS; CN=Gandi Standard SSL CA
*    SSL certificate verify ok.

  0     0    0     0    0     0      0      0 --:--:--  0:00:01 --:--:--     0> GET /blog/index.atom HTTP/1.1
> User-Agent: curl/7.37.1
> Host: www.mnot.net
> Accept: */*
> 
< HTTP/1.1 200 OK

< Date: Wed, 06 Aug 2014 16:03:15 GMT
* Server Apache is not blacklisted
< Server: Apache
< Last-Modified: Sat, 07 Jun 2014 02:11:47 GMT
< ETag: "119c7-4fb35801b4713"
< Accept-Ranges: bytes
< Content-Length: 72135
< Strict-Transport-Security: max-age=7862400
< Public-Key-Pins-Report-Only: max-age=604800; pin-sha256="ZitlqPmA9FDAxkwOW/c7ehlNFk8qJ9FmZLXG6GzdjNM="; pin-sha256="XRXP98inz4rd1/gS9fJSNVfyrZbqY00T7PeRXUPd15w="; report-uri="/lib/key-pin.cgi"
< Content-Type: application/atom+xml
< Content-Language: en
< 
{ [data not shown]

 45 72135   45 32768    0     0  12253      0  0:00:05  0:00:02  0:00:03 12249
100 72135  100 72135    0     0  26691      0  0:00:02  0:00:02 --:--:-- 26687
* Connection #0 to host www.mnot.net left intact

After wget -v -O testwget https://www.mnot.net/blog/index.atom:

--2014-08-06 18:25:48--  https://www.mnot.net/blog/index.atom
Resolving www.mnot.net (www.mnot.net)... 119.9.43.241
Connecting to www.mnot.net (www.mnot.net)|119.9.43.241|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 72135 (70K) [application/atom+xml]
Saving to: ‘testwget’

     0K .......... .......... .......... .......... .......... 70% 16.8K 1s
    50K .......... ..........                                 100%  104K=3.2s

2014-08-06 18:25:53 (22.2 KB/s) - ‘testwget’ saved [72135/72135]

I also played with openssl s_client -servername mnot.net:443 -connect mnot.net:443
and gnutls-cli -p 443 mnot.net but I'm still not sure why it's not working with elfeed though.

Failed to update feed

Just imported all my actual feeds to Elfeed. Now if I press G, the strange error message occurs in minibuffer: Elfeed update failed for https://news.ycombinator.com/rss: (wrong-type-argument symbolp http://trendingjs.com/rss)

Here's my tiny init.el with subscription list: http://pastebin.com/raw.php?i=kH3XvQS5

Problem with Zotero feed

I set up my Zotero feed, which uses an https URL. Unfortunately, url-retrieve is not able to retrieve it. The error comes from gnutls. I tested it with gnutls-cli. However, mm-url-insert has no problem with it. I also tried giving elfeed the local URL file:///path/to/feed.xml to the feed but it complains with void-variable url-http-end-of-headers. I really need to get this working, elfeed is becoming an essential tool in my workflow.

Show/hide/scale images

Hi.

My main notebook is a 11" netbook which I love and carry everywhere. The issue with elfeed is that the (bigger) images in the posts take up all the screen and the scrolling gets very confusing. It would be awesome if I could toggle image display or scale them to say 20% to have an overview.

I looked at the code a bit but didn't figure out how you actually render the feeds (though I only looked very briefly, I'm quite busy at the moment :/)

If you see an easy way to implement this, I would be very thankful, otherwise I can take a stab at it and send some patch, but no sooner than next month.

Thanks for the amazing package!

Automatically moving the cursor to top on update in *elfeed-search*

I look through the feeds in elfeed-search from top to bottom marking them as read using r. Sometimes I want to hide read items by updating list using g. But cursor stays on the same line as before, so I have to move it to top manually using M-<.

As you may know I schedule elfeed-update using run-at-time. It works nice, but has annoying side effect. When feed list starts updating, it forces multiple refreshes (similar to g), and as a result I often lose cursor position.

It could be nice to have an option for automatically moving cursor to top (first or second line) after pressing g or any other list refreshes.

Elfeed update failed for... errors in GnuTLS -19.

Can anyone confirm this with:

("https://www.simonsfoundation.org/quanta-archive/feed" press science math physics)

Errors in Messages after feeds update sesssion:

gnutls.c: [0] (Emacs) fatal error: An unexpected TLS handshake packet was received.

gnutls.el: (err=[-19] An unexpected TLS handshake packet was received.) boot: (:priority NORMAL :hostname www.simonsfoundation.org :loglevel 0 :min-prime-bits 1024 :trustfiles (/etc/ssl/certs/ca-certificates.crt) :crlfiles nil :keylist nil :verify-flags nil :verify-error nil :verify-hostname-error nil :callbacks nil)

Elfeed update failed for https://www.simonsfoundation.org/quanta-archive/feed: (:error (gnutls-error #<process www.simonsfoundation.org> -19))

From http://gnutls.org/manual/html_node/Error-codes.html
-19 GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET An unexpected TLS handshake packet was received.

Default date for RSS entries with no <pubDate> tag

On every RSS update elfeed updates date for entries with no tag to the current date. This leads to such entries to be always "new" that is on the top of elfeed search buffer. It would be nicer if entries with no pubDate preserve the date of when they were fetched the first time.

Idea: allow setting a mode for content part

I have a few feeds that have a clear content type which could be displayed a bit more intelligent in Emacs.

An example is diff-feeds for commit logs or wiki sites, which i use to keep track of what has changed and if it needs my attention or not. Currently these diffs are just displayed as one blob of text. If the mode of the content part could somehow react to it and display it like diff-mode would, including perhaps a limited set of keybindings of that mode, this would make reading that content a lot more pleasant.

Download into zotero

I use elfeed almost exclusively for viewing table of contents from academic journals (via current awareness services from publishers who provide rss feeds). I would like an automatic option to import the link to an article into zotero, parse the metadata and download the corresponding pdf file (if it is downloadable) automatically.

Could you give me any hints on where to start with this?

code to create orgmode links

I have the following in my configuration files.

(defun elfeed-entry-as-html-link ()
  "Store an http link to an elfeed entry"
  (when (equal major-mode 'elfeed-show-mode)
    (let ((description (elfeed-entry-title elfeed-show-entry))
      (link (elfeed-entry-link elfeed-show-entry)))
     (org-store-link-props
      :type "http"
      :link link
      :description description))))

(add-hook 'org-store-link-functions 'elfeed-entry-as-html-link)

This way, when I org-capture in elfeed-show-mode using a template that includes a link, I get a nicely formatted link to the online linked entry. I use this to capture stuff I want to read later. Don't hesitate to use this if you want to integrate this small function to elfeed.

RFE: move point to the first unread feed after syncing

It would be nice if the point was moved to the beginning of the buffer (or the first unread feed) after finishing the sync. Currently, the point is left on the same spot, which could be in the middle of the buffer. Just a small convenience feature.

File index is large (9.9M), really open? a.k.a Tips about db maintenance.

I have currently ~ 550 feeds. (a lot of youtube and vimeo feeds)
Elfeed's db is ~ 526 MiB.

Can you give me some tips about db maintenance?

  • How can I physically remove entries older than X weeks?
  • How can I keep only favorite entries?
  • Maybe we can split elfeed db in two parts - operations and archive?

Any feedback is appreciated before I run out of disk space :)

elfeed-update-feed does not complete

Hi,

I'm facing an issue with updating the majority of my feeds.

  • Each time I try to update one of them with elfeed-update-feed, only one single entry is getting fetched.
    Then I'm getting the following error in my Messages buffer :
Elfeed update failed for http://feeds.mashable.com/Mashable?format=xml: (void-variable feed-title)
  • Re-running the command again lets me fetch the following missing entry, and so on.

Sorry but, wasn't able to find answers using the void-variable / feed-title keywords. Thanks.

Update docstring for elfeed-show-yank in elfeed-show.el

(defun elfeed-show-yank ()
  "Visit the current entry in the browser."
  (interactive)
  (let ((link (elfeed-entry-link elfeed-show-entry)))
    (when link
      (x-set-selection 'PRIMARY link)
      (message "Yanked: %s" link))))

Is the same docstring like in elfeed-show-visit.

Folders

I love elfeed. In my books, it ranks before RSSOwl and QuiteRSS, which are two very fine feed readers.

I miss the option to create folders, though, not only tags. The folder pane could be displayed in a separate window or something like speedbar. Would it be possible to include this?

Better completition in search dialog

I think it would be nice to have better completition in the search dialog (s or S). Specifically, tags could be autocompleted (if the word starts with +/-), also dates (with @) format, for example @2-d could expand to days etc.

To achieve this, it would be necessary to get a list of all existing tags. Is there a simple way to do this? I could try to hack the completition "engine" myself, but I don't understand much how the elfeed database works.

Thanks

Optional and more liberal handling of not well-formed XML (especially ‘&’).

Is it possible to handle not well-formed XML on our side
or at least allow '&'?

If I have some troubles with

Elfeed update failed for http://swannodette.github.com/atom.xml: (error XML: (Not Well-Formed) Invalid entity reference)

then this is almost always ‘&’.

Sometimes content providers do not react properly for notifications to fix not well-formed content.
Disabling feed is a little too harsh solution.
Escape hatch in form of — ok, I will allow ‘&’ — would be helpful in such situations.

http://bitemyapp.com/rss.xml

XML Parsing Error: not well-formed
Location: http://bitemyapp.com/rss.xml
Line Number 11, Column 56:    <title>Parsing and rendering templates in Clojure & Haskell</title>
-------------------------------------------------------^

http://swannodette.github.com/atom.xml

XML Parsing Error: not well-formed
Location: http://swannodette.github.io/atom.xml
Line Number 128, Column 26:   <title>Transit, JSON & ClojureScript</title>
-------------------------^

Add tag in elfeed-show

Adding tags for future reference is quite useful, but at the moment I have to jump back to elfeed-search to elfeed-search-tag-all. Doing it while viewing the post would be better

openssl vs gnutls as tls-program

In emacs we have tls-program variable which defaults to:

(setq tls-program '("gnutls-cli --insecure -p %p %h" "gnutls-cli --insecure -p %p %h --protocols ssl3" "openssl s_client -connect %h:%p -no_ssl2 -ign_eof"))

After changing it for example to:

(setq tls-program '("openssl s_client -connect %h:%p -no_ssl2 -ign_eof"))

and updating some feed with elfeed-update-feed I still can see error like this:
gnutls.c: [0] (Emacs) fatal error: The TLS connection was non-properly terminated.

And here I'm not sure if I really changed to openssl or not?

How can I check if elfeed is using openssl, because I feel that with latter setting (openssl as tls-program) I have less gnutls errors during update.

Additional info:
gnutls-cli 3.3.6
openssl 1.0.1.h-1

HTTP feeds fetched as HTTPS

Problem happens when elfeed fetches simultaneously HTTPS and HTTP feed. Emacs just stucks for a while and update doesn't proceed.

Here is part of backtrace:

Debugger entered--Lisp error: (quit)
  re-search-forward("\\(^    Verify return code: .+\n---\n\\|^- Simple Client Mode:\n\\(\n\\|^\\*\\*\\* Starting TLS handshake\n\\)*\\)" nil t)
  open-tls-stream("feeds2.feedburner.com" #<buffer  *url-http-temp*-69304> "feeds2.feedburner.com" 80)
  network-stream-open-tls("feeds2.feedburner.com" #<buffer  *url-http-temp*-69304> "feeds2.feedburner.com" 80 (:type tls :nowait t))
  open-network-stream("feeds2.feedburner.com" #<buffer  *url-http-temp*-69304> "feeds2.feedburner.com" 80 :type tls :nowait t)
  ... 
  url-retrieve
  ... 
  elfeed--check-queue()
  ... 
  url-http-activate-callback()
  ...
  url-http
  url-https
  ...
  elfeed--check-queue()

Looking at backtrace, I can see that url-open-stream tries to use tls method for port 80 which is cleary invalid and results in my issue. Normally url-open-stream checks for url-gateway-method variable. However this variable is set by url-https down the stack and elfeed--check-queue asks to retreive new HTTP URL with url-gateway-method already set to tls.

One solution I could propose is to reset url-gateway-method to default value but I don't like this approach. Perhaps code that manages queue can be changed in some other way to fix the issue?

BTW what do you think about using url-queue-retrieve?

Wrong type argument: number-or-marker-p, nil

I got this error when trying to open a feed for reading. Here is the backtrace, if it can be of any help:

Debugger entered--Lisp error: (wrong-type-argument number-or-marker-p nil)
  elfeed-insert-link("https://inconsolation.wordpress.com/2014/12/31/bonus-2014-in-review/" "https://inconsolation.wordpress.com/2014/12/31/bonus-2014-in-review/")
  elfeed-show-refresh()
  elfeed-show-entry([cl-struct-elfeed-entry ("http://inconsolation.wordpress.com/feed/" . "http://inconsolation.wordpress.com/?p=8246") "Bonus: 2014 in review" "https://inconsolation.wordpress.com/2014/12/31/bonus-2014-in-review/" 1420036223.0 [cl-struct-elfeed-ref "67d04e1eab49f5c467b6fdb3781317900df9fa78"] html nil (blog) "http://inconsolation.wordpress.com/feed/" nil])
  elfeed-search-show-entry([cl-struct-elfeed-entry ("http://inconsolation.wordpress.com/feed/" . "http://inconsolation.wordpress.com/?p=8246") "Bonus: 2014 in review" "https://inconsolation.wordpress.com/2014/12/31/bonus-2014-in-review/" 1420036223.0 [cl-struct-elfeed-ref "67d04e1eab49f5c467b6fdb3781317900df9fa78"] html nil (blog) "http://inconsolation.wordpress.com/feed/" nil])
  funcall-interactively(elfeed-search-show-entry [cl-struct-elfeed-entry ("http://inconsolation.wordpress.com/feed/" . "http://inconsolation.wordpress.com/?p=8246") "Bonus: 2014 in review" "https://inconsolation.wordpress.com/2014/12/31/bonus-2014-in-review/" 1420036223.0 [cl-struct-elfeed-ref "67d04e1eab49f5c467b6fdb3781317900df9fa78"] html nil (blog) "http://inconsolation.wordpress.com/feed/" nil])
  #<subr call-interactively>(elfeed-search-show-entry nil nil)
  ad-Advice-call-interactively(#<subr call-interactively> elfeed-search-show-entry nil nil)
  apply(ad-Advice-call-interactively #<subr call-interactively> (elfeed-search-show-entry nil nil))
  call-interactively(elfeed-search-show-entry nil nil)
  command-execute(elfeed-search-show-entry)

I'm using GNU Emacs 25.0.50.1.

cannot open the elfeed-show window

Since last package update the command elfeed-search-show-entry does nothing. Digging into the code I have noticed that (elfeed-search-selected :ignore-region) returns nil. Right here, everything was working great. Any ideas ?

semantics of multiple "words" in a filter

Wouldn't it make more sense to test cl-every instead of cl-some in the regular expression match in elfeed-search-filter? You can achieve "or" semantics easily with the \| syntax in regular expression, but it's very difficult to do "match thing having foo and bar in any order anywhere in the title".

Say you are reading lots of webcomics, you might want to "read a comic about thing, but these come in various orders because every artist has the titles set up differently.

Default filter

A really tiny request:

At the moment the default filter is '@6-months-ago +unread' and I quite often just update the feed list, press s, type an additional keyword to filter the results forgetting the space. It does not work, since my keyword gets joined to tag '+unread'.

So, could you please change the default filter to '@6-months-ago +unread ' with a space character at the end.

Search syntax: '+' should mean 'any category'

I my opinion the plus character '+' should match 'any category' in a search string.

I keep trying to reduce key strokes that I repeat a lot. I usually start elfeed session by reading the most common new categories first and for me that is 'Daily News' : '+n'. When I am done with those, I replace that part of the search string with '+j' that lists new science journal feeds. After that I go for the next most numerous category. (They all have one letter codes) Backspacing the search string from '... +n' to '...+' still does not display any articles because '+' has a special meaning to note a category and does not match anything.

However, in practice all articles have some category (default being something like '+read' or but there is no reason to ever show that as a string). Therefore a better semantic for '+' is 'any category'.

In other words, the effect of the following two search strings should be the same:
@1-month-ago +unread +
@1-month-ago +unread

That would allow me to use the former to see the most numerous category, and type in the corresponding one letter category and enter to start reading those articles. ... And it makes more semantic sense, at least to me.

Disable undo in *elfeed-search*?

I recently received a warning about the size of the buffer undo list in *elfeed-search*.

I added buffer-disable-undo to my elfeed-search-mode-hook and haven't seen any ill effects. However, I'm not very knowledgeable about Emacs's undo system. (My due diligence consisted entirely of a quick grep through elfeed's source for any references to "undo").

Do you know if disabling undo like that in the search buffer is safe/reasonable? Are there any downsides to be aware of?

Thanks - elfeed is a great package.

Feed results in hanging up emacs

(Edit: I'm getting rid of the byte-code stuff as github does not like it).

When I try to update this feed https://www.gaslampgames.com/feed/ an exception is triggered then emacs hangs, until I manage to "C-c" or "C-g" a few times.

This is the backtrace I'm getting:

Debugger entered--Lisp error: (error "gaslampgames.comfeed/443 nodename nor servname provided, or not known")
  make-network-process(:name "gaslampgames.comfeed" :buffer #<buffer  *url-http-temp*> :host "gaslampgames.comfeed" :service 443 :nowait nil)
  open-network-stream("gaslampgames.comfeed" #<buffer  *url-http-temp*> "gaslampgames.comfeed" 443)
  open-gnutls-stream("gaslampgames.comfeed" #<buffer  *url-http-temp*> "gaslampgames.comfeed" 443)
  network-stream-open-tls("gaslampgames.comfeed" #<buffer  *url-http-temp*> "gaslampgames.comfeed" 443 (:type tls :nowait t))
  open-network-stream("gaslampgames.comfeed" #<buffer  *url-http-temp*> "gaslampgames.comfeed" 443 :type tls :nowait t)
  byte-code("..." [coding-system-for-write coding-system-for-read gw-method name buffer host binary (tls ssl native) native plain open-network-stream :type :nowait featurep make-network-process (:nowait t) socks socks-open-network-stream telnet url-open-telnet rlogin url-open-rlogin error "Bad setting of url-gateway-method: %s" service url-gateway-method conn] 11)
  url-open-stream("gaslampgames.comfeed" #<buffer  *url-http-temp*> "gaslampgames.comfeed" 443)
  url-http-find-free-connection("gaslampgames.comfeed" 443)
  url-http([cl-struct-url "https" nil nil "gaslampgames.comfeed" nil "/" nil nil t :silent t] #[..." [..." ["http://gaslampgames.com/feed/" print-escape-newlines :error t message "Elfeed update failed for %s: %S" err funcall make-byte-code 0 " ... vconcat vector [url-http-end-of-headers set-buffer-multibyte t elfeed-xml-parse-region elfeed-feed-type eql :atom elfeed-entries-from-atom :rss elfeed-entries-from-rss :rss1\.0 elfeed-entries-from-rss1\.0 error "Unknown feed type." elfeed-db-add] 5 "\n\n(fn)" error 257 "\..." [message "Elfeed update failed for %s: %s"] "\n\n(fn ERROR)" kill-buffer] 11 "\n\n(fn STATUS)"] funcall make-byte-code 0 "..." vconcat vector [elfeed-connections cl-delete :key car elfeed--check-queue] 5 "\n\n(fn)"] 8 "\n\n(fn STATUS)"] ((:redirect "https://gaslampgames.comfeed/")))
  url-https([cl-struct-url "https" nil nil "gaslampgames.comfeed" nil "/" nil nil t :silent t] #[..." ["http://gaslampgames.com/feed/" print-escape-newlines :error t message "Elfeed update failed for %s: %S" err funcall make-byte-code 0 "  ..." vconcat vector [url-http-end-of-headers set-buffer-multibyte t elfeed-xml-parse-region elfeed-feed-type eql :atom elfeed-entries-from-atom :rss elfeed-entries-from-rss :rss1\.0 elfeed-entries-from-rss1\.0 error "Unknown feed type." elfeed-db-add] 5 "\n\n(fn)" error 257 "..." [message "Elfeed update failed for %s: %s"] "\n\n(fn ERROR)" kill-buffer] 11 "\n\n(fn STATUS)"] funcall make-byte-code 0 "..." vconcat vector [elfeed-connections cl-delete :key car elfeed--check-queue] 5 "\n\n(fn)"] 8 "\n\n(fn STATUS)"] ((:redirect "https://gaslampgames.comfeed/")))
  url-retrieve-internal("https://gaslampgames.comfeed/" #[257 "..." ["http://gaslampgames.com/feed/" print-escape-newlines :error t message "Elfeed update failed for %s: %S" err funcall make-byte-code 0 "    ..." vconcat vector [url-http-end-of-headers set-buffer-multibyte t elfeed-xml-parse-region elfeed-feed-type eql :atom elfeed-entries-from-atom :rss elfeed-entries-from-rss :rss1\.0 elfeed-entries-from-rss1\.0 error "Unknown feed type." elfeed-db-add] 5 "\n\n(fn)" error 257 "..." [message "Elfeed update failed for %s: %s"] "\n\n(fn ERROR)" kill-buffer] 11 "\n\n(fn STATUS)"] funcall make-byte-code 0 "..." vconcat vector [elfeed-connections cl-delete :key car elfeed--check-queue] 5 "\n\n(fn)"] 8 "\n\n(fn STATUS)"] ((:redirect "https://gaslampgames.comfeed/")) :silent nil)
  url-http-parse-headers()
  url-http-content-length-after-change-function(279 599 320)
  url-http-wait-for-headers-change-function(1 609 608)
  url-http-generic-filter(#<process gaslampgames.com> "HTTP/1.1 301 Moved Permanently
\nDate: Sun, 13 Jul 2014 08:26:57 GMT
\nServer: Apache/2.2.22 (Debian)
\nLocation: https://gaslampgames.comfeed/
\nVary: Accept-Encoding
\nContent-Length: 319
\nKeep-Alive: timeout=5, max=100
\nConnection: Keep-Alive
\nContent-Type: text/html; charset=iso-8859-1
\n
\n<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n<title>301 Moved Permanently</title>\n</head><body>\n<h1>Moved Permanently</h1>\n<p>The document has moved <a href=\"https://gaslampgames.comfeed/\">here</a>.</p>\n<hr>\n<address>Apache/2.2.22 (Debian) Server at gaslampgames.com Port 80</address>\n</body></html>\n")

I find the missing / in the redirection strange. When I nagivate to the https://www.gaslampgames.com/feed/ url using Firefox, it's showing me a feed and proposing to subscribe to it.

Is this a bug in elfeed or in their feed?

Unwanted interrupts

If I press C-g for any reason while elfeed is updating, I will get a (:error (error "Transfer interrupted!")). The solution is to wrap the callbacks, or at least some portions with

(let ((inhibit-quit t)) 
  ;; ...
)

Obviously the code inside this section must never hang.

Update failures

Updating some of my feeds fails with:

Elfeed update failed for http://www.drdobbs.com/rss/all: (:error (error connection-failed "failed with code 101\n" :host "www.drdobbs.com" :service 80))
Elfeed update failed for http://www.drdobbs.com/rss/all: (:error (error connection-failed "deleted\n" :host "www.drdobbs.com" :service 80) :error (error connection-failed "failed with code 101\n" :host "www.drdobbs.com" :service 80))
Elfeed update failed for http://wz2100.net/news/feeds/atom/: (:error (error connection-failed "failed with code 101\n" :host "wz2100.net" :service 80))
Elfeed update failed for http://wz2100.net/news/feeds/atom/: (:error (error connection-failed "deleted\n" :host "wz2100.net" :service 80) :error (error connection-failed "failed with code 101\n" :host "wz2100.net" :service 80))
Elfeed update failed for http://feeds.feedburner.com/Phoronix: (:error (error connection-failed "failed with code 101\n" :host "feeds.feedburner.com" :service 80))
Elfeed update failed for http://feeds.feedburner.com/Phoronix: (:error (error connection-failed "deleted\n" :host "feeds.feedburner.com" :service 80) :error (error connection-failed "failed with code 101\n" :host "feeds.feedburner.com" :service 80))

They all work well when viewed from Firefox or when fetched via Thunderbird.

n and p don't move up/down in the search view

The docs say that n/p and will move to the next/previous entry. That didn't work for me. Here is the output of C-h m:

Major mode for listing elfeed feed entries.
key             binding
---             -------

RET     elfeed-search-show-entry
+       elfeed-search-tag-all
-       elfeed-search-untag-all
0 .. 9      digit-argument
G       elfeed-update
b       elfeed-search-browse-url
g       ??
q       quit-window
r       ??
s       elfeed-search-set-filter
u       ??
y       elfeed-search-yank
<remap>     Prefix Command

Looking at the keymap, it seems that anything defined to do next and previous. Also, it looks like anything defined using the pattern here:

(define-key map "u" (elfeed-expose #'elfeed-search-tag-all 'unread))

Doesn't end up working.

I might be misunderstanding the docs as n/p does work when viewing an entry.

Contents from <link></link> should be trimmed

I subscribed to http://www.echojs.com/rss and found that URL opening is not working in elfeed.

This feed has item format like this:

<item><title>
VVVV.js
</title>
 <guid>http://www.vvvvjs.com/</guid> <link>
http://www.vvvvjs.com/
</link>
 <description><![CDATA[<a href="http://www.echojs.com/news/9782">Comments</a>]]></description> <comments>http://www.echojs.com/news/9782</comments></item>

Improve reading of feeds with story arcs

Since the r, b, u, and RET hotkeys move the point to the next line, It's most efficient to start with your point on the first entry and work downwards. This leads to reading the most recent posts first, which is undesirable when reading through a feed for something like a webcomic with a story arc. You wouldn't start reading a comic book from back to front, would you?

To accommodate this use-case, we could add the option of sorting search results by date, ascending/descending. Although, I suspect a much easier solution would be to let the user decide which way the point moves after pressing one of the hotkeys, so I can start with my point at the bottom.

How can I interrupt feed update when it's stuck (without restarting emacs)?

When I update my feeds, the updating sometimes gets stuck (nothing happens after a while, and the status text remains at "89 feeds pending, 1 in process ...").

I've tried doing C-g, q, or killing the buffer, but I found the only way to quit the update process is to restart emacs. Is there a better way?

search function

Sorry for this generic question. After playing a little with elfeed I could not figure out if there is a possibility to seach inside the feed. As I am using for 2/3 feeds from journal, it would be really useful to search inside the abstract.

add a flag to show the entire link, whatever the window size

it would be nice to have a way to force elfeed to always show the entire link. i often use emacs on the command line and use an external link grabber, which only works if the entire link is shown.
this would probably necessitate a small change in elfeed-insert-link, to show either the entire url or do as it does now.

thanks for elfeed, using it daily!

Elfeed: libxml2 functionality is unavailable

Hello,

Configured elfeed for emacs, got rss, after i'm trying to open any rss feed, got following error:

Elfeed: libxml2 functionality is unavailable

Emacs configured with libxml2 support:

Does Emacs use -lxml2? yes

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.