clipcellar 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,56 @@
1
+ # Copyright (C) 2014 Masafumi Yokoyama <myokoym@gmail.com>
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License as published by the Free Software Foundation; either
6
+ # version 2.1 of the License, or (at your option) any later version.
7
+ #
8
+ # This library is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public
14
+ # License along with this library; if not, write to the Free Software
15
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
+
17
+ module Clipcellar
18
+ class GroongaSearcher
19
+ class << self
20
+ def search(database, words, options)
21
+ clipboards = database.clipboards
22
+ selected_clipboards = clipboards.select do |clipboard|
23
+ expression = nil
24
+ words.each do |word|
25
+ sub_expression = (clipboard.text =~ word)
26
+ if expression.nil?
27
+ expression = sub_expression
28
+ else
29
+ expression &= sub_expression
30
+ end
31
+ end
32
+
33
+ if options[:mtime]
34
+ base_date = (Time.now - (options[:mtime] * 60 * 60 * 24))
35
+ mtime_expression = clipboard.date > base_date
36
+ if expression.nil?
37
+ expression = mtime_expression
38
+ else
39
+ expression &= mtime_expression
40
+ end
41
+ end
42
+
43
+ expression
44
+ end
45
+
46
+ order = options[:reverse] ? "ascending" : "descending"
47
+ sorted_clipboards = selected_clipboards.sort([{
48
+ :key => "created_at",
49
+ :order => order,
50
+ }])
51
+
52
+ sorted_clipboards
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,108 @@
1
+ # Copyright (C) 2014 Masafumi Yokoyama <myokoym@gmail.com>
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License as published by the Free Software Foundation; either
6
+ # version 2.1 of the License, or (at your option) any later version.
7
+ #
8
+ # This library is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public
14
+ # License along with this library; if not, write to the Free Software
15
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
+
17
+ require "gtk2"
18
+ require "erb"
19
+
20
+ module Clipcellar
21
+ class TreeView < Gtk::TreeView
22
+ KEY_COLUMN, TEXT_COLUMN, TIME_COLUMN, STRFTIME_COLUMN, LINE_COLUMN, ESCAPED_TEXT_COLUMN = *0..5
23
+
24
+ def initialize(records)
25
+ super()
26
+ @model = Gtk::ListStore.new(String, String, Time, String, String, String)
27
+ create_tree(@model, records)
28
+ end
29
+
30
+ def next
31
+ move_cursor(Gtk::MovementStep::DISPLAY_LINES, 1)
32
+ end
33
+
34
+ def prev
35
+ move_cursor(Gtk::MovementStep::DISPLAY_LINES, -1)
36
+ end
37
+
38
+ def remove_selected_record
39
+ return nil unless selected_iter
40
+ @model.remove(selected_iter)
41
+ end
42
+
43
+ def get_text(path)
44
+ @model.get_iter(path).get_value(TEXT_COLUMN)
45
+ end
46
+
47
+ def selected_key
48
+ return nil unless selected_iter
49
+ selected_iter.get_value(KEY_COLUMN)
50
+ end
51
+
52
+ def selected_text
53
+ return nil unless selected_iter
54
+ selected_iter.get_value(TEXT_COLUMN)
55
+ end
56
+
57
+ def selected_time
58
+ return nil unless selected_iter
59
+ selected_iter.get_value(TIME_COLUMN)
60
+ end
61
+
62
+ def selected_iter
63
+ selection.selected
64
+ end
65
+
66
+ private
67
+ def create_tree(model, records)
68
+ set_model(model)
69
+ self.search_column = TEXT_COLUMN
70
+ self.enable_search = false
71
+ self.rules_hint = true
72
+ self.tooltip_column = ESCAPED_TEXT_COLUMN
73
+
74
+ selection.set_mode(:browse)
75
+
76
+ records.each do |record|
77
+ load_record(model, record)
78
+ end
79
+
80
+ column = Gtk::TreeViewColumn.new
81
+ column.title = "Inserted Time"
82
+ append_column(column)
83
+ renderer = Gtk::CellRendererText.new
84
+ column.pack_start(renderer, :expand => false)
85
+ column.add_attribute(renderer, :text, STRFTIME_COLUMN)
86
+
87
+ column = Gtk::TreeViewColumn.new
88
+ column.title = "Part of a Text (the Full Text appears in a Tooltip)"
89
+ append_column(column)
90
+ renderer = Gtk::CellRendererText.new
91
+ column.pack_start(renderer, :expand => false)
92
+ column.add_attribute(renderer, :text, LINE_COLUMN)
93
+
94
+ expand_all
95
+ end
96
+
97
+ def load_record(model, record)
98
+ iter = model.append
99
+ iter.set_value(KEY_COLUMN, record[:key])
100
+ iter.set_value(TEXT_COLUMN, record[:text])
101
+ iter.set_value(TIME_COLUMN, record[:time])
102
+ iter.set_value(STRFTIME_COLUMN, record[:time].strftime("%Y-%m-%d %H:%M:%S"))
103
+ iter.set_value(LINE_COLUMN, record[:text].gsub(/[\n\t]/, " ")) if record[:text]
104
+ escaped_text = ERB::Util.html_escape(record[:text])
105
+ iter.set_value(ESCAPED_TEXT_COLUMN, escaped_text)
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,19 @@
1
+ # Copyright (C) 2014 Masafumi Yokoyama <myokoym@gmail.com>
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License as published by the Free Software Foundation; either
6
+ # version 2.1 of the License, or (at your option) any later version.
7
+ #
8
+ # This library is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public
14
+ # License along with this library; if not, write to the Free Software
15
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
+
17
+ module Clipcellar
18
+ VERSION = "0.0.1"
19
+ end
@@ -0,0 +1,121 @@
1
+ # Copyright (C) 2014 Masafumi Yokoyama <myokoym@gmail.com>
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License as published by the Free Software Foundation; either
6
+ # version 2.1 of the License, or (at your option) any later version.
7
+ #
8
+ # This library is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public
14
+ # License along with this library; if not, write to the Free Software
15
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
+
17
+ require "gtk2"
18
+ require "clipcellar/tree_view"
19
+ require "clipcellar/clipboard"
20
+ require "clipcellar/command"
21
+
22
+ module Clipcellar
23
+ class Window < Gtk::Window
24
+ attr_accessor :text
25
+ def initialize(records)
26
+ super()
27
+ @records = records
28
+ self.title = "Clipcellar"
29
+ set_default_size(640, 480)
30
+ signal_connect("destroy") do
31
+ Gtk.main_quit
32
+ end
33
+
34
+ @vbox = Gtk::VBox.new
35
+ add(@vbox)
36
+
37
+ @scrolled_window = Gtk::ScrolledWindow.new
38
+ @scrolled_window.set_policy(:automatic, :automatic)
39
+ @vbox.pack_start(@scrolled_window, true, true, 0)
40
+
41
+ @tree_view = TreeView.new(records)
42
+ @scrolled_window.add(@tree_view)
43
+
44
+ @label = Gtk::Label.new
45
+ @label.text = "Double Click or Press Return: Copy to Clipboard / Ctrl+d: Delete from Data Store"
46
+ @vbox.pack_start(@label, false, false, 0)
47
+
48
+ @tree_view.signal_connect("row-activated") do |tree_view, path, column|
49
+ Clipboard.copy_to_clipboard(@tree_view.selected_text)
50
+ end
51
+
52
+ define_key_bindings
53
+ end
54
+
55
+ def run
56
+ show_all
57
+ Gtk.main
58
+ end
59
+
60
+ private
61
+ def define_key_bindings
62
+ signal_connect("key-press-event") do |widget, event|
63
+ handled = false
64
+
65
+ if event.state.control_mask?
66
+ handled = action_from_keyval_with_control_mask(event.keyval)
67
+ else
68
+ handled = action_from_keyval(event.keyval)
69
+ end
70
+
71
+ handled
72
+ end
73
+ end
74
+
75
+ def action_from_keyval(keyval)
76
+ case keyval
77
+ when Gdk::Keyval::GDK_KEY_n
78
+ @tree_view.next
79
+ when Gdk::Keyval::GDK_KEY_p
80
+ @tree_view.prev
81
+ when Gdk::Keyval::GDK_KEY_Return
82
+ Clipboard.copy_to_clipboard(@tree_view.selected_text)
83
+ when Gdk::Keyval::GDK_KEY_h
84
+ @scrolled_window.hadjustment.value -= 17
85
+ when Gdk::Keyval::GDK_KEY_j
86
+ @scrolled_window.vadjustment.value += 17
87
+ when Gdk::Keyval::GDK_KEY_k
88
+ @scrolled_window.vadjustment.value -= 17
89
+ when Gdk::Keyval::GDK_KEY_l
90
+ @scrolled_window.hadjustment.value += 17
91
+ when Gdk::Keyval::GDK_KEY_q
92
+ destroy
93
+ else
94
+ return false
95
+ end
96
+ true
97
+ end
98
+
99
+ def action_from_keyval_with_control_mask(keyval)
100
+ case keyval
101
+ when Gdk::Keyval::GDK_KEY_n
102
+ 10.times { @tree_view.next }
103
+ when Gdk::Keyval::GDK_KEY_p
104
+ 10.times { @tree_view.prev }
105
+ when Gdk::Keyval::GDK_KEY_d
106
+ # TODO: don't want to use Command class.
107
+ GroongaDatabase.new.open(Command.new.database_dir) do |database|
108
+ database.delete(@tree_view.selected_key)
109
+ end
110
+ @tree_view.remove_selected_record
111
+ else
112
+ return false
113
+ end
114
+ true
115
+ end
116
+
117
+ def clipboard
118
+ Gtk::Clipboard.get(Gdk::Selection::CLIPBOARD)
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
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 "test-unit"
20
+ require "test/unit/notify"
21
+ require "test/unit/rr"
22
+
23
+ base_dir = File.expand_path(File.join(File.dirname(__FILE__), ".."))
24
+ $LOAD_PATH.unshift(File.join(base_dir, "lib"))
25
+ $LOAD_PATH.unshift(File.join(base_dir, "test"))
26
+
27
+ exit Test::Unit::AutoRunner.run(true)
@@ -0,0 +1,53 @@
1
+ # Copyright (C) 2014 Masafumi Yokoyama <myokoym@gmail.com>
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License as published by the Free Software Foundation; either
6
+ # version 2.1 of the License, or (at your option) any later version.
7
+ #
8
+ # This library is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public
14
+ # License along with this library; if not, write to the Free Software
15
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
+
17
+ require "fileutils"
18
+ require "stringio"
19
+ require "clipcellar/version"
20
+ require "clipcellar/command"
21
+
22
+ class CommandTest < Test::Unit::TestCase
23
+ class << self
24
+ def startup
25
+ @@tmpdir_base = File.join(File.dirname(__FILE__), "tmp")
26
+ @@tmpdir = File.join(@@tmpdir_base, "database")
27
+ FileUtils.rm_rf(@@tmpdir)
28
+ FileUtils.mkdir_p(@@tmpdir)
29
+ @@command = Clipcellar::Command.new
30
+ @@command.instance_variable_set(:@base_dir, @@tmpdir_base)
31
+ @@command.instance_variable_set(:@database_dir, @@tmpdir)
32
+ end
33
+
34
+ def shutdown
35
+ FileUtils.rm_rf(@@tmpdir)
36
+ end
37
+ end
38
+
39
+ def test_version
40
+ s = ""
41
+ io = StringIO.new(s)
42
+ $stdout = io
43
+ @@command.version
44
+ assert_equal("#{Clipcellar::VERSION}\n", s)
45
+ $stdout = STDOUT
46
+ end
47
+
48
+ def test_destroy
49
+ assert_true(File.exist?(@@tmpdir))
50
+ @@command.destroy
51
+ assert_false(File.exist?(@@tmpdir))
52
+ end
53
+ end
metadata ADDED
@@ -0,0 +1,178 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: clipcellar
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Masafumi Yokoyama
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-07-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: gtk2
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rroonga
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: thor
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: test-unit
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
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: test-unit-notify
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
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: test-unit-rr
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
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: bundler
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ version: '1.6'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: '1.6'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rake
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: Clipcellar is a full-text searchable data store for clipboard by GTK+
126
+ (via Ruby/GTK2) and Groonga (via Rroonga).
127
+ email:
128
+ - myokoym@gmail.com
129
+ executables:
130
+ - clipcellar
131
+ extensions: []
132
+ extra_rdoc_files: []
133
+ files:
134
+ - .gitignore
135
+ - Gemfile
136
+ - LICENSE.txt
137
+ - NEWS.md
138
+ - README.md
139
+ - Rakefile
140
+ - bin/clipcellar
141
+ - clipcellar.gemspec
142
+ - lib/clipcellar.rb
143
+ - lib/clipcellar/clipboard.rb
144
+ - lib/clipcellar/command.rb
145
+ - lib/clipcellar/groonga_database.rb
146
+ - lib/clipcellar/groonga_searcher.rb
147
+ - lib/clipcellar/tree_view.rb
148
+ - lib/clipcellar/version.rb
149
+ - lib/clipcellar/window.rb
150
+ - test/run-test.rb
151
+ - test/test-command.rb
152
+ homepage: https://github.com/myokoym/clipcellar
153
+ licenses:
154
+ - LGPLv2.1 or later
155
+ metadata: {}
156
+ post_install_message:
157
+ rdoc_options: []
158
+ require_paths:
159
+ - lib
160
+ required_ruby_version: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - '>='
163
+ - !ruby/object:Gem::Version
164
+ version: '0'
165
+ required_rubygems_version: !ruby/object:Gem::Requirement
166
+ requirements:
167
+ - - '>='
168
+ - !ruby/object:Gem::Version
169
+ version: '0'
170
+ requirements: []
171
+ rubyforge_project:
172
+ rubygems_version: 2.0.14
173
+ signing_key:
174
+ specification_version: 4
175
+ summary: Full-Text Searchable Data Store for Clipboard
176
+ test_files:
177
+ - test/run-test.rb
178
+ - test/test-command.rb