rutt 0.3.3 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|