feedcellar 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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