picky-client 2.1.2 → 2.2.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.
- data/lib/picky-client/aux/terminal.rb +225 -0
- data/spec/picky-client/aux/terminal_spec.rb +150 -0
- metadata +5 -2
@@ -0,0 +1,225 @@
|
|
1
|
+
module Picky
|
2
|
+
|
3
|
+
# A simple terminal based search.
|
4
|
+
#
|
5
|
+
class Terminal
|
6
|
+
|
7
|
+
attr_reader :client
|
8
|
+
|
9
|
+
def initialize given_uri, id_amount = nil
|
10
|
+
check_highline_gem
|
11
|
+
check_picky_client_gem
|
12
|
+
|
13
|
+
require 'uri'
|
14
|
+
uri = URI.parse given_uri
|
15
|
+
|
16
|
+
# If the user gave a whole url without http, add that and reparse.
|
17
|
+
#
|
18
|
+
unless uri.path
|
19
|
+
uri = URI.parse "http://#{given_uri}"
|
20
|
+
end
|
21
|
+
|
22
|
+
# If the user gave a path without / in front, add one.
|
23
|
+
#
|
24
|
+
unless uri.path =~ /^\//
|
25
|
+
uri.path = "/#{uri.path}"
|
26
|
+
end
|
27
|
+
|
28
|
+
@searches = 0
|
29
|
+
@durations = 0
|
30
|
+
@current_text = ''
|
31
|
+
@cursor_offset = 0
|
32
|
+
@last_ids = ''
|
33
|
+
@id_amount = id_amount && Integer(id_amount) || 20
|
34
|
+
@client = Picky::Client.new :host => (uri.host || 'localhost'), :port => (uri.port || 8080), :path => uri.path
|
35
|
+
|
36
|
+
install_trap
|
37
|
+
end
|
38
|
+
def check_highline_gem # :nodoc:
|
39
|
+
require "highline/system_extensions"
|
40
|
+
extend HighLine::SystemExtensions
|
41
|
+
rescue LoadError
|
42
|
+
warn_gem_missing 'highline', 'the terminal interface'
|
43
|
+
exit 1
|
44
|
+
end
|
45
|
+
def check_picky_client_gem # :nodoc:
|
46
|
+
require 'picky-client'
|
47
|
+
rescue LoadError
|
48
|
+
warn_gem_missing 'picky-client', 'the terminal interface'
|
49
|
+
exit 1
|
50
|
+
end
|
51
|
+
|
52
|
+
# Install the Ctrl-C handler.
|
53
|
+
#
|
54
|
+
def install_trap
|
55
|
+
Signal.trap('INT') do
|
56
|
+
print "\e[100D"
|
57
|
+
flush
|
58
|
+
puts "\n"
|
59
|
+
puts "You performed #{@searches} searches, totalling #{"%.3f" % @durations} seconds."
|
60
|
+
print "\e[100D"
|
61
|
+
flush
|
62
|
+
exit
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Flush to STDOUT.
|
67
|
+
#
|
68
|
+
def flush
|
69
|
+
STDOUT.flush
|
70
|
+
end
|
71
|
+
|
72
|
+
# Position cursor amount to the left.
|
73
|
+
#
|
74
|
+
def left amount = 1
|
75
|
+
print "\e[#{amount}D"
|
76
|
+
flush
|
77
|
+
end
|
78
|
+
|
79
|
+
# Position cursor amount to the right.
|
80
|
+
#
|
81
|
+
def right amount = 1
|
82
|
+
print "\e[#{amount}C"
|
83
|
+
flush
|
84
|
+
end
|
85
|
+
|
86
|
+
# Move cursor to position.
|
87
|
+
#
|
88
|
+
def move_to position
|
89
|
+
relative = position - @cursor_offset
|
90
|
+
if relative > 0
|
91
|
+
right relative
|
92
|
+
else
|
93
|
+
left relative
|
94
|
+
end
|
95
|
+
@cursor_offset = position
|
96
|
+
flush
|
97
|
+
end
|
98
|
+
|
99
|
+
# Delete one character.
|
100
|
+
#
|
101
|
+
def backspace
|
102
|
+
chop_text
|
103
|
+
print "\e[1D \e[1D"
|
104
|
+
flush
|
105
|
+
end
|
106
|
+
|
107
|
+
# Write the text to the input area.
|
108
|
+
#
|
109
|
+
def write text
|
110
|
+
@cursor_offset += text.size
|
111
|
+
print text
|
112
|
+
flush
|
113
|
+
end
|
114
|
+
|
115
|
+
# Chop off one character.
|
116
|
+
#
|
117
|
+
def chop_text
|
118
|
+
@current_text.chop!
|
119
|
+
end
|
120
|
+
|
121
|
+
# Add the given text to the current text.
|
122
|
+
#
|
123
|
+
def add_text text
|
124
|
+
@current_text << text
|
125
|
+
end
|
126
|
+
|
127
|
+
# Type the given text into the input area.
|
128
|
+
#
|
129
|
+
def type_search character
|
130
|
+
add_text character
|
131
|
+
write character
|
132
|
+
end
|
133
|
+
|
134
|
+
# Write the amount of result ids.
|
135
|
+
#
|
136
|
+
def write_results results
|
137
|
+
move_to 0
|
138
|
+
write "%9d" % (results && results.total || 0)
|
139
|
+
move_to 10 + @current_text.size
|
140
|
+
end
|
141
|
+
|
142
|
+
# Move to the id area.
|
143
|
+
#
|
144
|
+
def move_to_ids
|
145
|
+
move_to 12 + @current_text.size
|
146
|
+
end
|
147
|
+
|
148
|
+
# Write the result ids.
|
149
|
+
#
|
150
|
+
def write_ids results
|
151
|
+
move_to_ids
|
152
|
+
write "=> #{results.total ? results.ids(@id_amount) : []}"
|
153
|
+
rescue StandardError => e
|
154
|
+
p e.message
|
155
|
+
p e.backtrace
|
156
|
+
end
|
157
|
+
|
158
|
+
# Clear the result ids.
|
159
|
+
#
|
160
|
+
def clear_ids
|
161
|
+
move_to_ids
|
162
|
+
write @ids_clearing_string ||= " "*200
|
163
|
+
end
|
164
|
+
|
165
|
+
# Log a search.
|
166
|
+
#
|
167
|
+
def log results
|
168
|
+
@searches += 1
|
169
|
+
@durations += (results[:duration] || 0)
|
170
|
+
end
|
171
|
+
|
172
|
+
# Perform a search.
|
173
|
+
#
|
174
|
+
def search full = false
|
175
|
+
client.search @current_text, :ids => (full ? @id_amount : 0)
|
176
|
+
end
|
177
|
+
|
178
|
+
# Perform a search and write the results.
|
179
|
+
#
|
180
|
+
# Handles 404s and connection problems.
|
181
|
+
#
|
182
|
+
def search_and_write full = false
|
183
|
+
results = search full
|
184
|
+
results.extend Picky::Convenience
|
185
|
+
|
186
|
+
log results
|
187
|
+
|
188
|
+
full ? write_ids(results) : clear_ids
|
189
|
+
|
190
|
+
write_results results
|
191
|
+
rescue Errno::ECONNREFUSED => e
|
192
|
+
write "Please start a Picky server listening to #{@client.path}."
|
193
|
+
rescue Yajl::ParseError => e
|
194
|
+
write "Got a 404. Maybe the path #{@client.path} isn't a correct one?"
|
195
|
+
end
|
196
|
+
|
197
|
+
# Run the terminal.
|
198
|
+
#
|
199
|
+
# Note: Uses a simple loop to handle input.
|
200
|
+
#
|
201
|
+
def run
|
202
|
+
puts "Type and see the result count update. Press enter for the first #{@id_amount} result ids."
|
203
|
+
puts "Break with Ctrl-C."
|
204
|
+
|
205
|
+
search_and_write
|
206
|
+
|
207
|
+
loop do
|
208
|
+
input = get_character
|
209
|
+
|
210
|
+
case input
|
211
|
+
when 127
|
212
|
+
backspace
|
213
|
+
search_and_write
|
214
|
+
when 13
|
215
|
+
search_and_write true
|
216
|
+
else # All other.
|
217
|
+
type_search input.chr
|
218
|
+
search_and_write
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
end
|
224
|
+
|
225
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
# We need to load the Statistics file explicitly as the Statistics
|
6
|
+
# are not loaded with the Loader (not needed in the server, only for script runs).
|
7
|
+
#
|
8
|
+
require File.expand_path '../../../../lib/picky-client/aux/terminal', __FILE__
|
9
|
+
|
10
|
+
describe Picky::Terminal do
|
11
|
+
|
12
|
+
let(:terminal) { described_class.new('/some/url') }
|
13
|
+
|
14
|
+
describe 'backspace' do
|
15
|
+
it 'works correctly' do
|
16
|
+
terminal.should_receive(:chop_text).once.ordered.with()
|
17
|
+
terminal.should_receive(:print).once.ordered.with "\e[1D \e[1D"
|
18
|
+
terminal.should_receive(:flush).once.ordered.with()
|
19
|
+
|
20
|
+
terminal.backspace
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe 'write_results' do
|
25
|
+
it 'works correctly' do
|
26
|
+
terminal.should_receive(:move_to).once.ordered.with 0
|
27
|
+
terminal.should_receive(:write).once.ordered.with " 0"
|
28
|
+
terminal.should_receive(:move_to).once.ordered.with 10
|
29
|
+
|
30
|
+
terminal.write_results nil
|
31
|
+
end
|
32
|
+
it 'works correctly' do
|
33
|
+
terminal.should_receive(:move_to).once.ordered.with 0
|
34
|
+
terminal.should_receive(:write).once.ordered.with "123456789"
|
35
|
+
terminal.should_receive(:move_to).once.ordered.with 10
|
36
|
+
|
37
|
+
terminal.write_results stub(:results, :total => 123456789)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe 'search' do
|
42
|
+
before(:each) do
|
43
|
+
@client = stub :client
|
44
|
+
terminal.stub! :client => @client
|
45
|
+
|
46
|
+
terminal.add_text 'hello'
|
47
|
+
end
|
48
|
+
it 'searches full correctly' do
|
49
|
+
@client.should_receive(:search).once.with 'hello', :ids => 20
|
50
|
+
|
51
|
+
terminal.search true
|
52
|
+
end
|
53
|
+
it 'searches full correctly' do
|
54
|
+
terminal = described_class.new('/some/url', 33)
|
55
|
+
terminal.stub! :client => @client
|
56
|
+
|
57
|
+
@client.should_receive(:search).once.with '', :ids => 33
|
58
|
+
|
59
|
+
terminal.search true
|
60
|
+
end
|
61
|
+
it 'searches live correctly' do
|
62
|
+
@client.should_receive(:search).once.with 'hello', :ids => 0
|
63
|
+
|
64
|
+
terminal.search
|
65
|
+
end
|
66
|
+
it 'searches live correctly' do
|
67
|
+
@client.should_receive(:search).once.with 'hello', :ids => 0
|
68
|
+
|
69
|
+
terminal.search false
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe 'clear_ids' do
|
74
|
+
it 'moves to the ids, then clears all' do
|
75
|
+
terminal.should_receive(:move_to_ids).once.with()
|
76
|
+
terminal.should_receive(:write).once.with " "*200
|
77
|
+
|
78
|
+
terminal.clear_ids
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe 'write_ids' do
|
83
|
+
it 'writes the result\'s ids' do
|
84
|
+
terminal.should_receive(:move_to_ids).once.with()
|
85
|
+
terminal.should_receive(:write).once.with "=> []"
|
86
|
+
|
87
|
+
terminal.write_ids stub(:results, :total => nil)
|
88
|
+
end
|
89
|
+
it 'writes the result\'s ids' do
|
90
|
+
terminal.should_receive(:move_to_ids).once.with()
|
91
|
+
terminal.should_receive(:write).once.with "=> [1, 2, 3]"
|
92
|
+
|
93
|
+
terminal.write_ids stub(:results, :total => 3, :ids => [1, 2, 3])
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe 'move_to_ids' do
|
98
|
+
it 'moves to a specific place' do
|
99
|
+
terminal.should_receive(:move_to).once.with 12
|
100
|
+
|
101
|
+
terminal.move_to_ids
|
102
|
+
end
|
103
|
+
it 'moves to a specific place' do
|
104
|
+
terminal.add_text 'test'
|
105
|
+
|
106
|
+
terminal.should_receive(:move_to).once.with 16
|
107
|
+
|
108
|
+
terminal.move_to_ids
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe 'left' do
|
113
|
+
it 'moves by amount' do
|
114
|
+
terminal.should_receive(:print).once.ordered.with "\e[13D"
|
115
|
+
terminal.should_receive(:flush).once.ordered
|
116
|
+
|
117
|
+
terminal.left 13
|
118
|
+
end
|
119
|
+
it 'default is 1' do
|
120
|
+
terminal.should_receive(:print).once.ordered.with "\e[1D"
|
121
|
+
terminal.should_receive(:flush).once.ordered
|
122
|
+
|
123
|
+
terminal.left
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe 'right' do
|
128
|
+
it 'moves by amount' do
|
129
|
+
terminal.should_receive(:print).once.ordered.with "\e[13C"
|
130
|
+
terminal.should_receive(:flush).once.ordered
|
131
|
+
|
132
|
+
terminal.right 13
|
133
|
+
end
|
134
|
+
it 'default is 1' do
|
135
|
+
terminal.should_receive(:print).once.ordered.with "\e[1C"
|
136
|
+
terminal.should_receive(:flush).once.ordered
|
137
|
+
|
138
|
+
terminal.right
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
describe 'flush' do
|
143
|
+
it 'flushes STDOUT' do
|
144
|
+
STDOUT.should_receive(:flush).once.with()
|
145
|
+
|
146
|
+
terminal.flush
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: picky-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 2.
|
5
|
+
version: 2.2.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Florian Hanke
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-04-
|
13
|
+
date: 2011-04-14 00:00:00 +10:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -33,6 +33,7 @@ extensions: []
|
|
33
33
|
extra_rdoc_files:
|
34
34
|
- README.rdoc
|
35
35
|
files:
|
36
|
+
- lib/picky-client/aux/terminal.rb
|
36
37
|
- lib/picky-client/client.rb
|
37
38
|
- lib/picky-client/convenience.rb
|
38
39
|
- lib/picky-client/helper.rb
|
@@ -45,6 +46,7 @@ files:
|
|
45
46
|
- javascripts/jquery-1.5.0.min.js
|
46
47
|
- javascripts/picky.min.js
|
47
48
|
- README.rdoc
|
49
|
+
- spec/picky-client/aux/terminal_spec.rb
|
48
50
|
- spec/picky-client/client_spec.rb
|
49
51
|
- spec/picky-client/convenience_spec.rb
|
50
52
|
- spec/picky-client/helper_spec.rb
|
@@ -77,6 +79,7 @@ signing_key:
|
|
77
79
|
specification_version: 3
|
78
80
|
summary: picky Ruby Search Engine Client
|
79
81
|
test_files:
|
82
|
+
- spec/picky-client/aux/terminal_spec.rb
|
80
83
|
- spec/picky-client/client_spec.rb
|
81
84
|
- spec/picky-client/convenience_spec.rb
|
82
85
|
- spec/picky-client/helper_spec.rb
|