rutt 0.3.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +1 -0
- data/Gemfile.lock +3 -0
- data/VERSION +1 -1
- data/bin/rutt +14 -12
- data/lib/rutt.rb +9 -8
- data/lib/rutt/db/config.rb +25 -0
- data/lib/rutt/db/feed.rb +75 -0
- data/lib/rutt/db/item.rb +43 -0
- data/lib/rutt/screen.rb +38 -36
- data/lib/rutt/screen/content.rb +64 -0
- data/lib/rutt/screen/feed.rb +95 -0
- data/lib/rutt/screen/item.rb +105 -0
- data/lib/rutt/{instapaper.rb → share/instapaper.rb} +0 -0
- data/rutt.gemspec +12 -9
- metadata +34 -20
- data/lib/rutt/config.rb +0 -23
- data/lib/rutt/content_screen.rb +0 -57
- data/lib/rutt/feed.rb +0 -74
- data/lib/rutt/feed_screen.rb +0 -93
- data/lib/rutt/item.rb +0 -40
- data/lib/rutt/item_screen.rb +0 -103
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -26,6 +26,8 @@ GEM
|
|
26
26
|
diff-lcs (~> 1.1.2)
|
27
27
|
rspec-mocks (2.3.0)
|
28
28
|
ruby-feedparser (0.7)
|
29
|
+
ruby-readability (0.2.3)
|
30
|
+
nokogiri (>= 1.4.2)
|
29
31
|
sqlite3 (1.3.3)
|
30
32
|
|
31
33
|
PLATFORMS
|
@@ -42,4 +44,5 @@ DEPENDENCIES
|
|
42
44
|
rcov
|
43
45
|
rspec (~> 2.3.0)
|
44
46
|
ruby-feedparser
|
47
|
+
ruby-readability
|
45
48
|
sqlite3
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.0
|
data/bin/rutt
CHANGED
@@ -14,6 +14,8 @@ require 'feedparser'
|
|
14
14
|
require 'parallel'
|
15
15
|
require 'instapaper'
|
16
16
|
require 'oauth'
|
17
|
+
require 'readability'
|
18
|
+
require 'open-uri'
|
17
19
|
|
18
20
|
require 'rutt'
|
19
21
|
|
@@ -30,7 +32,7 @@ def start_screen
|
|
30
32
|
|
31
33
|
stdscr.clear
|
32
34
|
|
33
|
-
feed_screen = Rutt::
|
35
|
+
feed_screen = Rutt::Screen::Feed.new(stdscr)
|
34
36
|
feed_screen.loop
|
35
37
|
ensure
|
36
38
|
Ncurses.endwin()
|
@@ -39,21 +41,21 @@ end
|
|
39
41
|
|
40
42
|
def main
|
41
43
|
|
42
|
-
Rutt::Config.make_table!
|
43
|
-
Rutt::Feed.make_table!
|
44
|
-
Rutt::Item.make_table!
|
44
|
+
Rutt::DB::Config.make_table!
|
45
|
+
Rutt::DB::Feed.make_table!
|
46
|
+
Rutt::DB::Item.make_table!
|
45
47
|
|
46
48
|
options = {}
|
47
49
|
OptionParser.new do |opts|
|
48
50
|
opts.banner = "Usage: rutt.rb [options]"
|
49
51
|
|
50
52
|
opts.on('-a', '--add FEED', "Add a feed") do |url|
|
51
|
-
Rutt::Feed::add(url)
|
53
|
+
Rutt::DB::Feed::add(url)
|
52
54
|
exit
|
53
55
|
end
|
54
56
|
|
55
57
|
opts.on('-r', '--refresh', "Refresh feeds.") do
|
56
|
-
Rutt::Feed::refresh
|
58
|
+
Rutt::DB::Feed::refresh
|
57
59
|
exit
|
58
60
|
end
|
59
61
|
|
@@ -62,14 +64,14 @@ def main
|
|
62
64
|
|
63
65
|
urls.each do |url|
|
64
66
|
puts "Adding #{url}"
|
65
|
-
Rutt::Feed::add(url, false)
|
67
|
+
Rutt::DB::Feed::add(url, false)
|
66
68
|
end
|
67
69
|
|
68
70
|
exit
|
69
71
|
end
|
70
72
|
|
71
73
|
opts.on('-s', '--set-key', "Set config") do |key, value|
|
72
|
-
Rutt::Config.set(ARGV[0], ARGV[1])
|
74
|
+
Rutt::DB::Config.set(ARGV[0], ARGV[1])
|
73
75
|
exit
|
74
76
|
end
|
75
77
|
|
@@ -77,10 +79,10 @@ def main
|
|
77
79
|
|
78
80
|
end.parse!
|
79
81
|
|
80
|
-
consumer_key = Rutt::Config.get("instapaper.consumer-key")
|
81
|
-
consumer_secret = Rutt::Config.get("instapaper.consumer-secret")
|
82
|
-
username = Rutt::Config.get("instapaper.username")
|
83
|
-
password = Rutt::Config.get("instapaper.password")
|
82
|
+
consumer_key = Rutt::DB::Config.get("instapaper.consumer-key")
|
83
|
+
consumer_secret = Rutt::DB::Config.get("instapaper.consumer-secret")
|
84
|
+
username = Rutt::DB::Config.get("instapaper.username")
|
85
|
+
password = Rutt::DB::Config.get("instapaper.password")
|
84
86
|
|
85
87
|
$instapaper = Rutt::Instapaper::API.new(consumer_key, consumer_secret)
|
86
88
|
$instapaper.authorize(username, password)
|
data/lib/rutt.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
|
-
require 'rutt/config'
|
2
|
-
require 'rutt/
|
3
|
-
require 'rutt/
|
4
|
-
require 'rutt/feed'
|
5
|
-
require 'rutt/item'
|
1
|
+
require 'rutt/db/config'
|
2
|
+
require 'rutt/db/feed'
|
3
|
+
require 'rutt/db/item'
|
6
4
|
require 'rutt/screen'
|
7
|
-
require 'rutt/
|
8
|
-
require 'rutt/
|
9
|
-
require 'rutt/
|
5
|
+
require 'rutt/screen/feed'
|
6
|
+
require 'rutt/screen/item'
|
7
|
+
require 'rutt/screen/content'
|
8
|
+
require 'rutt/share/instapaper'
|
9
|
+
require 'rutt/opml'
|
10
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Rutt
|
2
|
+
module DB
|
3
|
+
module Config
|
4
|
+
extend self
|
5
|
+
|
6
|
+
def make_table!
|
7
|
+
$db.execute(%{
|
8
|
+
create table if not exists config (
|
9
|
+
id integer PRIMARY KEY,
|
10
|
+
key text,
|
11
|
+
value text,
|
12
|
+
UNIQUE(key))
|
13
|
+
})
|
14
|
+
end
|
15
|
+
|
16
|
+
def get(key)
|
17
|
+
$db.get_first_value("select value from config where key = ?", key)
|
18
|
+
end
|
19
|
+
|
20
|
+
def set(key, value)
|
21
|
+
$db.execute("insert or replace into config(key, value) values (?, ?)", key, value)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/rutt/db/feed.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
module Rutt
|
2
|
+
module DB
|
3
|
+
module Feed
|
4
|
+
extend self
|
5
|
+
|
6
|
+
def make_table!
|
7
|
+
$db.execute(%{
|
8
|
+
create table if not exists feeds (
|
9
|
+
id integer PRIMARY KEY,
|
10
|
+
title text,
|
11
|
+
url text,
|
12
|
+
update_interval integer default 3600,
|
13
|
+
created_at NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
14
|
+
updated_at NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
15
|
+
UNIQUE(url))
|
16
|
+
})
|
17
|
+
end
|
18
|
+
|
19
|
+
def add(url, refresh=true)
|
20
|
+
$db.execute("insert or ignore into feeds (url) values ('#{url}')")
|
21
|
+
$db.execute("select * from feeds where id = (select last_insert_rowid())") do |feed|
|
22
|
+
refresh_for(feed)
|
23
|
+
end if refresh
|
24
|
+
end
|
25
|
+
|
26
|
+
def get(id)
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
def delete(feed)
|
31
|
+
$db.execute("delete from items where feed_id = ?", feed['id'])
|
32
|
+
$db.execute("delete from feeds where id = ?", feed['id'])
|
33
|
+
end
|
34
|
+
|
35
|
+
def all(min_limit=0, max_limit=-1)
|
36
|
+
$db.execute(%{
|
37
|
+
select f.*,
|
38
|
+
(select count(*) from items iu where iu.feed_id = f.id) as num_items,
|
39
|
+
(select count(*) from items ir where ir.read = 0 and ir.feed_id = f.id) as unread
|
40
|
+
from feeds f where unread > 0 order by id desc limit #{min_limit},#{max_limit}
|
41
|
+
})
|
42
|
+
end
|
43
|
+
|
44
|
+
def refresh
|
45
|
+
feeds = $db.execute("select * from feeds")
|
46
|
+
results = Parallel.map(feeds, :in_threads => 8) do |feed|
|
47
|
+
refresh_for(feed)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def refresh_for(feed)
|
52
|
+
content = open(feed['url']).read
|
53
|
+
rss = FeedParser::Feed::new(content)
|
54
|
+
|
55
|
+
puts rss.title
|
56
|
+
|
57
|
+
$db.execute("update feeds set title = ? where id = ?", rss.title, feed['id'])
|
58
|
+
|
59
|
+
rss.items.each do |item|
|
60
|
+
$db.execute("insert or ignore into items (feed_id, title, url, published_at) values (?, ?, ?, ?)", feed['id'], item.title, item.link, item.date.to_i)
|
61
|
+
end
|
62
|
+
rescue Exception => e
|
63
|
+
# no-op
|
64
|
+
end
|
65
|
+
|
66
|
+
def unread(feed_id)
|
67
|
+
$db.execute("select * from items where feed_id = ? and read = 0", feed)
|
68
|
+
end
|
69
|
+
|
70
|
+
def mark_as_read(feed)
|
71
|
+
$db.execute("update items set read = 1 where feed_id = ?", feed['id'])
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/lib/rutt/db/item.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
module Rutt
|
2
|
+
module DB
|
3
|
+
module Item
|
4
|
+
|
5
|
+
extend self
|
6
|
+
|
7
|
+
def make_table!
|
8
|
+
$db.execute(%{
|
9
|
+
create table if not exists items (
|
10
|
+
id integer PRIMARY KEY,
|
11
|
+
feed_id integer,
|
12
|
+
title text,
|
13
|
+
url text,
|
14
|
+
description text,
|
15
|
+
read int default 0,
|
16
|
+
prioritize int default 0,
|
17
|
+
published_at DATE NOT NULL DEFAULT (datetime('now','localtime')),
|
18
|
+
created_at NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
19
|
+
updated_at NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
20
|
+
UNIQUE(url),
|
21
|
+
FOREIGN KEY(feed_id) REFERENCES feeds(id))
|
22
|
+
})
|
23
|
+
end
|
24
|
+
|
25
|
+
def all(feed, min_limit=0, max_limit=-1)
|
26
|
+
$db.execute("select * from items where feed_id = ? order by published_at desc limit #{min_limit},#{max_limit}", feed['id'])
|
27
|
+
end
|
28
|
+
|
29
|
+
def mark_as_unread(item)
|
30
|
+
$db.execute("update items set read = 0 where id = #{item['id']}")
|
31
|
+
end
|
32
|
+
|
33
|
+
def mark_as_read(item)
|
34
|
+
$db.execute("update items set read = 1 where id = #{item['id']}")
|
35
|
+
end
|
36
|
+
|
37
|
+
# Weak abstraction.
|
38
|
+
def sent_to_instapaper(item)
|
39
|
+
$db.execute("update items set read = 2 where id = #{item['id']}")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/rutt/screen.rb
CHANGED
@@ -1,51 +1,53 @@
|
|
1
1
|
module Rutt
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
module Screen
|
3
|
+
class Base
|
4
|
+
def initialize(stdscr)
|
5
|
+
@stdscr = stdscr
|
5
6
|
|
6
|
-
|
7
|
-
|
7
|
+
@min_y = 1
|
8
|
+
@max_y = @stdscr.getmaxy
|
8
9
|
|
9
|
-
|
10
|
-
|
10
|
+
@min_limit = @min_y - 1
|
11
|
+
@max_limit = @max_y - 5
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
13
|
+
@cur_y = 1
|
14
|
+
@cur_x = 0
|
15
|
+
end
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
def incr_page
|
18
|
+
@min_limit = @max_limit
|
19
|
+
@max_limit += (@max_y - 5)
|
20
|
+
end
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
def decr_page
|
23
|
+
@max_limit = @min_limit
|
24
|
+
@min_limit -= (@max_y - 5)
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
|
26
|
+
if @max_limit <= 0
|
27
|
+
@min_limit = @min_y - 1
|
28
|
+
@max_limit = @max_y - 5
|
29
|
+
end
|
28
30
|
end
|
29
|
-
end
|
30
31
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
32
|
+
def display_menu
|
33
|
+
@stdscr.clear
|
34
|
+
@stdscr.move(0, 0)
|
35
|
+
@stdscr.addstr(" rutt #{@menu}\n")
|
36
|
+
end
|
36
37
|
|
37
|
-
|
38
|
-
|
39
|
-
|
38
|
+
def move_pointer(pos, move_to=false)
|
39
|
+
@stdscr.move(@cur_y, 0)
|
40
|
+
@stdscr.addstr(" ")
|
40
41
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
42
|
+
if move_to == true
|
43
|
+
@cur_y = pos
|
44
|
+
else
|
45
|
+
@cur_y += pos
|
46
|
+
end
|
46
47
|
|
47
|
-
|
48
|
-
|
48
|
+
@stdscr.move(@cur_y, 0)
|
49
|
+
@stdscr.addstr(">")
|
50
|
+
end
|
49
51
|
end
|
50
52
|
end
|
51
53
|
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Rutt
|
2
|
+
module Screen
|
3
|
+
class Content < Base
|
4
|
+
def initialize(stdscr, item)
|
5
|
+
@item = item
|
6
|
+
@menu = "i:back b:open in browser"
|
7
|
+
|
8
|
+
super(stdscr)
|
9
|
+
end
|
10
|
+
|
11
|
+
def display_content
|
12
|
+
# @content = `elinks -dump -dump-charset ascii -force-html #{@item['url']}`
|
13
|
+
source = open(@item['url']).read
|
14
|
+
content = Nokogiri::HTML(::Readability::Document.new(source).content).text
|
15
|
+
|
16
|
+
@content = content.split("\n").map do |s|
|
17
|
+
s.gsub(/.{0,74}(?:\s|\Z)/){($& + 5.chr).gsub(/\n\005/,"\n")}.gsub(/((\n|^)[>|\s]*[>|].*?)\005/, "\\1").gsub(/\005/,"\n").split("\n") << "\n"
|
18
|
+
end.flatten
|
19
|
+
|
20
|
+
@stdscr.addstr(" #{@item['title']} (#{@item['url']})\n\n")
|
21
|
+
|
22
|
+
lines = @content[@min_limit..@max_limit]
|
23
|
+
lines.each { |line| @stdscr.addstr(" #{line}\n") } if lines
|
24
|
+
|
25
|
+
@stdscr.refresh
|
26
|
+
end
|
27
|
+
|
28
|
+
def window
|
29
|
+
@stdscr.clear
|
30
|
+
display_menu
|
31
|
+
display_content
|
32
|
+
end
|
33
|
+
|
34
|
+
def loop
|
35
|
+
@cur_line = 0
|
36
|
+
|
37
|
+
window
|
38
|
+
|
39
|
+
while true do
|
40
|
+
c = @stdscr.getch
|
41
|
+
if c > 0 && c < 255
|
42
|
+
case c.chr
|
43
|
+
when /[iq]/i
|
44
|
+
DB::Item::mark_as_read(@item)
|
45
|
+
break
|
46
|
+
when /b/i
|
47
|
+
Launchy.open(@item['url'])
|
48
|
+
end
|
49
|
+
else
|
50
|
+
case c
|
51
|
+
when Ncurses::KEY_UP
|
52
|
+
decr_page
|
53
|
+
window
|
54
|
+
when Ncurses::KEY_DOWN
|
55
|
+
incr_page
|
56
|
+
window
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module Rutt
|
2
|
+
module Screen
|
3
|
+
class Feed < Base
|
4
|
+
def initialize(stdscr)
|
5
|
+
@menu = "q:Quit d:delete r:refresh all"
|
6
|
+
|
7
|
+
super(stdscr)
|
8
|
+
end
|
9
|
+
|
10
|
+
def display_feeds
|
11
|
+
@cur_y = @min_y
|
12
|
+
|
13
|
+
@feeds = DB::Feed::all(@min_limit, @max_limit)
|
14
|
+
@feeds.each do |feed|
|
15
|
+
# next if feed['unread'] == 0 # This should be configurable: feed.showread
|
16
|
+
|
17
|
+
@stdscr.move(@cur_y, 0)
|
18
|
+
@stdscr.addstr(" #{feed['unread']}/#{feed['num_items']}\t\t#{feed['title']}\n")
|
19
|
+
|
20
|
+
@cur_y += 1
|
21
|
+
end
|
22
|
+
|
23
|
+
@cur_y = @min_y
|
24
|
+
@stdscr.refresh
|
25
|
+
end
|
26
|
+
|
27
|
+
def window
|
28
|
+
@stdscr.clear
|
29
|
+
|
30
|
+
display_menu
|
31
|
+
display_feeds
|
32
|
+
move_pointer(0)
|
33
|
+
end
|
34
|
+
|
35
|
+
def loop
|
36
|
+
window
|
37
|
+
|
38
|
+
while true do
|
39
|
+
c = @stdscr.getch
|
40
|
+
|
41
|
+
if c > 0 && c < 255
|
42
|
+
case c.chr
|
43
|
+
when /q/i
|
44
|
+
break
|
45
|
+
when /a/i
|
46
|
+
# no-op
|
47
|
+
when /r/i
|
48
|
+
cur_y = @cur_y
|
49
|
+
|
50
|
+
DB::Feed::refresh
|
51
|
+
|
52
|
+
window
|
53
|
+
move_pointer(cur_y, move_to=true)
|
54
|
+
when /d/i
|
55
|
+
cur_y = @cur_y - 1
|
56
|
+
|
57
|
+
@stdscr.clear
|
58
|
+
display_menu
|
59
|
+
feed = @feeds[cur_y]
|
60
|
+
@stdscr.move(2, 0)
|
61
|
+
@stdscr.addstr("Are you sure you want to delete #{feed['title']}? ")
|
62
|
+
d = @stdscr.getch
|
63
|
+
if d.chr =~ /y/i
|
64
|
+
DB::Feed::delete(feed)
|
65
|
+
end
|
66
|
+
window
|
67
|
+
move_pointer(cur_y, move_to=true)
|
68
|
+
when /p/i
|
69
|
+
decr_page
|
70
|
+
window
|
71
|
+
when /n/i
|
72
|
+
incr_page
|
73
|
+
window
|
74
|
+
when / /
|
75
|
+
cur_y = @cur_y
|
76
|
+
@stdscr.addstr("#{@feeds[cur_y]}")
|
77
|
+
item_screen = Item.new(@stdscr, @feeds[cur_y - 1])
|
78
|
+
item_screen.loop
|
79
|
+
|
80
|
+
window
|
81
|
+
move_pointer(cur_y, move_to=true)
|
82
|
+
end
|
83
|
+
else
|
84
|
+
case c
|
85
|
+
when Ncurses::KEY_UP
|
86
|
+
move_pointer(-1)
|
87
|
+
when Ncurses::KEY_DOWN
|
88
|
+
move_pointer(1)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module Rutt
|
2
|
+
module Screen
|
3
|
+
class Item < Base
|
4
|
+
def initialize(stdscr, feed)
|
5
|
+
@feed = feed
|
6
|
+
@menu = " i:quit r:refresh m:mark as read u:mark as unread a:mark all as read b:open in browser"
|
7
|
+
|
8
|
+
super(stdscr)
|
9
|
+
end
|
10
|
+
|
11
|
+
def display_items
|
12
|
+
@cur_y = @min_y
|
13
|
+
|
14
|
+
@items = DB::Item::all(@feed, @min_limit, @max_limit)
|
15
|
+
@items.each do |item|
|
16
|
+
item_status = case item['read'].to_i
|
17
|
+
when 0 then 'N'
|
18
|
+
when 1 then ' '
|
19
|
+
when 2 then 'I'
|
20
|
+
else ' '
|
21
|
+
end
|
22
|
+
@stdscr.addstr(" #{item_status}\t#{Time.at(item['published_at']).strftime("%b %d, %Y %R:%M")}\t#{item['title']}\n")
|
23
|
+
@cur_y += 1
|
24
|
+
end
|
25
|
+
|
26
|
+
@cur_y = @min_y
|
27
|
+
@stdscr.refresh
|
28
|
+
end
|
29
|
+
|
30
|
+
def window
|
31
|
+
@stdscr.clear
|
32
|
+
|
33
|
+
display_menu
|
34
|
+
display_items
|
35
|
+
move_pointer(0)
|
36
|
+
end
|
37
|
+
|
38
|
+
def loop
|
39
|
+
window
|
40
|
+
|
41
|
+
while true do
|
42
|
+
c = @stdscr.getch
|
43
|
+
|
44
|
+
if c > 0 && c < 255
|
45
|
+
case c.chr
|
46
|
+
when /[iq]/i
|
47
|
+
break
|
48
|
+
when /s/i
|
49
|
+
cur_y = @cur_y - 1
|
50
|
+
$instapaper.request('/api/1/bookmarks/add', {
|
51
|
+
'url' => @items[cur_y]['url'],
|
52
|
+
'title' => @items[cur_y]['title'],
|
53
|
+
})
|
54
|
+
DB::Item::sent_to_instapaper(@items[cur_y])
|
55
|
+
window
|
56
|
+
move_pointer(@cur_y, move_to=true)
|
57
|
+
when /a/i
|
58
|
+
DB::Feed::mark_as_read(@feed)
|
59
|
+
window
|
60
|
+
move_pointer(@cur_y, move_to=true)
|
61
|
+
when /p/i
|
62
|
+
decr_page
|
63
|
+
window
|
64
|
+
when /n/i
|
65
|
+
incr_page
|
66
|
+
window
|
67
|
+
when /b/i
|
68
|
+
cur_y = @cur_y - 1
|
69
|
+
DB::Item::mark_as_read(@items[cur_y])
|
70
|
+
Launchy.open(@items[cur_y]['url'])
|
71
|
+
window
|
72
|
+
move_pointer(@cur_y, move_to=true)
|
73
|
+
when /m/i
|
74
|
+
cur_y = @cur_y - 1
|
75
|
+
DB::Item::mark_as_read(@items[cur_y])
|
76
|
+
window
|
77
|
+
move_pointer(cur_y + 1, move_to=true)
|
78
|
+
when /u/i
|
79
|
+
cur_y = @cur_y - 1
|
80
|
+
DB::Item::mark_as_unread(@items[cur_y])
|
81
|
+
window
|
82
|
+
move_pointer(cur_y + 1, move_to=true)
|
83
|
+
when /r/i
|
84
|
+
DB::Feed::refresh_for(@feed)
|
85
|
+
window
|
86
|
+
when / /
|
87
|
+
content_screen = Content.new(@stdscr, @items[@cur_y - 1])
|
88
|
+
content_screen.loop
|
89
|
+
|
90
|
+
window
|
91
|
+
move_pointer(@cur_y, move_to=true)
|
92
|
+
end
|
93
|
+
else
|
94
|
+
case c
|
95
|
+
when Ncurses::KEY_UP
|
96
|
+
move_pointer(-1)
|
97
|
+
when Ncurses::KEY_DOWN
|
98
|
+
move_pointer(1)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
File without changes
|
data/rutt.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{rutt}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.4.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Abhi Yerra"]
|
12
|
-
s.date = %q{2011-
|
12
|
+
s.date = %q{2011-05-19}
|
13
13
|
s.default_executable = %q{rutt}
|
14
14
|
s.description = %q{The Mutt of RSS/Atom feeds.}
|
15
15
|
s.email = %q{abhi@berkeley.edu}
|
@@ -29,15 +29,15 @@ Gem::Specification.new do |s|
|
|
29
29
|
"VERSION",
|
30
30
|
"bin/rutt",
|
31
31
|
"lib/rutt.rb",
|
32
|
-
"lib/rutt/config.rb",
|
33
|
-
"lib/rutt/
|
34
|
-
"lib/rutt/
|
35
|
-
"lib/rutt/feed_screen.rb",
|
36
|
-
"lib/rutt/instapaper.rb",
|
37
|
-
"lib/rutt/item.rb",
|
38
|
-
"lib/rutt/item_screen.rb",
|
32
|
+
"lib/rutt/db/config.rb",
|
33
|
+
"lib/rutt/db/feed.rb",
|
34
|
+
"lib/rutt/db/item.rb",
|
39
35
|
"lib/rutt/opml.rb",
|
40
36
|
"lib/rutt/screen.rb",
|
37
|
+
"lib/rutt/screen/content.rb",
|
38
|
+
"lib/rutt/screen/feed.rb",
|
39
|
+
"lib/rutt/screen/item.rb",
|
40
|
+
"lib/rutt/share/instapaper.rb",
|
41
41
|
"rutt.gemspec",
|
42
42
|
"spec/rutt_spec.rb",
|
43
43
|
"spec/spec_helper.rb"
|
@@ -63,6 +63,7 @@ Gem::Specification.new do |s|
|
|
63
63
|
s.add_runtime_dependency(%q<ruby-feedparser>, [">= 0"])
|
64
64
|
s.add_runtime_dependency(%q<sqlite3>, [">= 0"])
|
65
65
|
s.add_runtime_dependency(%q<oauth>, [">= 0"])
|
66
|
+
s.add_runtime_dependency(%q<ruby-readability>, [">= 0"])
|
66
67
|
s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
|
67
68
|
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
68
69
|
s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
|
@@ -75,6 +76,7 @@ Gem::Specification.new do |s|
|
|
75
76
|
s.add_dependency(%q<ruby-feedparser>, [">= 0"])
|
76
77
|
s.add_dependency(%q<sqlite3>, [">= 0"])
|
77
78
|
s.add_dependency(%q<oauth>, [">= 0"])
|
79
|
+
s.add_dependency(%q<ruby-readability>, [">= 0"])
|
78
80
|
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
79
81
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
80
82
|
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
@@ -88,6 +90,7 @@ Gem::Specification.new do |s|
|
|
88
90
|
s.add_dependency(%q<ruby-feedparser>, [">= 0"])
|
89
91
|
s.add_dependency(%q<sqlite3>, [">= 0"])
|
90
92
|
s.add_dependency(%q<oauth>, [">= 0"])
|
93
|
+
s.add_dependency(%q<ruby-readability>, [">= 0"])
|
91
94
|
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
92
95
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
93
96
|
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rutt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 15
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 4
|
9
|
+
- 0
|
10
|
+
version: 0.4.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Abhi Yerra
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-05-19 00:00:00 +00:00
|
19
19
|
default_executable: rutt
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -117,8 +117,22 @@ dependencies:
|
|
117
117
|
version_requirements: *id007
|
118
118
|
prerelease: false
|
119
119
|
- !ruby/object:Gem::Dependency
|
120
|
-
type: :
|
120
|
+
type: :runtime
|
121
121
|
requirement: &id008 !ruby/object:Gem::Requirement
|
122
|
+
none: false
|
123
|
+
requirements:
|
124
|
+
- - ">="
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
hash: 3
|
127
|
+
segments:
|
128
|
+
- 0
|
129
|
+
version: "0"
|
130
|
+
name: ruby-readability
|
131
|
+
version_requirements: *id008
|
132
|
+
prerelease: false
|
133
|
+
- !ruby/object:Gem::Dependency
|
134
|
+
type: :development
|
135
|
+
requirement: &id009 !ruby/object:Gem::Requirement
|
122
136
|
none: false
|
123
137
|
requirements:
|
124
138
|
- - ~>
|
@@ -130,11 +144,11 @@ dependencies:
|
|
130
144
|
- 0
|
131
145
|
version: 2.3.0
|
132
146
|
name: rspec
|
133
|
-
version_requirements: *
|
147
|
+
version_requirements: *id009
|
134
148
|
prerelease: false
|
135
149
|
- !ruby/object:Gem::Dependency
|
136
150
|
type: :development
|
137
|
-
requirement: &
|
151
|
+
requirement: &id010 !ruby/object:Gem::Requirement
|
138
152
|
none: false
|
139
153
|
requirements:
|
140
154
|
- - ~>
|
@@ -146,11 +160,11 @@ dependencies:
|
|
146
160
|
- 0
|
147
161
|
version: 1.0.0
|
148
162
|
name: bundler
|
149
|
-
version_requirements: *
|
163
|
+
version_requirements: *id010
|
150
164
|
prerelease: false
|
151
165
|
- !ruby/object:Gem::Dependency
|
152
166
|
type: :development
|
153
|
-
requirement: &
|
167
|
+
requirement: &id011 !ruby/object:Gem::Requirement
|
154
168
|
none: false
|
155
169
|
requirements:
|
156
170
|
- - ~>
|
@@ -162,11 +176,11 @@ dependencies:
|
|
162
176
|
- 2
|
163
177
|
version: 1.5.2
|
164
178
|
name: jeweler
|
165
|
-
version_requirements: *
|
179
|
+
version_requirements: *id011
|
166
180
|
prerelease: false
|
167
181
|
- !ruby/object:Gem::Dependency
|
168
182
|
type: :development
|
169
|
-
requirement: &
|
183
|
+
requirement: &id012 !ruby/object:Gem::Requirement
|
170
184
|
none: false
|
171
185
|
requirements:
|
172
186
|
- - ">="
|
@@ -176,7 +190,7 @@ dependencies:
|
|
176
190
|
- 0
|
177
191
|
version: "0"
|
178
192
|
name: rcov
|
179
|
-
version_requirements: *
|
193
|
+
version_requirements: *id012
|
180
194
|
prerelease: false
|
181
195
|
description: The Mutt of RSS/Atom feeds.
|
182
196
|
email: abhi@berkeley.edu
|
@@ -198,15 +212,15 @@ files:
|
|
198
212
|
- VERSION
|
199
213
|
- bin/rutt
|
200
214
|
- lib/rutt.rb
|
201
|
-
- lib/rutt/config.rb
|
202
|
-
- lib/rutt/
|
203
|
-
- lib/rutt/
|
204
|
-
- lib/rutt/feed_screen.rb
|
205
|
-
- lib/rutt/instapaper.rb
|
206
|
-
- lib/rutt/item.rb
|
207
|
-
- lib/rutt/item_screen.rb
|
215
|
+
- lib/rutt/db/config.rb
|
216
|
+
- lib/rutt/db/feed.rb
|
217
|
+
- lib/rutt/db/item.rb
|
208
218
|
- lib/rutt/opml.rb
|
209
219
|
- lib/rutt/screen.rb
|
220
|
+
- lib/rutt/screen/content.rb
|
221
|
+
- lib/rutt/screen/feed.rb
|
222
|
+
- lib/rutt/screen/item.rb
|
223
|
+
- lib/rutt/share/instapaper.rb
|
210
224
|
- rutt.gemspec
|
211
225
|
- spec/rutt_spec.rb
|
212
226
|
- spec/spec_helper.rb
|
data/lib/rutt/config.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
module Rutt
|
2
|
-
module Config
|
3
|
-
extend self
|
4
|
-
|
5
|
-
def make_table!
|
6
|
-
$db.execute(%{
|
7
|
-
create table if not exists config (
|
8
|
-
id integer PRIMARY KEY,
|
9
|
-
key text,
|
10
|
-
value text,
|
11
|
-
UNIQUE(key))
|
12
|
-
})
|
13
|
-
end
|
14
|
-
|
15
|
-
def get(key)
|
16
|
-
$db.get_first_value("select value from config where key = ?", key)
|
17
|
-
end
|
18
|
-
|
19
|
-
def set(key, value)
|
20
|
-
$db.execute("insert or replace into config(key, value) values (?, ?)", key, value)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
data/lib/rutt/content_screen.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
module Rutt
|
2
|
-
class ContentScreen < Screen
|
3
|
-
def initialize(stdscr, item)
|
4
|
-
@item = item
|
5
|
-
@menu = "i:back b:open in browser"
|
6
|
-
|
7
|
-
super(stdscr)
|
8
|
-
end
|
9
|
-
|
10
|
-
def display_content
|
11
|
-
@content = `elinks -dump -dump-charset ascii -force-html #{@item['url']}`
|
12
|
-
@content = @content.split("\n")
|
13
|
-
|
14
|
-
@stdscr.addstr(" #{@item['title']} (#{@item['url']})\n\n")
|
15
|
-
|
16
|
-
lines = @content[@min_limit..@max_limit]
|
17
|
-
lines.each { |line| @stdscr.addstr(" #{line}\n") } if lines
|
18
|
-
|
19
|
-
@stdscr.refresh
|
20
|
-
end
|
21
|
-
|
22
|
-
def window
|
23
|
-
@stdscr.clear
|
24
|
-
display_menu
|
25
|
-
display_content
|
26
|
-
end
|
27
|
-
|
28
|
-
def loop
|
29
|
-
@cur_line = 0
|
30
|
-
|
31
|
-
window
|
32
|
-
|
33
|
-
while true do
|
34
|
-
c = @stdscr.getch
|
35
|
-
if c > 0 && c < 255
|
36
|
-
case c.chr
|
37
|
-
when /[iq]/i
|
38
|
-
Item::mark_as_read(@item)
|
39
|
-
break
|
40
|
-
when /b/i
|
41
|
-
Launchy.open(@item['url'])
|
42
|
-
end
|
43
|
-
else
|
44
|
-
case c
|
45
|
-
when Ncurses::KEY_UP
|
46
|
-
decr_page
|
47
|
-
window
|
48
|
-
when Ncurses::KEY_DOWN
|
49
|
-
incr_page
|
50
|
-
window
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
data/lib/rutt/feed.rb
DELETED
@@ -1,74 +0,0 @@
|
|
1
|
-
module Rutt
|
2
|
-
|
3
|
-
module Feed
|
4
|
-
extend self
|
5
|
-
|
6
|
-
def make_table!
|
7
|
-
$db.execute(%{
|
8
|
-
create table if not exists feeds (
|
9
|
-
id integer PRIMARY KEY,
|
10
|
-
title text,
|
11
|
-
url text,
|
12
|
-
update_interval integer default 3600,
|
13
|
-
created_at NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
14
|
-
updated_at NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
15
|
-
UNIQUE(url))
|
16
|
-
})
|
17
|
-
end
|
18
|
-
|
19
|
-
def add(url, refresh=true)
|
20
|
-
$db.execute("insert or ignore into feeds (url) values ('#{url}')")
|
21
|
-
$db.execute("select * from feeds where id = (select last_insert_rowid())") do |feed|
|
22
|
-
refresh_for(feed)
|
23
|
-
end if refresh
|
24
|
-
end
|
25
|
-
|
26
|
-
def get(id)
|
27
|
-
|
28
|
-
end
|
29
|
-
|
30
|
-
def delete(feed)
|
31
|
-
$db.execute("delete from items where feed_id = ?", feed['id'])
|
32
|
-
$db.execute("delete from feeds where id = ?", feed['id'])
|
33
|
-
end
|
34
|
-
|
35
|
-
def all(min_limit=0, max_limit=-1)
|
36
|
-
$db.execute(%{
|
37
|
-
select f.*,
|
38
|
-
(select count(*) from items iu where iu.feed_id = f.id) as num_items,
|
39
|
-
(select count(*) from items ir where ir.read = 0 and ir.feed_id = f.id) as unread
|
40
|
-
from feeds f where unread > 0 order by id desc limit #{min_limit},#{max_limit}
|
41
|
-
})
|
42
|
-
end
|
43
|
-
|
44
|
-
def refresh
|
45
|
-
feeds = $db.execute("select * from feeds")
|
46
|
-
results = Parallel.map(feeds, :in_threads => 8) do |feed|
|
47
|
-
refresh_for(feed)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def refresh_for(feed)
|
52
|
-
content = open(feed['url']).read
|
53
|
-
rss = FeedParser::Feed::new(content)
|
54
|
-
|
55
|
-
puts rss.title
|
56
|
-
|
57
|
-
$db.execute("update feeds set title = ? where id = ?", rss.title, feed['id'])
|
58
|
-
|
59
|
-
rss.items.each do |item|
|
60
|
-
$db.execute("insert or ignore into items (feed_id, title, url, published_at) values (?, ?, ?, ?)", feed['id'], item.title, item.link, item.date.to_i)
|
61
|
-
end
|
62
|
-
rescue Exception => e
|
63
|
-
# no-op
|
64
|
-
end
|
65
|
-
|
66
|
-
def unread(feed_id)
|
67
|
-
$db.execute("select * from items where feed_id = ? and read = 0", feed)
|
68
|
-
end
|
69
|
-
|
70
|
-
def mark_as_read(feed)
|
71
|
-
$db.execute("update items set read = 1 where feed_id = ?", feed['id'])
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
data/lib/rutt/feed_screen.rb
DELETED
@@ -1,93 +0,0 @@
|
|
1
|
-
module Rutt
|
2
|
-
class FeedScreen < Screen
|
3
|
-
def initialize(stdscr)
|
4
|
-
@menu = "q:Quit d:delete r:refresh all"
|
5
|
-
|
6
|
-
super(stdscr)
|
7
|
-
end
|
8
|
-
|
9
|
-
def display_feeds
|
10
|
-
@cur_y = @min_y
|
11
|
-
|
12
|
-
@feeds = Feed::all(@min_limit, @max_limit)
|
13
|
-
@feeds.each do |feed|
|
14
|
-
# next if feed['unread'] == 0 # This should be configurable: feed.showread
|
15
|
-
|
16
|
-
@stdscr.move(@cur_y, 0)
|
17
|
-
@stdscr.addstr(" #{feed['unread']}/#{feed['num_items']}\t\t#{feed['title']}\n")
|
18
|
-
|
19
|
-
@cur_y += 1
|
20
|
-
end
|
21
|
-
|
22
|
-
@cur_y = @min_y
|
23
|
-
@stdscr.refresh
|
24
|
-
end
|
25
|
-
|
26
|
-
def window
|
27
|
-
@stdscr.clear
|
28
|
-
|
29
|
-
display_menu
|
30
|
-
display_feeds
|
31
|
-
move_pointer(0)
|
32
|
-
end
|
33
|
-
|
34
|
-
def loop
|
35
|
-
window
|
36
|
-
|
37
|
-
while true do
|
38
|
-
c = @stdscr.getch
|
39
|
-
|
40
|
-
if c > 0 && c < 255
|
41
|
-
case c.chr
|
42
|
-
when /q/i
|
43
|
-
break
|
44
|
-
when /a/i
|
45
|
-
# no-op
|
46
|
-
when /r/i
|
47
|
-
cur_y = @cur_y
|
48
|
-
|
49
|
-
Feed::refresh
|
50
|
-
|
51
|
-
window
|
52
|
-
move_pointer(cur_y, move_to=true)
|
53
|
-
when /d/i
|
54
|
-
cur_y = @cur_y - 1
|
55
|
-
|
56
|
-
@stdscr.clear
|
57
|
-
display_menu
|
58
|
-
feed = @feeds[cur_y]
|
59
|
-
@stdscr.move(2, 0)
|
60
|
-
@stdscr.addstr("Are you sure you want to delete #{feed['title']}? ")
|
61
|
-
d = @stdscr.getch
|
62
|
-
if d.chr =~ /y/i
|
63
|
-
Feed::delete(feed)
|
64
|
-
end
|
65
|
-
window
|
66
|
-
move_pointer(cur_y, move_to=true)
|
67
|
-
when /p/i
|
68
|
-
decr_page
|
69
|
-
window
|
70
|
-
when /n/i
|
71
|
-
incr_page
|
72
|
-
window
|
73
|
-
when / /
|
74
|
-
cur_y = @cur_y
|
75
|
-
@stdscr.addstr("#{@feeds[cur_y]}")
|
76
|
-
item_screen = ItemScreen.new(@stdscr, @feeds[cur_y - 1])
|
77
|
-
item_screen.loop
|
78
|
-
|
79
|
-
window
|
80
|
-
move_pointer(cur_y, move_to=true)
|
81
|
-
end
|
82
|
-
else
|
83
|
-
case c
|
84
|
-
when Ncurses::KEY_UP
|
85
|
-
move_pointer(-1)
|
86
|
-
when Ncurses::KEY_DOWN
|
87
|
-
move_pointer(1)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
data/lib/rutt/item.rb
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
module Rutt
|
2
|
-
module Item
|
3
|
-
|
4
|
-
extend self
|
5
|
-
|
6
|
-
def make_table!
|
7
|
-
$db.execute(%{
|
8
|
-
create table if not exists items (
|
9
|
-
id integer PRIMARY KEY,
|
10
|
-
feed_id integer,
|
11
|
-
title text,
|
12
|
-
url text,
|
13
|
-
description text,
|
14
|
-
read int default 0,
|
15
|
-
prioritize int default 0,
|
16
|
-
published_at DATE NOT NULL DEFAULT (datetime('now','localtime')),
|
17
|
-
created_at NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
18
|
-
updated_at NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
19
|
-
UNIQUE(url),
|
20
|
-
FOREIGN KEY(feed_id) REFERENCES feeds(id))
|
21
|
-
})
|
22
|
-
end
|
23
|
-
|
24
|
-
def all(feed, min_limit=0, max_limit=-1)
|
25
|
-
$db.execute("select * from items where feed_id = ? order by published_at desc limit #{min_limit},#{max_limit}", feed['id'])
|
26
|
-
end
|
27
|
-
|
28
|
-
def mark_as_unread(item)
|
29
|
-
$db.execute("update items set read = 0 where id = #{item['id']}")
|
30
|
-
end
|
31
|
-
|
32
|
-
def mark_as_read(item)
|
33
|
-
$db.execute("update items set read = 1 where id = #{item['id']}")
|
34
|
-
end
|
35
|
-
|
36
|
-
def sent_to_instapaper(item)
|
37
|
-
$db.execute("update items set read = 2 where id = #{item['id']}")
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
data/lib/rutt/item_screen.rb
DELETED
@@ -1,103 +0,0 @@
|
|
1
|
-
module Rutt
|
2
|
-
class ItemScreen < Screen
|
3
|
-
def initialize(stdscr, feed)
|
4
|
-
@feed = feed
|
5
|
-
@menu = " i:quit r:refresh m:mark as read u:mark as unread a:mark all as read b:open in browser"
|
6
|
-
|
7
|
-
super(stdscr)
|
8
|
-
end
|
9
|
-
|
10
|
-
def display_items
|
11
|
-
@cur_y = @min_y
|
12
|
-
|
13
|
-
@items = Item::all(@feed, @min_limit, @max_limit)
|
14
|
-
@items.each do |item|
|
15
|
-
item_status = case item['read'].to_i
|
16
|
-
when 0 then 'N'
|
17
|
-
when 1 then ' '
|
18
|
-
when 2 then 'I'
|
19
|
-
else ' '
|
20
|
-
end
|
21
|
-
@stdscr.addstr(" #{item_status}\t#{Time.at(item['published_at']).strftime("%b %d, %Y %R:%M")}\t#{item['title']}\n")
|
22
|
-
@cur_y += 1
|
23
|
-
end
|
24
|
-
|
25
|
-
@cur_y = @min_y
|
26
|
-
@stdscr.refresh
|
27
|
-
end
|
28
|
-
|
29
|
-
def window
|
30
|
-
@stdscr.clear
|
31
|
-
|
32
|
-
display_menu
|
33
|
-
display_items
|
34
|
-
move_pointer(0)
|
35
|
-
end
|
36
|
-
|
37
|
-
def loop
|
38
|
-
window
|
39
|
-
|
40
|
-
while true do
|
41
|
-
c = @stdscr.getch
|
42
|
-
|
43
|
-
if c > 0 && c < 255
|
44
|
-
case c.chr
|
45
|
-
when /[iq]/i
|
46
|
-
break
|
47
|
-
when /s/i
|
48
|
-
cur_y = @cur_y - 1
|
49
|
-
$instapaper.request('/api/1/bookmarks/add', {
|
50
|
-
'url' => @items[cur_y]['url'],
|
51
|
-
'title' => @items[cur_y]['title'],
|
52
|
-
})
|
53
|
-
Item::sent_to_instapaper(@items[cur_y])
|
54
|
-
window
|
55
|
-
move_pointer(@cur_y, move_to=true)
|
56
|
-
when /a/i
|
57
|
-
Feed::mark_as_read(@feed)
|
58
|
-
window
|
59
|
-
move_pointer(@cur_y, move_to=true)
|
60
|
-
when /p/i
|
61
|
-
decr_page
|
62
|
-
window
|
63
|
-
when /n/i
|
64
|
-
incr_page
|
65
|
-
window
|
66
|
-
when /b/i
|
67
|
-
cur_y = @cur_y - 1
|
68
|
-
Item::mark_as_read(@items[cur_y])
|
69
|
-
Launchy.open(@items[cur_y]['url'])
|
70
|
-
window
|
71
|
-
move_pointer(@cur_y, move_to=true)
|
72
|
-
when /m/i
|
73
|
-
cur_y = @cur_y - 1
|
74
|
-
Item::mark_as_read(@items[cur_y])
|
75
|
-
window
|
76
|
-
move_pointer(cur_y + 1, move_to=true)
|
77
|
-
when /u/i
|
78
|
-
cur_y = @cur_y - 1
|
79
|
-
Item::mark_as_unread(@items[cur_y])
|
80
|
-
window
|
81
|
-
move_pointer(cur_y + 1, move_to=true)
|
82
|
-
when /r/i
|
83
|
-
Feed::refresh_for(@feed)
|
84
|
-
window
|
85
|
-
when / /
|
86
|
-
content_screen = ContentScreen.new(@stdscr, @items[@cur_y - 1])
|
87
|
-
content_screen.loop
|
88
|
-
|
89
|
-
window
|
90
|
-
move_pointer(@cur_y, move_to=true)
|
91
|
-
end
|
92
|
-
else
|
93
|
-
case c
|
94
|
-
when Ncurses::KEY_UP
|
95
|
-
move_pointer(-1)
|
96
|
-
when Ncurses::KEY_DOWN
|
97
|
-
move_pointer(1)
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|