tty-process-ctl 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +7 -6
- data/Gemfile.lock +2 -0
- data/VERSION +1 -1
- data/lib/tty-process-ctl.rb +80 -22
- data/spec/tty-process-ctl_spec.rb +166 -85
- data/tty-process-ctl.gemspec +5 -2
- metadata +26 -15
data/Gemfile
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
source "http://rubygems.org"
|
2
2
|
|
3
3
|
group :development do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
gem "rake", "~> 0.9"
|
5
|
+
gem "rspec", "~> 2.8"
|
6
|
+
gem "rdoc", "~> 3.12"
|
7
|
+
gem "bundler", "~> 1.1"
|
8
|
+
gem "jeweler", "~> 1.8"
|
9
|
+
gem "simplecov", ">= 0"
|
10
|
+
gem "cli", "~> 1.0"
|
10
11
|
end
|
data/Gemfile.lock
CHANGED
@@ -11,6 +11,7 @@ GEM
|
|
11
11
|
rdoc
|
12
12
|
json (1.7.5)
|
13
13
|
multi_json (1.3.6)
|
14
|
+
rake (0.9.2.2)
|
14
15
|
rdoc (3.12)
|
15
16
|
json (~> 1.4)
|
16
17
|
rspec (2.11.0)
|
@@ -33,6 +34,7 @@ DEPENDENCIES
|
|
33
34
|
bundler (~> 1.1)
|
34
35
|
cli (~> 1.0)
|
35
36
|
jeweler (~> 1.8)
|
37
|
+
rake (~> 0.9)
|
36
38
|
rdoc (~> 3.12)
|
37
39
|
rspec (~> 2.8)
|
38
40
|
simplecov
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.5.0
|
data/lib/tty-process-ctl.rb
CHANGED
@@ -4,18 +4,43 @@ require 'pty'
|
|
4
4
|
require 'io/console'
|
5
5
|
|
6
6
|
class TTYProcessCtl
|
7
|
-
|
7
|
+
Timeout = Class.new(Timeout::Error)
|
8
|
+
|
9
|
+
class Listener
|
10
|
+
def initialize(&callback)
|
11
|
+
@callback = callback
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(message)
|
15
|
+
@callback.call(message)
|
16
|
+
rescue LocalJumpError => error
|
17
|
+
# brake in listener
|
18
|
+
close if error.reason == :break
|
19
|
+
end
|
20
|
+
|
21
|
+
def on_close(&callback)
|
22
|
+
@on_close = callback unless closed?
|
23
|
+
self
|
24
|
+
end
|
25
|
+
|
26
|
+
def close
|
27
|
+
@on_close.call(self) if @on_close
|
28
|
+
@closed = true
|
29
|
+
end
|
30
|
+
|
31
|
+
def closed?
|
32
|
+
@closed
|
33
|
+
end
|
8
34
|
end
|
9
35
|
|
10
36
|
include Enumerable
|
11
37
|
|
12
38
|
def initialize(command, options = {})
|
13
|
-
@
|
14
|
-
@max_messages = options[:max_messages] || 4000
|
39
|
+
@backlog_size = options[:backlog_size] || 4000
|
15
40
|
@command = command
|
16
41
|
|
42
|
+
@listeners = []
|
17
43
|
@out_queue = Queue.new
|
18
|
-
@messages = []
|
19
44
|
|
20
45
|
@r, @w, @pid = PTY.spawn(@command)
|
21
46
|
@w.echo = false # disable echoing of commands
|
@@ -47,18 +72,26 @@ class TTYProcessCtl
|
|
47
72
|
raise IOError.new("process '#{@command}' (pid: #{@pid}) not accepting input")
|
48
73
|
end
|
49
74
|
|
50
|
-
def
|
51
|
-
|
75
|
+
def on(regexp = nil, &callback)
|
76
|
+
# return listender to user so he can close it after use
|
77
|
+
listener do |message|
|
78
|
+
next if regexp and message !~ regexp
|
79
|
+
callback.call(message)
|
80
|
+
end
|
52
81
|
end
|
53
82
|
|
54
|
-
def each(options = {})
|
55
|
-
return enum_for(:each, options) unless
|
56
|
-
|
57
|
-
|
58
|
-
|
83
|
+
def each(options = {}, &block)
|
84
|
+
return enum_for(:each, options) unless block
|
85
|
+
listener = listener(&block)
|
86
|
+
begin
|
87
|
+
timeout(options[:timeout]) do
|
88
|
+
true while not listener.closed? and poll
|
59
89
|
end
|
90
|
+
self
|
91
|
+
ensure
|
92
|
+
# make sure we close the listener when each exits
|
93
|
+
listener.close
|
60
94
|
end
|
61
|
-
self
|
62
95
|
end
|
63
96
|
|
64
97
|
def each_until(pattern, options = {})
|
@@ -84,17 +117,25 @@ class TTYProcessCtl
|
|
84
117
|
end
|
85
118
|
|
86
119
|
def wait_exit(options = {})
|
87
|
-
|
120
|
+
poll!(options)
|
88
121
|
@thread.join
|
89
122
|
self
|
90
123
|
end
|
91
124
|
|
92
|
-
def
|
93
|
-
|
94
|
-
|
125
|
+
def poll(options = {})
|
126
|
+
timeout(options[:timeout]) do
|
127
|
+
return process_message
|
95
128
|
end
|
96
|
-
|
97
|
-
|
129
|
+
end
|
130
|
+
|
131
|
+
def poll!(options = {})
|
132
|
+
timeout(options[:timeout]) do
|
133
|
+
true while process_message
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def flush
|
138
|
+
true while process_message_no_block
|
98
139
|
self
|
99
140
|
end
|
100
141
|
|
@@ -108,17 +149,34 @@ class TTYProcessCtl
|
|
108
149
|
end
|
109
150
|
end
|
110
151
|
|
111
|
-
def
|
152
|
+
def listener(&block)
|
153
|
+
listener = Listener.new(&block).on_close do |listener|
|
154
|
+
@listeners.delete(listener)
|
155
|
+
end
|
156
|
+
@listeners << listener
|
157
|
+
listener
|
158
|
+
end
|
159
|
+
|
160
|
+
def process_message_no_block
|
161
|
+
process_message(true)
|
162
|
+
rescue ThreadError
|
163
|
+
nil
|
164
|
+
end
|
165
|
+
|
166
|
+
def process_message(no_block = false)
|
167
|
+
return nil if not alive? and @out_queue.empty?
|
112
168
|
message = @out_queue.pop(no_block)
|
113
169
|
return nil unless message
|
114
|
-
|
115
|
-
@
|
170
|
+
message.freeze
|
171
|
+
@listeners.each do |listener|
|
172
|
+
listener.call(message)
|
173
|
+
end
|
116
174
|
message
|
117
175
|
end
|
118
176
|
|
119
177
|
def enqueue_message(message)
|
120
178
|
@out_queue << message
|
121
|
-
@out_queue.pop while @out_queue.length > @
|
179
|
+
@out_queue.pop while @out_queue.length > @backlog_size
|
122
180
|
end
|
123
181
|
|
124
182
|
def enqueue_end
|
@@ -5,31 +5,45 @@ describe TTYProcessCtl do
|
|
5
5
|
TTYProcessCtl.new('spec/stub')
|
6
6
|
end
|
7
7
|
|
8
|
-
|
9
|
-
subject
|
10
|
-
|
11
|
-
|
8
|
+
after :each do
|
9
|
+
subject.send_command 'stop' if subject.alive?
|
10
|
+
subject.wait_exit
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should be Enumerable' do
|
14
|
+
subject.should respond_to :take
|
15
|
+
subject.take(2).should == ["151 recipes", "16 achievements"]
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should skip oldest messages if backlog queue is full' do
|
19
|
+
subject = TTYProcessCtl.new('spec/stub', backlog_size: 2)
|
12
20
|
|
21
|
+
subject.each_until(/Done/).to_a
|
22
|
+
subject.send_command 'help'
|
23
|
+
subject.send_command 'stop'
|
24
|
+
|
25
|
+
# fait for backlog to overflow
|
26
|
+
sleep 0.2
|
27
|
+
|
28
|
+
subject.each.to_a.should == [
|
29
|
+
"2011-09-19 22:12:00 [INFO] Saving chunks",
|
30
|
+
"2011-09-19 22:12:00 [INFO] Saving chunks"
|
31
|
+
]
|
32
|
+
end
|
33
|
+
|
34
|
+
describe 'process output enumeration' do
|
13
35
|
it 'should allow iterating the output lines' do
|
36
|
+
subject.send_command 'stop'
|
14
37
|
lines_count = 0
|
15
38
|
subject.each do |line|
|
16
39
|
lines_count += 1
|
17
40
|
end
|
18
|
-
lines_count.should ==
|
41
|
+
lines_count.should == 23
|
19
42
|
end
|
20
43
|
|
21
44
|
it 'should allow iterating the output lines with enumerator' do
|
22
|
-
subject.
|
23
|
-
|
24
|
-
|
25
|
-
it 'should be Enumerable' do
|
26
|
-
subject.should respond_to :take
|
27
|
-
subject.take(2).should == ["151 recipes", "16 achievements"]
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'should return nothing if iterating on dead process' do
|
31
|
-
subject.each.to_a.length.should == 20
|
32
|
-
subject.each.to_a.should be_empty
|
45
|
+
subject.send_command 'stop'
|
46
|
+
subject.each.to_a.length.should == 23
|
33
47
|
end
|
34
48
|
|
35
49
|
it 'should allow iteration until pattern is found in message' do
|
@@ -42,8 +56,132 @@ describe TTYProcessCtl do
|
|
42
56
|
|
43
57
|
it 'should allow waiting for message matching pattern' do
|
44
58
|
subject.wait_until(/NOT ENOUGH RAM/)
|
59
|
+
subject.send_command 'stop'
|
45
60
|
subject.each.to_a.first.should == "2011-09-10 12:58:55 [WARNING] To start the server with more ram, launch it as \"java -Xmx1024M -Xms1024M -jar minecraft_server.jar\""
|
46
61
|
end
|
62
|
+
|
63
|
+
it 'should return nothing if iterating on dead process' do
|
64
|
+
subject.send_command 'stop'
|
65
|
+
subject.each.to_a.length.should == 23
|
66
|
+
subject.should_not be_alive
|
67
|
+
subject.each.to_a.should be_empty
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should allow flushing backlog messages' do
|
71
|
+
subject.each_until(/SERVER IS RUNNING/).to_a
|
72
|
+
sleep 0.2
|
73
|
+
|
74
|
+
subject.flush
|
75
|
+
|
76
|
+
subject.send_command 'list'
|
77
|
+
subject.each_until(/Connected players/).to_a.should == ["2011-09-20 14:42:04 [INFO] Connected players: kazuya"]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe 'on message callbacks' do
|
82
|
+
describe 'when enumerating' do
|
83
|
+
it 'should call on message callback' do
|
84
|
+
messages = []
|
85
|
+
subject.on do |message|
|
86
|
+
messages << message
|
87
|
+
end
|
88
|
+
|
89
|
+
subject.wait_until(/NOT ENOUGH RAM/)
|
90
|
+
messages.should == [
|
91
|
+
"151 recipes",
|
92
|
+
"16 achievements",
|
93
|
+
"2011-09-10 12:58:55 [INFO] Starting minecraft server version Beta 1.7.3",
|
94
|
+
"2011-09-10 12:58:55 [WARNING] **** NOT ENOUGH RAM!"
|
95
|
+
]
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'should call on message callback if given regexp matches the message' do
|
99
|
+
messages = []
|
100
|
+
subject.on(/recipes|achievements/) do |message|
|
101
|
+
messages << message
|
102
|
+
end
|
103
|
+
|
104
|
+
subject.wait_until(/NOT ENOUGH RAM/)
|
105
|
+
messages.should == [
|
106
|
+
"151 recipes",
|
107
|
+
"16 achievements"
|
108
|
+
]
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe 'when polling' do
|
113
|
+
it 'should call on message callback' do
|
114
|
+
messages = []
|
115
|
+
subject.on do |message|
|
116
|
+
messages << message
|
117
|
+
end
|
118
|
+
|
119
|
+
subject.send_command 'stop'
|
120
|
+
subject.poll!(timeout: 1.0)
|
121
|
+
|
122
|
+
messages.length.should == 23
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'should call on message callback if given regexp matches the message' do
|
126
|
+
messages = []
|
127
|
+
subject.on(/recipes|achievements/) do |message|
|
128
|
+
messages << message
|
129
|
+
end
|
130
|
+
|
131
|
+
subject.send_command 'stop'
|
132
|
+
subject.poll!(timeout: 1.0)
|
133
|
+
|
134
|
+
messages.should == [
|
135
|
+
"151 recipes",
|
136
|
+
"16 achievements"
|
137
|
+
]
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
describe 'when flushing' do
|
142
|
+
it 'should call on message callback if given regexp matches the message' do
|
143
|
+
messages = []
|
144
|
+
subject.on(/recipes|achievements/) do |message|
|
145
|
+
messages << message
|
146
|
+
end
|
147
|
+
|
148
|
+
sleep 1.0
|
149
|
+
subject.flush
|
150
|
+
|
151
|
+
messages.should == [
|
152
|
+
"151 recipes",
|
153
|
+
"16 achievements"
|
154
|
+
]
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
describe 'closing' do
|
159
|
+
it 'with close method on listener' do
|
160
|
+
counter = 0
|
161
|
+
listener = subject.on do
|
162
|
+
counter += 1
|
163
|
+
end
|
164
|
+
|
165
|
+
subject.poll
|
166
|
+
listener.close
|
167
|
+
subject.poll
|
168
|
+
|
169
|
+
counter.should == 1
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'with break' do
|
173
|
+
counter = 0
|
174
|
+
subject.on do
|
175
|
+
counter += 1
|
176
|
+
break
|
177
|
+
end
|
178
|
+
|
179
|
+
subject.poll
|
180
|
+
subject.poll
|
181
|
+
|
182
|
+
counter.should == 1
|
183
|
+
end
|
184
|
+
end
|
47
185
|
end
|
48
186
|
|
49
187
|
describe 'sending commands' do
|
@@ -76,35 +214,6 @@ describe TTYProcessCtl do
|
|
76
214
|
end
|
77
215
|
end
|
78
216
|
|
79
|
-
describe 'messages' do
|
80
|
-
subject do
|
81
|
-
TTYProcessCtl.new('spec/stub --exit')
|
82
|
-
end
|
83
|
-
|
84
|
-
it 'should allow access to previously outputed messages' do
|
85
|
-
subject.each.to_a
|
86
|
-
subject.messages.length.should == 20
|
87
|
-
end
|
88
|
-
|
89
|
-
describe 'flushing' do
|
90
|
-
subject do
|
91
|
-
TTYProcessCtl.new('spec/stub')
|
92
|
-
end
|
93
|
-
|
94
|
-
it 'should allow flushing queued messages before iteration' do
|
95
|
-
subject.each_until(/SERVER IS RUNNING/).to_a
|
96
|
-
sleep 0.2
|
97
|
-
|
98
|
-
subject.flush
|
99
|
-
|
100
|
-
subject.send_command 'list'
|
101
|
-
subject.each_until(/Connected players/).to_a.should == ["2011-09-20 14:42:04 [INFO] Connected players: kazuya"]
|
102
|
-
|
103
|
-
subject.send_command 'stop'
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
217
|
describe 'process status query' do
|
109
218
|
it 'should allow querying if process is alive' do
|
110
219
|
subject.should be_alive
|
@@ -130,60 +239,34 @@ describe TTYProcessCtl do
|
|
130
239
|
end
|
131
240
|
end
|
132
241
|
|
133
|
-
describe 'limiting' do
|
134
|
-
it 'should allow defining maximum number of messages that can be queued' do
|
135
|
-
subject = TTYProcessCtl.new('spec/stub', max_queue_length: 2)
|
136
|
-
|
137
|
-
subject.each_until(/Done/).to_a
|
138
|
-
subject.send_command 'help'
|
139
|
-
subject.send_command 'stop'
|
140
|
-
|
141
|
-
sleep 0.2
|
142
|
-
subject.each.to_a.length.should == 2
|
143
|
-
subject.wait_exit
|
144
|
-
end
|
145
|
-
|
146
|
-
it 'should allow defining maximum number of messages that can be remembered' do
|
147
|
-
subject = TTYProcessCtl.new('spec/stub', max_messages: 2)
|
148
|
-
|
149
|
-
subject.each_until(/Done/).to_a
|
150
|
-
subject.send_command 'help'
|
151
|
-
subject.flush
|
152
|
-
subject.send_command 'stop'
|
153
|
-
subject.wait_exit
|
154
|
-
|
155
|
-
subject.messages.length.should == 2
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
242
|
describe 'timeout' do
|
160
|
-
|
161
|
-
|
162
|
-
|
243
|
+
subject do
|
244
|
+
# wait for process to be ready and delay each message printout by 0.1 second
|
245
|
+
TTYProcessCtl.new('spec/stub --delay 0.01').wait_until(/151 recipes/, timeout: 1)
|
163
246
|
end
|
164
247
|
|
165
248
|
describe 'each calls with block' do
|
166
249
|
it 'should raise TTYProcessCtl::Timeout on timieout' do
|
167
250
|
expect {
|
168
|
-
subject.each(timeout: 0.1)
|
251
|
+
subject.each(timeout: 0.1){}
|
169
252
|
}.to raise_error TTYProcessCtl::Timeout
|
170
253
|
|
171
254
|
expect {
|
172
|
-
subject.each_until(/bogous/, timeout: 0.1)
|
255
|
+
subject.each_until(/bogous/, timeout: 0.1){}
|
173
256
|
}.to raise_error TTYProcessCtl::Timeout
|
174
257
|
|
175
258
|
expect {
|
176
|
-
subject.each_until_exclude(/bogous/, timeout: 0.1)
|
259
|
+
subject.each_until_exclude(/bogous/, timeout: 0.1){}
|
177
260
|
}.to raise_error TTYProcessCtl::Timeout
|
178
261
|
end
|
179
262
|
|
180
263
|
it 'should not raise error if they return before timeout' do
|
181
264
|
expect {
|
182
|
-
subject.each_until(/
|
265
|
+
subject.each_until(/achievements/, timeout: 1){}
|
183
266
|
}.to_not raise_error TTYProcessCtl::Timeout
|
184
267
|
|
185
268
|
expect {
|
186
|
-
subject.each_until_exclude(/
|
269
|
+
subject.each_until_exclude(/NOT ENOUGH RAM/, timeout: 1){}
|
187
270
|
}.to_not raise_error TTYProcessCtl::Timeout
|
188
271
|
|
189
272
|
expect {
|
@@ -209,11 +292,11 @@ describe TTYProcessCtl do
|
|
209
292
|
|
210
293
|
it 'should not raise error if they return before timeout' do
|
211
294
|
expect {
|
212
|
-
subject.each_until(/
|
295
|
+
subject.each_until(/achievements/, timeout: 1).to_a
|
213
296
|
}.to_not raise_error TTYProcessCtl::Timeout
|
214
297
|
|
215
298
|
expect {
|
216
|
-
subject.each_until_exclude(/
|
299
|
+
subject.each_until_exclude(/NOT ENOUGH RAM/, timeout: 1).to_a
|
217
300
|
}.to_not raise_error TTYProcessCtl::Timeout
|
218
301
|
|
219
302
|
expect {
|
@@ -248,17 +331,15 @@ describe TTYProcessCtl do
|
|
248
331
|
end
|
249
332
|
|
250
333
|
describe 'chaining' do
|
251
|
-
subject do
|
252
|
-
TTYProcessCtl.new('spec/stub --exit')
|
253
|
-
end
|
254
|
-
|
255
334
|
it 'should work with each methods' do
|
335
|
+
subject.send_command 'stop'
|
256
336
|
subject.each_until(/recipes/){}.should == subject
|
257
337
|
subject.each_until_exclude(/achievements/){}.should == subject
|
258
338
|
subject.each{}.should == subject
|
259
339
|
end
|
260
340
|
|
261
341
|
it 'should work with wait methods' do
|
342
|
+
subject.send_command 'stop'
|
262
343
|
subject.wait_until(/Done/){}.should == subject
|
263
344
|
subject.wait_exit{}.should == subject
|
264
345
|
end
|
data/tty-process-ctl.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "tty-process-ctl"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.5.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Jakub Pastuszek"]
|
12
|
-
s.date = "2012-11-
|
12
|
+
s.date = "2012-11-24"
|
13
13
|
s.description = "This gem was created to enable control of interactive terminal applications. It is using pseudo tty to communicate with the process via simple API."
|
14
14
|
s.email = "jpastuszek@gmail.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -44,6 +44,7 @@ Gem::Specification.new do |s|
|
|
44
44
|
s.specification_version = 3
|
45
45
|
|
46
46
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
47
|
+
s.add_development_dependency(%q<rake>, ["~> 0.9"])
|
47
48
|
s.add_development_dependency(%q<rspec>, ["~> 2.8"])
|
48
49
|
s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
|
49
50
|
s.add_development_dependency(%q<bundler>, ["~> 1.1"])
|
@@ -51,6 +52,7 @@ Gem::Specification.new do |s|
|
|
51
52
|
s.add_development_dependency(%q<simplecov>, [">= 0"])
|
52
53
|
s.add_development_dependency(%q<cli>, ["~> 1.0"])
|
53
54
|
else
|
55
|
+
s.add_dependency(%q<rake>, ["~> 0.9"])
|
54
56
|
s.add_dependency(%q<rspec>, ["~> 2.8"])
|
55
57
|
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
56
58
|
s.add_dependency(%q<bundler>, ["~> 1.1"])
|
@@ -59,6 +61,7 @@ Gem::Specification.new do |s|
|
|
59
61
|
s.add_dependency(%q<cli>, ["~> 1.0"])
|
60
62
|
end
|
61
63
|
else
|
64
|
+
s.add_dependency(%q<rake>, ["~> 0.9"])
|
62
65
|
s.add_dependency(%q<rspec>, ["~> 2.8"])
|
63
66
|
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
64
67
|
s.add_dependency(%q<bundler>, ["~> 1.1"])
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tty-process-ctl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,22 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-11-
|
12
|
+
date: 2012-11-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: &70125546618580 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0.9'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70125546618580
|
14
25
|
- !ruby/object:Gem::Dependency
|
15
26
|
name: rspec
|
16
|
-
requirement: &
|
27
|
+
requirement: &70125546616420 !ruby/object:Gem::Requirement
|
17
28
|
none: false
|
18
29
|
requirements:
|
19
30
|
- - ~>
|
@@ -21,10 +32,10 @@ dependencies:
|
|
21
32
|
version: '2.8'
|
22
33
|
type: :development
|
23
34
|
prerelease: false
|
24
|
-
version_requirements: *
|
35
|
+
version_requirements: *70125546616420
|
25
36
|
- !ruby/object:Gem::Dependency
|
26
37
|
name: rdoc
|
27
|
-
requirement: &
|
38
|
+
requirement: &70125546629980 !ruby/object:Gem::Requirement
|
28
39
|
none: false
|
29
40
|
requirements:
|
30
41
|
- - ~>
|
@@ -32,10 +43,10 @@ dependencies:
|
|
32
43
|
version: '3.12'
|
33
44
|
type: :development
|
34
45
|
prerelease: false
|
35
|
-
version_requirements: *
|
46
|
+
version_requirements: *70125546629980
|
36
47
|
- !ruby/object:Gem::Dependency
|
37
48
|
name: bundler
|
38
|
-
requirement: &
|
49
|
+
requirement: &70125546627680 !ruby/object:Gem::Requirement
|
39
50
|
none: false
|
40
51
|
requirements:
|
41
52
|
- - ~>
|
@@ -43,10 +54,10 @@ dependencies:
|
|
43
54
|
version: '1.1'
|
44
55
|
type: :development
|
45
56
|
prerelease: false
|
46
|
-
version_requirements: *
|
57
|
+
version_requirements: *70125546627680
|
47
58
|
- !ruby/object:Gem::Dependency
|
48
59
|
name: jeweler
|
49
|
-
requirement: &
|
60
|
+
requirement: &70125546623080 !ruby/object:Gem::Requirement
|
50
61
|
none: false
|
51
62
|
requirements:
|
52
63
|
- - ~>
|
@@ -54,10 +65,10 @@ dependencies:
|
|
54
65
|
version: '1.8'
|
55
66
|
type: :development
|
56
67
|
prerelease: false
|
57
|
-
version_requirements: *
|
68
|
+
version_requirements: *70125546623080
|
58
69
|
- !ruby/object:Gem::Dependency
|
59
70
|
name: simplecov
|
60
|
-
requirement: &
|
71
|
+
requirement: &70125546577740 !ruby/object:Gem::Requirement
|
61
72
|
none: false
|
62
73
|
requirements:
|
63
74
|
- - ! '>='
|
@@ -65,10 +76,10 @@ dependencies:
|
|
65
76
|
version: '0'
|
66
77
|
type: :development
|
67
78
|
prerelease: false
|
68
|
-
version_requirements: *
|
79
|
+
version_requirements: *70125546577740
|
69
80
|
- !ruby/object:Gem::Dependency
|
70
81
|
name: cli
|
71
|
-
requirement: &
|
82
|
+
requirement: &70125546572940 !ruby/object:Gem::Requirement
|
72
83
|
none: false
|
73
84
|
requirements:
|
74
85
|
- - ~>
|
@@ -76,7 +87,7 @@ dependencies:
|
|
76
87
|
version: '1.0'
|
77
88
|
type: :development
|
78
89
|
prerelease: false
|
79
|
-
version_requirements: *
|
90
|
+
version_requirements: *70125546572940
|
80
91
|
description: This gem was created to enable control of interactive terminal applications.
|
81
92
|
It is using pseudo tty to communicate with the process via simple API.
|
82
93
|
email: jpastuszek@gmail.com
|
@@ -117,7 +128,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
117
128
|
version: '0'
|
118
129
|
segments:
|
119
130
|
- 0
|
120
|
-
hash:
|
131
|
+
hash: -3155130806959499412
|
121
132
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
122
133
|
none: false
|
123
134
|
requirements:
|