feedcellar 0.4.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +0 -1
- data/NEWS.md +14 -3
- data/README.md +5 -21
- data/feedcellar.gemspec +1 -8
- data/lib/feedcellar/command.rb +2 -31
- data/lib/feedcellar/version.rb +2 -2
- metadata +1 -94
- data/config.ru +0 -34
- data/lib/feedcellar/curses_view.rb +0 -87
- data/lib/feedcellar/tree_view.rb +0 -133
- data/lib/feedcellar/views/index.haml +0 -16
- data/lib/feedcellar/views/layout.haml +0 -6
- data/lib/feedcellar/web.rb +0 -92
- data/lib/feedcellar/window.rb +0 -168
- data/test/test-curses_view.rb +0 -101
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9b0b56bc49519216392bb6b0554492c44760f5c0
|
4
|
+
data.tar.gz: 3712ec8b64294e089f4cf1be5f5437f3344ea0b9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 73a494cdbe21660f88e8c3b85b88b5a1950d6ae36267d7d7e5d7c5d42576bdebfb518bbae7d1701a4ec02cf7bf2c640568b507a2bc52e910ad8ac5adf9127d2d
|
7
|
+
data.tar.gz: 2679352036daeeafb087b32b4a8b22b1ded9f1cd37698448b21f9812984fe081eb4c826504c6e8ac00a4858ebee1d7b3c48e28bcdea8980433eac1657a304e33
|
data/NEWS.md
CHANGED
@@ -1,16 +1,27 @@
|
|
1
1
|
# NEWS
|
2
2
|
|
3
|
+
## 0.5.0: 2015-04-05
|
4
|
+
|
5
|
+
Extract interfaces to the other projects.
|
6
|
+
|
7
|
+
### Changes
|
8
|
+
|
9
|
+
* Improvements
|
10
|
+
* Extracted Web interface to feedcellar-web gem.
|
11
|
+
* Extracted GTK+ interface to feedcellar-gtk gem.
|
12
|
+
* Extracted Curses interface to feedcellar-curses gem.
|
13
|
+
|
3
14
|
## 0.4.1: 2015-04-04
|
4
15
|
|
5
|
-
Support to paginate!
|
16
|
+
Support to paginate for Web interface!
|
6
17
|
|
7
18
|
### Changes
|
8
19
|
|
9
20
|
* Improvements
|
10
21
|
* web: Added /register.opml root.
|
11
22
|
* web: Added %p to the feed list.
|
12
|
-
* Use Padrino::Helpers.
|
13
|
-
* Introduced to paginate.
|
23
|
+
* web: Use Padrino::Helpers.
|
24
|
+
* web: Introduced to paginate.
|
14
25
|
|
15
26
|
## 0.4.0: 2014-08-29
|
16
27
|
|
data/README.md
CHANGED
@@ -45,33 +45,17 @@ Powered by [Groonga][] (via [Rroonga][]) with [Ruby][].
|
|
45
45
|
|
46
46
|
$ feedcellar search WORD1 [WORD2...]
|
47
47
|
|
48
|
-
###
|
48
|
+
### Start web server and show feeds in a web browser
|
49
49
|
|
50
|
-
|
51
|
-
|
52
|
-
Or
|
53
|
-
|
54
|
-
$ rackup
|
55
|
-
|
56
|
-
#### Enable cache (using Racknga)
|
57
|
-
|
58
|
-
$ FEEDCELLAR_ENABLE_CACHE=true rackup
|
50
|
+
[Feedcellar::Web](https://github.com/feedcellar/feedcellar-web)
|
59
51
|
|
60
52
|
### Show feeds on GUI window (experimental)
|
61
53
|
|
62
|
-
|
63
|
-
$ feedcellar show [--lines=N]
|
54
|
+
[Feedcellar::Gtk](https://github.com/feedcellar/feedcellar-gtk)
|
64
55
|
|
65
56
|
### Rich view by curses (experimental)
|
66
57
|
|
67
|
-
|
68
|
-
$ feedcellar search ruby --curses
|
69
|
-
|
70
|
-
Keybind:
|
71
|
-
j: down
|
72
|
-
k: up
|
73
|
-
f, ENTER: open the link on Firefox
|
74
|
-
q: quit
|
58
|
+
[Feedcellar::Curses](https://github.com/feedcellar/feedcellar-curses)
|
75
59
|
|
76
60
|
### Delete database
|
77
61
|
|
@@ -79,7 +63,7 @@ Or
|
|
79
63
|
|
80
64
|
## License
|
81
65
|
|
82
|
-
Copyright (c) 2013-
|
66
|
+
Copyright (c) 2013-2015 Masafumi Yokoyama `<myokoym@gmail.com>`
|
83
67
|
|
84
68
|
LGPLv2.1 or later.
|
85
69
|
|
data/feedcellar.gemspec
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
#
|
3
3
|
# feedcellar.gemspec
|
4
4
|
#
|
5
|
-
# Copyright (C) 2013-
|
5
|
+
# Copyright (C) 2013-2015 Masafumi Yokoyama <myokoym@gmail.com>
|
6
6
|
#
|
7
7
|
# This library is free software; you can redistribute it and/or
|
8
8
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -39,13 +39,6 @@ Gem::Specification.new do |spec|
|
|
39
39
|
|
40
40
|
spec.add_runtime_dependency("rroonga", ">= 3.0.4")
|
41
41
|
spec.add_runtime_dependency("thor")
|
42
|
-
#spec.add_runtime_dependency("gtk2")
|
43
|
-
spec.add_runtime_dependency("sinatra")
|
44
|
-
spec.add_runtime_dependency("padrino-helpers")
|
45
|
-
spec.add_runtime_dependency("kaminari")
|
46
|
-
spec.add_runtime_dependency("haml")
|
47
|
-
spec.add_runtime_dependency("launchy")
|
48
|
-
spec.add_runtime_dependency("racknga")
|
49
42
|
|
50
43
|
spec.add_development_dependency("test-unit")
|
51
44
|
spec.add_development_dependency("test-unit-notify")
|
data/lib/feedcellar/command.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# class Feedcellar::Command
|
2
2
|
#
|
3
|
-
# Copyright (C) 2013-
|
3
|
+
# Copyright (C) 2013-2015 Masafumi Yokoyama <myokoym@gmail.com>
|
4
4
|
#
|
5
5
|
# This library is free software; you can redistribute it and/or
|
6
6
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -78,21 +78,6 @@ module Feedcellar
|
|
78
78
|
end
|
79
79
|
end
|
80
80
|
|
81
|
-
desc "show", "Show feeds on GUI."
|
82
|
-
option :lines, :type => :numeric, :aliases => "-n", :desc => "Number of lines"
|
83
|
-
def show
|
84
|
-
# TODO: Can we always require gtk2 gem?
|
85
|
-
begin
|
86
|
-
require "feedcellar/window"
|
87
|
-
rescue LoadError => e
|
88
|
-
$stderr.puts("#{e.class}: #{e.message}")
|
89
|
-
return false
|
90
|
-
end
|
91
|
-
|
92
|
-
window = Window.new(@database_dir, options)
|
93
|
-
window.run
|
94
|
-
end
|
95
|
-
|
96
81
|
desc "list", "Show registered resources list of title and URL."
|
97
82
|
def list
|
98
83
|
GroongaDatabase.new.open(@database_dir) do |database|
|
@@ -139,7 +124,6 @@ module Feedcellar
|
|
139
124
|
option :reverse, :type => :boolean, :aliases => "-r", :desc => "reverse order while sorting"
|
140
125
|
option :mtime, :type => :numeric, :desc => "feed's data was last modified n*24 hours ago."
|
141
126
|
option :resource, :type => :string, :desc => "search of partial match by feed's resource url"
|
142
|
-
option :curses, :type => :boolean, :desc => "rich view for easy web browse"
|
143
127
|
option :grouping, :type => :boolean, :desc => "group by resource"
|
144
128
|
def search(*words)
|
145
129
|
if words.empty? &&
|
@@ -151,10 +135,7 @@ module Feedcellar
|
|
151
135
|
GroongaDatabase.new.open(@database_dir) do |database|
|
152
136
|
sorted_feeds = GroongaSearcher.search(database, words, options)
|
153
137
|
|
154
|
-
if options[:
|
155
|
-
require "feedcellar/curses_view"
|
156
|
-
CursesView.run(sorted_feeds)
|
157
|
-
elsif options[:grouping]
|
138
|
+
if options[:grouping]
|
158
139
|
sorted_feeds.group("resource").each do |group|
|
159
140
|
puts "#{group.key.title} (#{group.n_sub_records})"
|
160
141
|
end
|
@@ -173,15 +154,5 @@ module Feedcellar
|
|
173
154
|
end
|
174
155
|
end
|
175
156
|
end
|
176
|
-
|
177
|
-
desc "web", "Show feeds in a web browser"
|
178
|
-
option :silent, :type => :boolean, :desc => "Don't open in browser"
|
179
|
-
def web
|
180
|
-
require "feedcellar/web"
|
181
|
-
require "launchy"
|
182
|
-
web_server_thread = Thread.new { Feedcellar::Web.run! }
|
183
|
-
Launchy.open("http://localhost:4567") unless options[:silent]
|
184
|
-
web_server_thread.join
|
185
|
-
end
|
186
157
|
end
|
187
158
|
end
|
data/lib/feedcellar/version.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# constant Feedcellar::VERSION
|
2
2
|
#
|
3
|
-
# Copyright (C) 2013-
|
3
|
+
# Copyright (C) 2013-2015 Masafumi Yokoyama <myokoym@gmail.com>
|
4
4
|
#
|
5
5
|
# This library is free software; you can redistribute it and/or
|
6
6
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -17,5 +17,5 @@
|
|
17
17
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
18
|
|
19
19
|
module Feedcellar
|
20
|
-
VERSION = "0.
|
20
|
+
VERSION = "0.5.0"
|
21
21
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: feedcellar
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Masafumi Yokoyama
|
@@ -38,90 +38,6 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: sinatra
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ">="
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
48
|
-
type: :runtime
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - ">="
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: padrino-helpers
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - ">="
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
62
|
-
type: :runtime
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - ">="
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: kaminari
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - ">="
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '0'
|
76
|
-
type: :runtime
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - ">="
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: haml
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - ">="
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '0'
|
90
|
-
type: :runtime
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - ">="
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '0'
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: launchy
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - ">="
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: '0'
|
104
|
-
type: :runtime
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - ">="
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: '0'
|
111
|
-
- !ruby/object:Gem::Dependency
|
112
|
-
name: racknga
|
113
|
-
requirement: !ruby/object:Gem::Requirement
|
114
|
-
requirements:
|
115
|
-
- - ">="
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: '0'
|
118
|
-
type: :runtime
|
119
|
-
prerelease: false
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
requirements:
|
122
|
-
- - ">="
|
123
|
-
- !ruby/object:Gem::Version
|
124
|
-
version: '0'
|
125
41
|
- !ruby/object:Gem::Dependency
|
126
42
|
name: test-unit
|
127
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -211,26 +127,18 @@ files:
|
|
211
127
|
- Rakefile
|
212
128
|
- bin/feedcellar
|
213
129
|
- bin/feedcellar-clear-cache
|
214
|
-
- config.ru
|
215
130
|
- feedcellar.gemspec
|
216
131
|
- lib/feedcellar.rb
|
217
132
|
- lib/feedcellar/command.rb
|
218
|
-
- lib/feedcellar/curses_view.rb
|
219
133
|
- lib/feedcellar/feed.rb
|
220
134
|
- lib/feedcellar/groonga_database.rb
|
221
135
|
- lib/feedcellar/groonga_searcher.rb
|
222
136
|
- lib/feedcellar/opml.rb
|
223
137
|
- lib/feedcellar/resource.rb
|
224
|
-
- lib/feedcellar/tree_view.rb
|
225
138
|
- lib/feedcellar/version.rb
|
226
|
-
- lib/feedcellar/views/index.haml
|
227
|
-
- lib/feedcellar/views/layout.haml
|
228
|
-
- lib/feedcellar/web.rb
|
229
|
-
- lib/feedcellar/window.rb
|
230
139
|
- test/fixtures/subscriptions.xml
|
231
140
|
- test/run-test.rb
|
232
141
|
- test/test-command.rb
|
233
|
-
- test/test-curses_view.rb
|
234
142
|
- test/test-opml.rb
|
235
143
|
homepage: http://myokoym.net/feedcellar/
|
236
144
|
licenses:
|
@@ -260,6 +168,5 @@ test_files:
|
|
260
168
|
- test/fixtures/subscriptions.xml
|
261
169
|
- test/run-test.rb
|
262
170
|
- test/test-command.rb
|
263
|
-
- test/test-curses_view.rb
|
264
171
|
- test/test-opml.rb
|
265
172
|
has_rdoc:
|
data/config.ru
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
# config.ru
|
2
|
-
#
|
3
|
-
# Copyright (C) 2014 Masafumi Yokoyama <myokoym@gmail.com>
|
4
|
-
#
|
5
|
-
# This library is free software; you can redistribute it and/or
|
6
|
-
# modify it under the terms of the GNU Lesser General Public
|
7
|
-
# License as published by the Free Software Foundation; either
|
8
|
-
# version 2.1 of the License, or (at your option) any later version.
|
9
|
-
#
|
10
|
-
# This library is distributed in the hope that it will be useful,
|
11
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
-
# Lesser General Public License for more details.
|
14
|
-
#
|
15
|
-
# You should have received a copy of the GNU Lesser General Public
|
16
|
-
# License along with this library; if not, write to the Free Software
|
17
|
-
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
|
-
|
19
|
-
base_dir = File.expand_path(File.dirname(__FILE__))
|
20
|
-
lib_dir = File.join(base_dir, "lib")
|
21
|
-
$LOAD_PATH.unshift(lib_dir)
|
22
|
-
require "feedcellar/web"
|
23
|
-
|
24
|
-
ENV["FEEDCELLAR_HOME"] ||= File.join(base_dir, ".feedcellar")
|
25
|
-
|
26
|
-
if ENV["FEEDCELLAR_ENABLE_CACHE"]
|
27
|
-
require "racknga"
|
28
|
-
require "racknga/middleware/cache"
|
29
|
-
|
30
|
-
cache_database_path = File.join(base_dir, "var", "cache", "db")
|
31
|
-
use Racknga::Middleware::Cache, :database_path => cache_database_path
|
32
|
-
end
|
33
|
-
|
34
|
-
run Feedcellar::Web
|
@@ -1,87 +0,0 @@
|
|
1
|
-
# module Feedcellar::CursesView
|
2
|
-
#
|
3
|
-
# Copyright (C) 2013-2014 Masafumi Yokoyama <myokoym@gmail.com>
|
4
|
-
#
|
5
|
-
# This library is free software; you can redistribute it and/or
|
6
|
-
# modify it under the terms of the GNU Lesser General Public
|
7
|
-
# License as published by the Free Software Foundation; either
|
8
|
-
# version 2.1 of the License, or (at your option) any later version.
|
9
|
-
#
|
10
|
-
# This library is distributed in the hope that it will be useful,
|
11
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
-
# Lesser General Public License for more details.
|
14
|
-
#
|
15
|
-
# You should have received a copy of the GNU Lesser General Public
|
16
|
-
# License along with this library; if not, write to the Free Software
|
17
|
-
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
|
-
|
19
|
-
require "curses"
|
20
|
-
|
21
|
-
module Feedcellar
|
22
|
-
module CursesView
|
23
|
-
module_function
|
24
|
-
def run(feeds)
|
25
|
-
Curses.init_screen
|
26
|
-
Curses.noecho
|
27
|
-
Curses.nonl
|
28
|
-
|
29
|
-
# TODO
|
30
|
-
feeds = feeds.to_a
|
31
|
-
feeds.reject! {|feed| feed.title.nil? }
|
32
|
-
|
33
|
-
render_feeds(feeds)
|
34
|
-
Curses.setpos(0, 0)
|
35
|
-
|
36
|
-
pos = 0
|
37
|
-
begin
|
38
|
-
loop do
|
39
|
-
case Curses.getch
|
40
|
-
when "j"
|
41
|
-
pos += 1 if pos < Curses.lines - 1
|
42
|
-
Curses.setpos(pos, 0)
|
43
|
-
when "k"
|
44
|
-
pos -= 1 if pos > 0
|
45
|
-
Curses.setpos(pos, 0)
|
46
|
-
when "f", 13
|
47
|
-
spawn("firefox",
|
48
|
-
feeds[pos].link,
|
49
|
-
[:out, :err] => "/dev/null")
|
50
|
-
when "d"
|
51
|
-
mainwin = Curses.stdscr
|
52
|
-
mainwin.clear
|
53
|
-
subwin = mainwin.subwin(mainwin.maxy, mainwin.maxx, 0, 0)
|
54
|
-
subwin.setpos(0, 0)
|
55
|
-
subwin.addstr(feeds[pos].title)
|
56
|
-
subwin.setpos(3, 0)
|
57
|
-
subwin.addstr(feeds[pos].resource.title)
|
58
|
-
subwin.setpos(6, 0)
|
59
|
-
subwin.addstr(feeds[pos].description)
|
60
|
-
subwin.refresh
|
61
|
-
Curses.getch
|
62
|
-
subwin.clear
|
63
|
-
subwin.close
|
64
|
-
render_feeds(feeds)
|
65
|
-
Curses.setpos(pos, 0)
|
66
|
-
when "q"
|
67
|
-
break
|
68
|
-
end
|
69
|
-
end
|
70
|
-
ensure
|
71
|
-
Curses.close_screen
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
module_function
|
76
|
-
def render_feeds(feeds)
|
77
|
-
feeds.each_with_index do |feed, i|
|
78
|
-
Curses.setpos(i, 0)
|
79
|
-
title = feed.title.gsub(/\n/, " ")
|
80
|
-
date = feed.date.strftime("%Y/%m/%d")
|
81
|
-
Curses.addstr("#{date} #{title}")
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
private_class_method :render_feeds
|
86
|
-
end
|
87
|
-
end
|
data/lib/feedcellar/tree_view.rb
DELETED
@@ -1,133 +0,0 @@
|
|
1
|
-
# class Feedcellar::TreeView
|
2
|
-
#
|
3
|
-
# Copyright (C) 2014 Masafumi Yokoyama <myokoym@gmail.com>
|
4
|
-
#
|
5
|
-
# This library is free software; you can redistribute it and/or
|
6
|
-
# modify it under the terms of the GNU Lesser General Public
|
7
|
-
# License as published by the Free Software Foundation; either
|
8
|
-
# version 2.1 of the License, or (at your option) any later version.
|
9
|
-
#
|
10
|
-
# This library is distributed in the hope that it will be useful,
|
11
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
-
# Lesser General Public License for more details.
|
14
|
-
#
|
15
|
-
# You should have received a copy of the GNU Lesser General Public
|
16
|
-
# License along with this library; if not, write to the Free Software
|
17
|
-
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
|
-
|
19
|
-
require "gtk2"
|
20
|
-
require "erb"
|
21
|
-
|
22
|
-
module Feedcellar
|
23
|
-
class TreeView < Gtk::TreeView
|
24
|
-
KEY_COLUMN, TITLE_COLUMN, LINK_COLUMN, DESCRIPTION_COLUMN, DATE_COLUMN, STRFTIME_COLUMN, RESOURCE_AND_TITLE_COLUMN = *0..6
|
25
|
-
|
26
|
-
def initialize(records)
|
27
|
-
super()
|
28
|
-
@model = Gtk::ListStore.new(String, String, String, String, Time, String, String)
|
29
|
-
create_tree(@model, records)
|
30
|
-
end
|
31
|
-
|
32
|
-
def next
|
33
|
-
move_cursor(Gtk::MovementStep::DISPLAY_LINES, 1)
|
34
|
-
end
|
35
|
-
|
36
|
-
def prev
|
37
|
-
move_cursor(Gtk::MovementStep::DISPLAY_LINES, -1)
|
38
|
-
end
|
39
|
-
|
40
|
-
def remove_selected_record
|
41
|
-
return nil unless selected_iter
|
42
|
-
@model.remove(selected_iter)
|
43
|
-
end
|
44
|
-
|
45
|
-
def get_link(path)
|
46
|
-
@model.get_iter(path).get_value(LINK_COLUMN)
|
47
|
-
end
|
48
|
-
|
49
|
-
def selected_key
|
50
|
-
return nil unless selected_iter
|
51
|
-
selected_iter.get_value(KEY_COLUMN)
|
52
|
-
end
|
53
|
-
|
54
|
-
def selected_title
|
55
|
-
return nil unless selected_iter
|
56
|
-
selected_iter.get_value(TITLE_COLUMN)
|
57
|
-
end
|
58
|
-
|
59
|
-
def selected_link
|
60
|
-
return nil unless selected_iter
|
61
|
-
selected_iter.get_value(LINK_COLUMN)
|
62
|
-
end
|
63
|
-
|
64
|
-
def selected_description
|
65
|
-
return nil unless selected_iter
|
66
|
-
selected_iter.get_value(DESCRIPTION_COLUMN)
|
67
|
-
end
|
68
|
-
|
69
|
-
def selected_date
|
70
|
-
return nil unless selected_iter
|
71
|
-
selected_iter.get_value(DATE_COLUMN)
|
72
|
-
end
|
73
|
-
|
74
|
-
def selected_iter
|
75
|
-
selection.selected
|
76
|
-
end
|
77
|
-
|
78
|
-
def update_model(records)
|
79
|
-
model = Gtk::ListStore.new(String, String, String, String, Time, String, String)
|
80
|
-
records.each do |record|
|
81
|
-
load_record(model, record)
|
82
|
-
end
|
83
|
-
set_model(model)
|
84
|
-
@model = model
|
85
|
-
end
|
86
|
-
|
87
|
-
private
|
88
|
-
def create_tree(model, records)
|
89
|
-
set_model(model)
|
90
|
-
self.search_column = TITLE_COLUMN
|
91
|
-
self.enable_search = false
|
92
|
-
self.rules_hint = true
|
93
|
-
self.tooltip_column = DESCRIPTION_COLUMN
|
94
|
-
|
95
|
-
selection.set_mode(:browse)
|
96
|
-
|
97
|
-
records.each do |record|
|
98
|
-
load_record(model, record)
|
99
|
-
end
|
100
|
-
|
101
|
-
column = create_column("Date", STRFTIME_COLUMN)
|
102
|
-
append_column(column)
|
103
|
-
|
104
|
-
column = create_column("Title", RESOURCE_AND_TITLE_COLUMN)
|
105
|
-
append_column(column)
|
106
|
-
|
107
|
-
expand_all
|
108
|
-
end
|
109
|
-
|
110
|
-
def create_column(title, index)
|
111
|
-
column = Gtk::TreeViewColumn.new
|
112
|
-
column.title = title
|
113
|
-
renderer = Gtk::CellRendererText.new
|
114
|
-
column.pack_start(renderer, :expand => false)
|
115
|
-
column.add_attribute(renderer, :text, index)
|
116
|
-
column.set_sort_column_id(index)
|
117
|
-
column
|
118
|
-
end
|
119
|
-
|
120
|
-
def load_record(model, record)
|
121
|
-
iter = model.append
|
122
|
-
iter.set_value(KEY_COLUMN, record._key)
|
123
|
-
iter.set_value(TITLE_COLUMN, record.title)
|
124
|
-
iter.set_value(LINK_COLUMN, record.link)
|
125
|
-
escaped_description = ERB::Util.html_escape(record.description)
|
126
|
-
iter.set_value(DESCRIPTION_COLUMN, escaped_description)
|
127
|
-
iter.set_value(DATE_COLUMN, record.date)
|
128
|
-
iter.set_value(STRFTIME_COLUMN, record.date.strftime("%Y-%m-%d\n%H:%M:%S"))
|
129
|
-
text = [record.resource.title, record.title].join("\n")
|
130
|
-
iter.set_value(RESOURCE_AND_TITLE_COLUMN, text)
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
%h1 feedcellar
|
2
|
-
%p= "Powered by Groonga #{groonga_version} and Rroonga #{rroonga_version}."
|
3
|
-
%form{:action => url("/search", false, true), :method => :get}
|
4
|
-
%input{:type => "textarea", :name => "word", :size => 20, :value => params[:word]}
|
5
|
-
%input{:type => "submit", :value => "Search"}
|
6
|
-
- if @feeds
|
7
|
-
%p
|
8
|
-
- grouping(@feeds).each do |resource|
|
9
|
-
= link_to(drilled_label(resource), drilled_url(resource))
|
10
|
-
= paginate(@paginated_feeds)
|
11
|
-
%ul
|
12
|
-
- @paginated_feeds.each do |feed|
|
13
|
-
%li
|
14
|
-
%p
|
15
|
-
= link_to("#{feed.title} - #{feed.resource.title}", feed.link)
|
16
|
-
= paginate(@paginated_feeds)
|
data/lib/feedcellar/web.rb
DELETED
@@ -1,92 +0,0 @@
|
|
1
|
-
# class Feedcellar::Web
|
2
|
-
#
|
3
|
-
# Copyright (C) 2014-2015 Masafumi Yokoyama <myokoym@gmail.com>
|
4
|
-
#
|
5
|
-
# This library is free software; you can redistribute it and/or
|
6
|
-
# modify it under the terms of the GNU Lesser General Public
|
7
|
-
# License as published by the Free Software Foundation; either
|
8
|
-
# version 2.1 of the License, or (at your option) any later version.
|
9
|
-
#
|
10
|
-
# This library is distributed in the hope that it will be useful,
|
11
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
-
# Lesser General Public License for more details.
|
14
|
-
#
|
15
|
-
# You should have received a copy of the GNU Lesser General Public
|
16
|
-
# License along with this library; if not, write to the Free Software
|
17
|
-
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
|
-
|
19
|
-
require "sinatra/base"
|
20
|
-
require "haml"
|
21
|
-
require "padrino-helpers"
|
22
|
-
require "kaminari/sinatra"
|
23
|
-
require "feedcellar/command"
|
24
|
-
|
25
|
-
module Feedcellar
|
26
|
-
class Web < Sinatra::Base
|
27
|
-
helpers Kaminari::Helpers::SinatraHelpers
|
28
|
-
|
29
|
-
get "/" do
|
30
|
-
haml :index
|
31
|
-
end
|
32
|
-
|
33
|
-
get "/search" do
|
34
|
-
if params[:word]
|
35
|
-
words = params[:word].split(" ")
|
36
|
-
else
|
37
|
-
words = []
|
38
|
-
end
|
39
|
-
options ||= {}
|
40
|
-
options[:resource_id] = params[:resource_id] if params[:resource_id]
|
41
|
-
@feeds = search(words, options)
|
42
|
-
if @feeds
|
43
|
-
page = params[:page]
|
44
|
-
n_per_page = options[:n_per_page] || 50
|
45
|
-
@paginated_feeds = pagenate_feeds(@feeds, page, n_per_page)
|
46
|
-
end
|
47
|
-
haml :index
|
48
|
-
end
|
49
|
-
|
50
|
-
get "/registers.opml" do
|
51
|
-
content_type :xml
|
52
|
-
opml = nil
|
53
|
-
GroongaDatabase.new.open(Command.new.database_dir) do |database|
|
54
|
-
opml = Opml.build(database.resources.records)
|
55
|
-
end
|
56
|
-
opml
|
57
|
-
end
|
58
|
-
|
59
|
-
helpers do
|
60
|
-
def search(words, options={})
|
61
|
-
database = GroongaDatabase.new
|
62
|
-
database.open(Command.new.database_dir)
|
63
|
-
GroongaSearcher.search(database, words, options)
|
64
|
-
end
|
65
|
-
|
66
|
-
def pagenate_feeds(feeds, page, n_per_page)
|
67
|
-
Kaminari.paginate_array(feeds.to_a).page(page).per(n_per_page)
|
68
|
-
end
|
69
|
-
|
70
|
-
def grouping(table)
|
71
|
-
key = "resource"
|
72
|
-
table.group(key).sort_by {|item| item.n_sub_records }.reverse
|
73
|
-
end
|
74
|
-
|
75
|
-
def drilled_url(resource)
|
76
|
-
url("/search?resource_id=#{resource._id}&word=#{params[:word]}")
|
77
|
-
end
|
78
|
-
|
79
|
-
def drilled_label(resource)
|
80
|
-
"#{resource.title} (#{resource.n_sub_records})"
|
81
|
-
end
|
82
|
-
|
83
|
-
def groonga_version
|
84
|
-
Groonga::VERSION[0..2].join(".")
|
85
|
-
end
|
86
|
-
|
87
|
-
def rroonga_version
|
88
|
-
Groonga::BINDINGS_VERSION.join(".")
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
data/lib/feedcellar/window.rb
DELETED
@@ -1,168 +0,0 @@
|
|
1
|
-
# class Feedcellar::Window
|
2
|
-
#
|
3
|
-
# Copyright (C) 2014 Masafumi Yokoyama <myokoym@gmail.com>
|
4
|
-
#
|
5
|
-
# This library is free software; you can redistribute it and/or
|
6
|
-
# modify it under the terms of the GNU Lesser General Public
|
7
|
-
# License as published by the Free Software Foundation; either
|
8
|
-
# version 2.1 of the License, or (at your option) any later version.
|
9
|
-
#
|
10
|
-
# This library is distributed in the hope that it will be useful,
|
11
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
-
# Lesser General Public License for more details.
|
14
|
-
#
|
15
|
-
# You should have received a copy of the GNU Lesser General Public
|
16
|
-
# License along with this library; if not, write to the Free Software
|
17
|
-
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
|
-
|
19
|
-
require "gtk2"
|
20
|
-
require "feedcellar/tree_view"
|
21
|
-
require "feedcellar/command"
|
22
|
-
require "feedcellar/groonga_database"
|
23
|
-
require "feedcellar/groonga_searcher"
|
24
|
-
|
25
|
-
module Feedcellar
|
26
|
-
class Window < Gtk::Window
|
27
|
-
def initialize(database_dir, options)
|
28
|
-
super()
|
29
|
-
@database = GroongaDatabase.new
|
30
|
-
@database.open(database_dir)
|
31
|
-
@options = options
|
32
|
-
self.title = "Feedcellar"
|
33
|
-
set_default_size(640, 480)
|
34
|
-
signal_connect("destroy") do
|
35
|
-
@database.close unless @database.closed?
|
36
|
-
Gtk.main_quit
|
37
|
-
end
|
38
|
-
|
39
|
-
@vbox = Gtk::VBox.new
|
40
|
-
add(@vbox)
|
41
|
-
|
42
|
-
@entry_hbox = Gtk::HBox.new
|
43
|
-
@vbox.pack_start(@entry_hbox, false, false, 0)
|
44
|
-
|
45
|
-
@entry = Gtk::Entry.new
|
46
|
-
@entry_hbox.add(@entry)
|
47
|
-
@search_button = Gtk::Button.new("Search")
|
48
|
-
@search_button.signal_connect("clicked") do
|
49
|
-
words = @entry.text.split(" ")
|
50
|
-
records = search(words, @options)
|
51
|
-
@tree_view.update_model(records)
|
52
|
-
end
|
53
|
-
@entry_hbox.add(@search_button)
|
54
|
-
|
55
|
-
@scrolled_window = Gtk::ScrolledWindow.new
|
56
|
-
@scrolled_window.set_policy(:automatic, :automatic)
|
57
|
-
@vbox.pack_start(@scrolled_window, true, true, 0)
|
58
|
-
|
59
|
-
records = all_records(options)
|
60
|
-
|
61
|
-
@tree_view = TreeView.new(records)
|
62
|
-
@scrolled_window.add(@tree_view)
|
63
|
-
|
64
|
-
@label = Gtk::Label.new
|
65
|
-
@label.text = "Double Click or Press Return: Open a Link into Browser/ Ctrl+d: Delete from Data Store"
|
66
|
-
@vbox.pack_start(@label, false, false, 0)
|
67
|
-
|
68
|
-
@tree_view.signal_connect("row-activated") do |tree_view, path, column|
|
69
|
-
show_uri(@tree_view.selected_link)
|
70
|
-
end
|
71
|
-
|
72
|
-
define_key_bindings
|
73
|
-
end
|
74
|
-
|
75
|
-
def run
|
76
|
-
show_all
|
77
|
-
Gtk.main
|
78
|
-
end
|
79
|
-
|
80
|
-
private
|
81
|
-
def search(words, options)
|
82
|
-
records = GroongaSearcher.search(@database, words, options)
|
83
|
-
if options[:lines]
|
84
|
-
records.take(options[:lines])
|
85
|
-
else
|
86
|
-
records
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
def all_records(options)
|
91
|
-
search(nil, options)
|
92
|
-
end
|
93
|
-
|
94
|
-
def define_key_bindings
|
95
|
-
signal_connect("key-press-event") do |widget, event|
|
96
|
-
handled = false
|
97
|
-
|
98
|
-
if event.state.control_mask?
|
99
|
-
handled = action_from_keyval_with_control_mask(event.keyval)
|
100
|
-
else
|
101
|
-
handled = action_from_keyval(event.keyval)
|
102
|
-
end
|
103
|
-
|
104
|
-
handled
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
def action_from_keyval(keyval)
|
109
|
-
case keyval
|
110
|
-
when Gdk::Keyval::GDK_KEY_n
|
111
|
-
@tree_view.next
|
112
|
-
when Gdk::Keyval::GDK_KEY_p
|
113
|
-
@tree_view.prev
|
114
|
-
when Gdk::Keyval::GDK_KEY_Return
|
115
|
-
show_uri(@tree_view.selected_link)
|
116
|
-
when Gdk::Keyval::GDK_KEY_h
|
117
|
-
@scrolled_window.hadjustment.value -= 17
|
118
|
-
when Gdk::Keyval::GDK_KEY_j
|
119
|
-
@scrolled_window.vadjustment.value += 17
|
120
|
-
when Gdk::Keyval::GDK_KEY_k
|
121
|
-
@scrolled_window.vadjustment.value -= 17
|
122
|
-
when Gdk::Keyval::GDK_KEY_l
|
123
|
-
@scrolled_window.hadjustment.value += 17
|
124
|
-
when Gdk::Keyval::GDK_KEY_q
|
125
|
-
destroy
|
126
|
-
else
|
127
|
-
return false
|
128
|
-
end
|
129
|
-
true
|
130
|
-
end
|
131
|
-
|
132
|
-
def action_from_keyval_with_control_mask(keyval)
|
133
|
-
case keyval
|
134
|
-
when Gdk::Keyval::GDK_KEY_n
|
135
|
-
10.times { @tree_view.next }
|
136
|
-
when Gdk::Keyval::GDK_KEY_p
|
137
|
-
10.times { @tree_view.prev }
|
138
|
-
when Gdk::Keyval::GDK_KEY_d
|
139
|
-
key = @tree_view.selected_key
|
140
|
-
if key
|
141
|
-
# TODO: don't want to use Command class.
|
142
|
-
GroongaDatabase.new.open(Command.new.database_dir) do |database|
|
143
|
-
database.delete(key)
|
144
|
-
end
|
145
|
-
@tree_view.remove_selected_record
|
146
|
-
end
|
147
|
-
else
|
148
|
-
return false
|
149
|
-
end
|
150
|
-
true
|
151
|
-
end
|
152
|
-
|
153
|
-
def show_uri(uri)
|
154
|
-
case RUBY_PLATFORM
|
155
|
-
when /darwin/
|
156
|
-
system("open", uri)
|
157
|
-
when /mswin|mingw|cygwin|bccwin/
|
158
|
-
system("start", uri)
|
159
|
-
else
|
160
|
-
if Gtk.respond_to?(:show_uri)
|
161
|
-
Gtk.show_uri(uri)
|
162
|
-
else
|
163
|
-
system("firefox", uri)
|
164
|
-
end
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
data/test/test-curses_view.rb
DELETED
@@ -1,101 +0,0 @@
|
|
1
|
-
# class CursesViewTest
|
2
|
-
#
|
3
|
-
# Copyright (C) 2013-2014 Masafumi Yokoyama <myokoym@gmail.com>
|
4
|
-
#
|
5
|
-
# This library is free software; you can redistribute it and/or
|
6
|
-
# modify it under the terms of the GNU Lesser General Public
|
7
|
-
# License as published by the Free Software Foundation; either
|
8
|
-
# version 2.1 of the License, or (at your option) any later version.
|
9
|
-
#
|
10
|
-
# This library is distributed in the hope that it will be useful,
|
11
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
-
# Lesser General Public License for more details.
|
14
|
-
#
|
15
|
-
# You should have received a copy of the GNU Lesser General Public
|
16
|
-
# License along with this library; if not, write to the Free Software
|
17
|
-
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
|
-
|
19
|
-
require "feedcellar/curses_view"
|
20
|
-
|
21
|
-
class CursesViewTest < Test::Unit::TestCase
|
22
|
-
def setup
|
23
|
-
@feeds = [
|
24
|
-
Feed.new("title", "http://example.net/post1", "desc1"),
|
25
|
-
Feed.new("title", "http://example.net/post2", "desc2"),
|
26
|
-
]
|
27
|
-
end
|
28
|
-
|
29
|
-
def test_run_quit
|
30
|
-
mock(Curses).getch { "q" }
|
31
|
-
assert_nothing_raised do
|
32
|
-
Feedcellar::CursesView.run(@feeds)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def test_run_down
|
37
|
-
mock(Curses).getch { "j" }
|
38
|
-
mock(Curses).getch { "q" }
|
39
|
-
assert_nothing_raised do
|
40
|
-
Feedcellar::CursesView.run(@feeds)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def test_run_up
|
45
|
-
mock(Curses).getch { "k" }
|
46
|
-
mock(Curses).getch { "q" }
|
47
|
-
assert_nothing_raised do
|
48
|
-
Feedcellar::CursesView.run(@feeds)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def test_run_firefox
|
53
|
-
mock(Curses).getch { "f" }
|
54
|
-
mock(Feedcellar::CursesView).spawn("firefox",
|
55
|
-
@feeds[0].link,
|
56
|
-
[:out, :err] => "/dev/null")
|
57
|
-
mock(Curses).getch { "q" }
|
58
|
-
assert_nothing_raised do
|
59
|
-
Feedcellar::CursesView.run(@feeds)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def test_run_down_and_firefox
|
64
|
-
mock(Curses).getch { "j" }
|
65
|
-
mock(Curses).getch { "f" }
|
66
|
-
mock(Feedcellar::CursesView).spawn("firefox",
|
67
|
-
@feeds[1].link,
|
68
|
-
[:out, :err] => "/dev/null")
|
69
|
-
mock(Curses).getch { "q" }
|
70
|
-
assert_nothing_raised do
|
71
|
-
Feedcellar::CursesView.run(@feeds)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def test_run_description
|
76
|
-
mock(Curses).getch { "d" }
|
77
|
-
mock(Curses).getch { "q" }
|
78
|
-
mock(Curses).getch { "q" }
|
79
|
-
assert_nothing_raised do
|
80
|
-
Feedcellar::CursesView.run(@feeds)
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
class Feed
|
85
|
-
attr_reader :title, :link, :date, :description, :resource
|
86
|
-
def initialize(title, link, description)
|
87
|
-
@title = title
|
88
|
-
@link = link
|
89
|
-
@date = Time.now
|
90
|
-
@description = description
|
91
|
-
@resource = Resource.new("Web Site's Title")
|
92
|
-
end
|
93
|
-
|
94
|
-
class Resource
|
95
|
-
attr_reader :title
|
96
|
-
def initialize(title)
|
97
|
-
@title = title
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|