feed.nvim is a web feed reader in Neovim.
Warning
This project is young, expect breaking changes, and for now there's a nasty bug if you are on neovim stable #125, recommand to use nightly or wait for the coming release of 0.11
other than that usage should be fun and smooth, go ahead and enjoy!
- ๐ฒ Fast and reliable rss/atom/json feed feed parsing, powered by tree-sitter
- ๐ View entries as beautiful markdown powered by pandoc
- ๐ช Lua database with no extra dependency
- ๐ Powerful entry searching by date, tag, feed, regex, and fulltext
- ๐ OPML support to import and export all your feeds and podcasts
- ๐งก RSShub integration to discover and track everything
Github integration to subscrbe to the new commits/release of your favorite repo/plugin
- ๐ถ libuv powered feed server with a web interface
- ๐ก support for popular feed sync services like Tiny Tiny RSS and Fresh RSS
For rocks.nvim:
:Rocks install feed.nvim
For lazy.nvim:
{ "neo451/feed.nvim", cmd = "Feed" }
- run
:checkhealth feed
to see your installation status - read tutorial below or read
:h feed.txt
To execute actions available in the current context, or give arguments to the command, use the following syntax:
Use :Feed <Tab>
, :Feed update_feed <Tab>
to get the completion
Use :Feed<Enter>
, :Feed update_feed<Enter>
to open menu and select
name | desc | bang |
---|---|---|
Feed <query> |
opens a index buffer, a list view based on the filter you passed in | no |
Feed index |
opens a index buffer, a list view based on your default filter | no |
Feed entry |
opens a entry buffer, a markdown view of the entry content | no |
Feed update |
updates all feeds in the database | no |
Feed update_feed <feed_url> |
update a single feed in the database | no |
Feed sync |
sync the database with your config, removes feeds and entries (if bang) not present | yes |
Feed search <query> |
opens picker to live search your database | no |
Feed grep |
opens picker to live grep your database (experimental) | no |
Feed list |
opens a split to show info about all your feeds in database | no |
Feed log |
opens a split to show log | no |
Feed load_opml <filepath/url> |
import from an OPML file or url | no |
Feed export_opml <filepath> |
export to an OPML file | no |
Feed web <port> |
opens a server on a port and opens the web interface in browser | no |
Feed urlview |
opens a select UI to picker urls in entry buffer, to open in browser | no |
By default, feed.nvim will not set any keymaps for you, press ?
in to see buffer-local keymaps.
action | key |
---|---|
hints | ? |
dot_repeat | . |
undo | u |
redo | <C-r> |
entry | <CR> |
split | <M-CR> |
browser | b |
refresh | r |
update | R |
search | s |
yank_url | Y |
untag | - |
tag | + |
quit | q |
action | key |
---|---|
hints | ? |
browser | b |
next | } |
prev | { |
full | f |
search | s |
untag | - |
tag | + |
urlview | r |
yank_url | Y |
quit | q |
Pass your feeds as list of links and tags in setup
Use Feed update
to update all
Use Feed update_feed
to update one feed
require("feed").setup({
feeds = {
-- These two styles both work
"https://neovim.io/news.xml",
{
"https://neovim.io/news.xml",
name = "Neovim News",
tags = { "tech", "news" }, -- tags given are inherited by all its entries
},
-- three link formats:
"https://neovim.io/news.xml", -- Regular links
"rsshub://rsshub://apnews/topics/apf-topnews" -- RSSHub links
"neovim/neovim/releases" -- GitHub links
},
})
Use Feed load_opml
to import your OPML file
Use Feed export_opml
to export your OPML file to load in other readers
Must start with http
or https
RSSHub links are first class citizens, format is rsshub://{route}
rsshub://{route}
will be resolved when fetching according to your config
Discover available {route}
in RSSHub documentation
rsshub://apnews/topics/apf-topnews
will be resolved to https://rsshub.app/apnews/topics/apf-topnews
by default
Config example:
require("feed").setup({
rsshub = {
instance = "127.0.0.1:1200", -- or any public instance listed here https://rsshub.netlify.app/instances
export = "https://rsshub.app", -- used in export_opml
},
})
GitHub user/repo links are also first class citizens,format is [github://]{user/repo}[{/releases|/commits}]
, so following four all work:
neo451/feed.nvim
github://neo451/feed.nvim
neo451/feed.nvim/releases
github://neo451/feed.nvim/releases
For now it defaults to subscribing to the commits
So first two is resolved into https://github.com/neo451/feed.nvim/commits.atom
Latter two is resolved into https://github.com/neo451/feed.nvim/releases.atom
- use
Feed search
to filter your feeds - you can also pass the query like
Feed =neovim +read
- the default query when you open up the index buffer is
+unread @2-weeks-ago
- no modifier matches entry title or entry url
!
is negative match with entry title or url=
is matching feed name and feed url~
is not matching feed name and feed url- these all respect your
ignorecase
option
+
meansmust_have
, searches entries' tags-
meansmust_not_have
, searches entries' tags
@
meansdate
, searches entries' date2015-8-10
searches only entries after the date2-months-ago
searches only entries within two months from now1-year-ago--6-months-ago
means entries in the period
#
meanslimit
, limits the number of entries
+blog +unread -star @6-months-ago #10 zig !rust
Only Shows 10 entries with tags blog and unread, without tag star, and are published within 6 month, making sure they have zig but not rust in the title.
@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 !n\=vim
Only show unread entries not having vim or nvim in the title or link.
+emacs =http://example.org/feed/
Only show entries tagged as emacs from a specific feed.
Use Feed grep
to live grep all entries in your database,
requires rg
and one of the search backends:
telescope
fzf-lua
mini.pick
Change the highlight of the tags section and use emojis and mini.icons for tags
require("feed").setup({
ui = {
tags = {
color = "String",
format = function(id, db)
local icons = {
news = "๐ฐ",
tech = "๐ป",
movies = "๐ฌ",
games = "๐ฎ",
music = "๐ต",
podcast = "๐ง",
books = "๐",
unread = "๐",
read = "โ
",
junk = "๐ฎ",
star = "โญ",
}
local get_icon = function(name)
if icons[name] then
return icons[name]
end
local has_mini, MiniIcons = pcall(require, "mini.icons")
if has_mini then
local icon = MiniIcons.get("filetype", name)
if icon then
return icon .. " "
end
end
return name
end
local tags = vim.tbl_map(get_icon, db:get_tags(id))
table.sort(tags)
return "[" .. table.concat(tags, ", ") .. "]"
end,
},
},
})
Custom function & keymap for podcast and w3m
local function play_podcast()
local link = require("feed").get_entry().link
if link:find("mp3") then
vim.ui.open(link)
-- any other player like:
-- vim.system({ "vlc.exe", link })
else
vim.notify("not a podcast episode")
end
end
local function show_in_w3m()
if not vim.fn.executable("w3m") then
vim.notify("w3m not installed")
return
end
local link = require("feed").get_entry().link
local w3m = require("feed.ui.window").new({
relative = "editor",
col = math.floor(vim.o.columns * 0.1),
row = math.floor(vim.o.lines * 0.1),
width = math.floor(vim.o.columns * 0.8),
height = math.floor(vim.o.lines * 0.8),
border = "rounded",
style = "minimal",
title = "Feed w3m",
zindex = 10,
})
vim.keymap.set({ "n", "t" }, "q", "<cmd>q<cr>", { silent = true, buffer = w3m.buf })
vim.fn.jobstart({ "w3m", link }, { term = true })
vim.cmd("startinsert")
end
require("feed").setup({
keys = {
index = {
[play_podcast] = "p",
[show_in_w3m] = "w",
},
},
})
Custom colorscheme only set when viewing feeds
local og_color
vim.api.nvim_create_autocmd("User", {
pattern = "FeedShowIndex",
callback = function()
if not og_color then
og_color = vim.g.colors_name
end
vim.cmd.colorscheme("kanagawa-lotus")
end,
})
vim.api.nvim_create_autocmd("User", {
pattern = "FeedQuitIndex",
callback = function()
vim.cmd.colorscheme(og_color)
end,
})
:TODO: