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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dcfa9e77897b4d4d13dfb10c1d9f790c81a7af69
4
- data.tar.gz: 8cca83a201985ae667e952db218b905b90aae003
3
+ metadata.gz: 9b0b56bc49519216392bb6b0554492c44760f5c0
4
+ data.tar.gz: 3712ec8b64294e089f4cf1be5f5437f3344ea0b9
5
5
  SHA512:
6
- metadata.gz: d6e20797bb035fd7047da253b321c58d3b384b6e5e6bf13517eab8c175dc8451a5ae5bbcd8a47c09fa55aa3d475f0395b0c732284134aa8e97a2f3252b8f0c20
7
- data.tar.gz: 5709b3c2cba9482a236d2360158f1dd1a039fa22749289fb059fb1b610f1a18be5187c717aaa4e30f28bacca41fb1eb7e3b845364007bcef0bc82f2ed0b349f2
6
+ metadata.gz: 73a494cdbe21660f88e8c3b85b88b5a1950d6ae36267d7d7e5d7c5d42576bdebfb518bbae7d1701a4ec02cf7bf2c640568b507a2bc52e910ad8ac5adf9127d2d
7
+ data.tar.gz: 2679352036daeeafb087b32b4a8b22b1ded9f1cd37698448b21f9812984fe081eb4c826504c6e8ac00a4858ebee1d7b3c48e28bcdea8980433eac1657a304e33
data/.travis.yml CHANGED
@@ -1,5 +1,4 @@
1
1
  rvm:
2
- - 1.9.3
3
2
  - 2.0.0
4
3
  - 2.1
5
4
  - 2.2
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
- ### Show feeds in a web browser
48
+ ### Start web server and show feeds in a web browser
49
49
 
50
- $ feedcellar web [--silent]
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
- $ gem install gtk2
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
- $ gem install curses # for Ruby 2.1
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-2014 Masafumi Yokoyama `<myokoym@gmail.com>`
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-2014 Masafumi Yokoyama <myokoym@gmail.com>
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")
@@ -1,6 +1,6 @@
1
1
  # class Feedcellar::Command
2
2
  #
3
- # Copyright (C) 2013-2014 Masafumi Yokoyama <myokoym@gmail.com>
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[:curses]
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
@@ -1,6 +1,6 @@
1
1
  # constant Feedcellar::VERSION
2
2
  #
3
- # Copyright (C) 2013-2014 Masafumi Yokoyama <myokoym@gmail.com>
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.4.1"
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.1
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
@@ -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)
@@ -1,6 +0,0 @@
1
- !!!
2
- %html
3
- %head
4
- %title feedcellar
5
- %body
6
- = yield
@@ -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
@@ -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
@@ -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