guillaumegentil-rspactor 0.2.8 → 0.3.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,119 @@
1
+ require 'rspactor/inspector'
2
+
3
+ describe RSpactor::Inspector do
4
+ before(:all) do
5
+ @inspector = described_class.new('/project')
6
+ end
7
+
8
+ def translate(file)
9
+ @inspector.translate(file)
10
+ end
11
+
12
+ describe "#translate" do
13
+ it "should consider all controllers when application_controller changes" do
14
+ translate('/project/app/controllers/application_controller.rb').should == ['/project/spec/controllers']
15
+ translate('/project/app/controllers/application.rb').should == ['/project/spec/controllers']
16
+ end
17
+
18
+ it "should translate files under 'app/' directory" do
19
+ translate('/project/app/controllers/foo_controller.rb').should ==
20
+ ['/project/spec/controllers/foo_controller_spec.rb']
21
+ end
22
+
23
+ it "should translate templates" do
24
+ translate('/project/app/views/foo/bar.erb').should == ['/project/spec/views/foo/bar.erb_spec.rb']
25
+ translate('/project/app/views/foo/bar.html.haml').should ==
26
+ ['/project/spec/views/foo/bar.html.haml_spec.rb', '/project/spec/views/foo/bar.html_spec.rb']
27
+ end
28
+
29
+ it "should consider all views when application_helper changes" do
30
+ translate('/project/app/helpers/application_helper.rb').should == ['/project/spec/helpers', '/project/spec/views']
31
+ end
32
+
33
+ it "should consider related templates when a helper changes" do
34
+ translate('/project/app/helpers/foo_helper.rb').should ==
35
+ ['/project/spec/helpers/foo_helper_spec.rb', '/project/spec/views/foo']
36
+ end
37
+
38
+ it "should translate files under deep 'lib/' directory" do
39
+ translate('/project/lib/awesum/rox.rb').should ==
40
+ ['/project/spec/lib/awesum/rox_spec.rb', '/project/spec/awesum/rox_spec.rb', '/project/spec/rox_spec.rb']
41
+ end
42
+
43
+ it "should translate files under shallow 'lib/' directory" do
44
+ translate('lib/runner.rb').should == ['/project/spec/lib/runner_spec.rb', '/project/spec/runner_spec.rb']
45
+ end
46
+
47
+ it "should handle relative paths" do
48
+ translate('foo.rb').should == ['/project/spec/foo_spec.rb']
49
+ end
50
+
51
+ it "should handle files without extension" do
52
+ translate('foo').should == ['/project/spec/foo_spec.rb']
53
+ end
54
+
55
+ it "should consider all controllers, helpers and views when routes.rb changes" do
56
+ translate('config/routes.rb').should == ['/project/spec/controllers', '/project/spec/helpers', '/project/spec/views']
57
+ end
58
+
59
+ it "should consider all models when config/database.yml changes" do
60
+ translate('config/database.yml').should == ['/project/spec/models']
61
+ end
62
+
63
+ it "should consider all models when db/schema.rb changes" do
64
+ translate('db/schema.rb').should == ['/project/spec/models']
65
+ end
66
+
67
+ it "should consider related model when its observer changes" do
68
+ translate('app/models/user_observer.rb').should == ['/project/spec/models/user_observer_spec.rb', '/project/spec/models/user_spec.rb']
69
+ end
70
+
71
+ it "should consider all specs when spec_helper changes" do
72
+ translate('spec/spec_helper.rb').should == ['/project/spec']
73
+ end
74
+
75
+ it "should consider all specs when code under spec/shared/ changes" do
76
+ translate('spec/shared/foo.rb').should == ['/project/spec']
77
+ end
78
+
79
+ it "should consider all specs when app configuration changes" do
80
+ translate('config/environment.rb').should == ['/project/spec']
81
+ translate('config/environments/test.rb').should == ['/project/spec']
82
+ translate('config/boot.rb').should == ['/project/spec']
83
+ end
84
+ end
85
+
86
+ describe "#determine_spec_files" do
87
+ def determine(file)
88
+ @inspector.determine_spec_files(file)
89
+ end
90
+
91
+ it "should filter out files that don't exist on the filesystem" do
92
+ @inspector.should_receive(:translate).with('foo').and_return(%w(valid_spec.rb invalid_spec.rb))
93
+ File.should_receive(:exists?).with('valid_spec.rb').and_return(true)
94
+ File.should_receive(:exists?).with('invalid_spec.rb').and_return(false)
95
+ determine('foo').should == ['valid_spec.rb']
96
+ end
97
+
98
+ it "should filter out files in subdirectories that are already on the list" do
99
+ @inspector.should_receive(:translate).with('foo').and_return(%w(
100
+ spec/foo_spec.rb
101
+ spec/views/moo/bar_spec.rb
102
+ spec/views/baa/boo_spec.rb
103
+ spec/models/baz_spec.rb
104
+ spec/controllers/moo_spec.rb
105
+ spec/models
106
+ spec/controllers
107
+ spec/views/baa
108
+ ))
109
+ File.stub!(:exists?).and_return(true)
110
+ determine('foo').should == %w(
111
+ spec/foo_spec.rb
112
+ spec/views/moo/bar_spec.rb
113
+ spec/models
114
+ spec/controllers
115
+ spec/views/baa
116
+ )
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,39 @@
1
+ require 'rspactor/listener'
2
+
3
+ describe RSpactor::Listener do
4
+ before(:all) do
5
+ @listener = described_class.new(%w(rb erb haml))
6
+ end
7
+
8
+ it "should be timestamped" do
9
+ @listener.last_check.should be_instance_of(Time)
10
+ end
11
+
12
+ it "should not ignore regular directories" do
13
+ @listener.ignore_path?('/project/foo/bar').should_not be
14
+ end
15
+
16
+ it "should ignore .git directories" do
17
+ @listener.ignore_path?('/project/.git/index').should be
18
+ end
19
+
20
+ it "should ignore dotfiles" do
21
+ @listener.ignore_file?('/project/.foo').should be
22
+ end
23
+
24
+ it "should not ignore files in directories which start with a dot" do
25
+ @listener.ignore_file?('/project/.foo/bar.rb').should be_false
26
+ end
27
+
28
+ it "should not ignore files without extension" do
29
+ @listener.ignore_file?('/project/foo.rb').should be_false
30
+ end
31
+
32
+ it "should ignore files without extension" do
33
+ @listener.ignore_file?('/project/foo').should be
34
+ end
35
+
36
+ it "should ignore files with extensions that don't match those specified" do
37
+ @listener.ignore_file?('/project/foo.bar').should be
38
+ end
39
+ end
@@ -0,0 +1,258 @@
1
+ require 'rspactor/runner'
2
+
3
+ describe RSpactor::Runner do
4
+
5
+ described_class.class_eval do
6
+ def run_command(cmd)
7
+ # never shell out in tests
8
+ cmd
9
+ end
10
+ end
11
+
12
+ def with_env(name, value)
13
+ old_value = ENV[name]
14
+ ENV[name] = value
15
+ begin
16
+ yield
17
+ ensure
18
+ ENV[name] = old_value
19
+ end
20
+ end
21
+
22
+ def capture_stderr(io = StringIO.new)
23
+ @old_stderr, $stderr = $stderr, io
24
+ begin; yield ensure; restore_stderr; end if block_given?
25
+ end
26
+
27
+ def restore_stderr
28
+ $stderr = @old_stderr
29
+ end
30
+
31
+ def capture_stdout(io = StringIO.new)
32
+ @old_stdout, $stdout = $stdout, io
33
+ begin; yield ensure; restore_stdout; end if block_given?
34
+ end
35
+
36
+ def restore_stdout
37
+ $stdout = @old_stdout
38
+ end
39
+
40
+ it 'should use the current directory to run in' do
41
+ mock_instance = mock('RunnerInstance')
42
+ mock_instance.stub!(:start)
43
+ RSpactor::Runner.should_receive(:new).with(Dir.pwd, {}).and_return(mock_instance)
44
+ RSpactor::Runner.start
45
+ end
46
+
47
+ it 'should take an optional directory to run in' do
48
+ mock_instance = mock('RunnerInstance')
49
+ mock_instance.stub!(:start)
50
+ RSpactor::Runner.should_receive(:new).with('/tmp/mu', {}).and_return(mock_instance)
51
+ RSpactor::Runner.start(:run_in => '/tmp/mu')
52
+ end
53
+
54
+ describe "start" do
55
+ before(:each) do
56
+ @runner = described_class.new('/my/path')
57
+ capture_stdout
58
+ end
59
+
60
+ after(:each) do
61
+ restore_stdout
62
+ end
63
+
64
+ def setup
65
+ @runner.start
66
+ end
67
+
68
+ context "Interactor" do
69
+ before(:each) do
70
+ @runner.stub!(:load_dotfile)
71
+ @runner.stub!(:start_listener)
72
+ @interactor = mock('Interactor')
73
+ @interactor.should_receive(:start_termination_handler)
74
+ RSpactor::Interactor.should_receive(:new).and_return(@interactor)
75
+ end
76
+
77
+ it "should start Interactor" do
78
+ @interactor.should_receive(:wait_for_enter_key).with(instance_of(String), 3)
79
+ setup
80
+ end
81
+
82
+ it "should run all specs if Interactor isn't interrupted" do
83
+ @interactor.should_receive(:wait_for_enter_key).and_return(nil)
84
+ @runner.should_receive(:run_spec_command).with('/my/path/spec')
85
+ setup
86
+ end
87
+
88
+ it "should skip running all specs if Interactor is interrupted" do
89
+ @interactor.should_receive(:wait_for_enter_key).and_return(true)
90
+ @runner.should_not_receive(:run_spec_command)
91
+ setup
92
+ end
93
+ end
94
+
95
+ it "should initialize Inspector" do
96
+ @runner.stub!(:load_dotfile)
97
+ @runner.stub!(:start_interactor)
98
+ RSpactor::Inspector.should_receive(:new).with('/my/path')
99
+ RSpactor::Listener.stub!(:new).and_return(mock('Listener').as_null_object)
100
+ setup
101
+ end
102
+
103
+ context "Listener" do
104
+ before(:each) do
105
+ @runner.stub!(:load_dotfile)
106
+ @runner.stub!(:start_interactor)
107
+ @inspector = mock("Inspector")
108
+ RSpactor::Inspector.stub!(:new).and_return(@inspector)
109
+ @listener = mock('Listener')
110
+ end
111
+
112
+ it "should run Listener" do
113
+ @listener.should_receive(:run).with('/my/path')
114
+ RSpactor::Listener.should_receive(:new).with(instance_of(Array)).and_return(@listener)
115
+ setup
116
+ end
117
+ end
118
+
119
+ it "should output 'watching' message on start" do
120
+ @runner.stub!(:load_dotfile)
121
+ @runner.stub!(:start_interactor)
122
+ @runner.stub!(:start_listener)
123
+ setup
124
+ $stdout.string.chomp.should == "** RSpactor is now watching at '/my/path'"
125
+ end
126
+
127
+ context "dotfile" do
128
+ before(:each) do
129
+ @runner.stub!(:start_interactor)
130
+ @runner.stub!(:start_listener)
131
+ end
132
+
133
+ it "should load dotfile if found" do
134
+ with_env('HOME', '/home/moo') do
135
+ File.should_receive(:exists?).with('/home/moo/.rspactor').and_return(true)
136
+ Kernel.should_receive(:load).with('/home/moo/.rspactor')
137
+ setup
138
+ end
139
+ end
140
+
141
+ it "should continue even if the dotfile raised errors" do
142
+ with_env('HOME', '/home/moo') do
143
+ File.should_receive(:exists?).and_return(true)
144
+ Kernel.should_receive(:load).with('/home/moo/.rspactor').and_raise(ArgumentError)
145
+ capture_stderr do
146
+ lambda { setup }.should_not raise_error
147
+ $stderr.string.split("\n").should include('Error while loading /home/moo/.rspactor: ArgumentError')
148
+ end
149
+ end
150
+ end
151
+ end
152
+ end
153
+
154
+ describe "#run_spec_command" do
155
+ before(:each) do
156
+ @runner = described_class.new('/my/path')
157
+ end
158
+
159
+ def with_rubyopt(string, &block)
160
+ with_env('RUBYOPT', string, &block)
161
+ end
162
+
163
+ def run(paths)
164
+ @runner.run_spec_command(paths)
165
+ end
166
+
167
+ it "should exit if the paths argument is empty" do
168
+ @runner.should_not_receive(:run_command)
169
+ run([])
170
+ end
171
+
172
+ it "should specify runner spec runner with joined paths" do
173
+ run(%w(foo bar)).should include(' spec foo bar ')
174
+ end
175
+
176
+ it "should specify default options: --color" do
177
+ run('foo').should include(' --color')
178
+ end
179
+
180
+ it "should setup RUBYOPT environment variable" do
181
+ with_rubyopt(nil) do
182
+ run('foo').should include("RUBYOPT='-Ilib:spec' ")
183
+ end
184
+ end
185
+
186
+ it "should concat existing RUBYOPTs" do
187
+ with_rubyopt('-rubygems -w') do
188
+ run('foo').should include("RUBYOPT='-Ilib:spec -rubygems -w' ")
189
+ end
190
+ end
191
+
192
+ it "should include growl formatter" do
193
+ run('foo').should include(' -f RSpecGrowler:STDOUT')
194
+ end
195
+
196
+ it "should include 'progress' formatter" do
197
+ run('foo').should include(' -f progress')
198
+ end
199
+
200
+ it "should not include 'progress' formatter if there already are 2 or more formatters" do
201
+ @runner.should_receive(:formatter_opts).and_return('-f foo --format bar')
202
+ run('foo').should_not include('-f progress')
203
+ end
204
+
205
+ it "should save status of last run" do
206
+ @runner.should_receive(:run_command).twice.and_return(true, false)
207
+ run('foo')
208
+ @runner.last_run_failed?.should be_false
209
+ run('bar')
210
+ @runner.last_run_failed?.should be_true
211
+ run([])
212
+ @runner.last_run_failed?.should be_false
213
+ end
214
+ end
215
+
216
+ describe "#spec_changed_files" do
217
+ before(:each) do
218
+ @runner = described_class.new('.')
219
+ @runner.stub!(:inspector).and_return(mock("Inspector"))
220
+ end
221
+
222
+ def set_inspector_expectation(file, ret)
223
+ @runner.inspector.should_receive(:determine_spec_files).with(file).and_return(ret)
224
+ end
225
+
226
+ it "should find and run spec files" do
227
+ set_inspector_expectation('moo.rb', ['spec/moo_spec.rb'])
228
+ set_inspector_expectation('views/baz.haml', [])
229
+ set_inspector_expectation('config/bar.yml', ['spec/bar_spec.rb', 'spec/bar_stuff_spec.rb'])
230
+
231
+ expected = %w(spec/moo_spec.rb spec/bar_spec.rb spec/bar_stuff_spec.rb)
232
+ @runner.should_receive(:run_spec_command).with(expected)
233
+
234
+ capture_stdout do
235
+ @runner.send(:spec_changed_files, %w(moo.rb views/baz.haml config/bar.yml))
236
+ $stdout.string.split("\n").should == expected
237
+ end
238
+ end
239
+
240
+ it "should run the full suite after a run succeded when the previous one failed" do
241
+ @runner.inspector.stub!(:determine_spec_files).and_return(['spec/foo_spec.rb'], ['spec/bar_spec.rb'])
242
+ @runner.stub!(:options).and_return({ :retry_failed => true })
243
+
244
+ capture_stdout do
245
+ @runner.stub!(:run_spec_command)
246
+ @runner.should_receive(:last_run_failed?).and_return(true, false)
247
+ @runner.should_receive(:run_all_specs)
248
+ @runner.send(:spec_changed_files, %w(moo.rb))
249
+ end
250
+ end
251
+ end
252
+
253
+ it "should have Runner in global namespace for backwards compatibility" do
254
+ defined?(::Runner).should be_true
255
+ ::Runner.should == described_class
256
+ end
257
+
258
+ end
metadata CHANGED
@@ -1,60 +1,54 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: guillaumegentil-rspactor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.8
4
+ version: 0.3.4
5
5
  platform: ruby
6
6
  authors:
7
+ - "Mislav Marohni\xC4\x87"
7
8
  - Andreas Wolff
9
+ - Pelle Braendgaard
10
+ - Thibaud Guillaume-Gentil
8
11
  autorequire:
9
12
  bindir: bin
10
13
  cert_chain: []
11
14
 
12
- date: 2009-04-20 00:00:00 -07:00
13
- default_executable: rspactor
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
16
- name: optiflag
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
20
- requirements:
21
- - - ">="
22
- - !ruby/object:Gem::Version
23
- version: "0"
24
- version:
25
- description: RSpactor is a little command line tool to automatically run your changed specs (much like autotest).
26
- email: treas@dynamicdudes.com
15
+ date: 2009-07-20 00:00:00 -07:00
16
+ default_executable:
17
+ dependencies: []
18
+
19
+ description:
20
+ email: mislav.marohnic@gmail.com
27
21
  executables:
28
22
  - rspactor
23
+ - rspactor-system
29
24
  extensions: []
30
25
 
31
- extra_rdoc_files:
32
- - bin/rspactor
33
- - lib/inspector.rb
34
- - lib/interactor.rb
35
- - lib/listener.rb
36
- - lib/resulting.rb
37
- - lib/runner.rb
26
+ extra_rdoc_files: []
27
+
38
28
  files:
39
- - asset/rails_fail.png
40
- - asset/rails_ok.png
41
- - bin/rspactor
42
- - lib/inspector.rb
43
- - lib/interactor.rb
44
- - lib/listener.rb
45
- - lib/resulting.rb
46
- - lib/runner.rb
47
29
  - Rakefile
48
- - Manifest
49
- - rspactor.gemspec
50
- has_rdoc: true
51
- homepage: http://github.com/guillaumegentil/rspactor/
30
+ - bin/rspactor
31
+ - bin/rspactor-system
32
+ - lib/rspactor
33
+ - lib/rspactor/growl.rb
34
+ - lib/rspactor/inspector.rb
35
+ - lib/rspactor/interactor.rb
36
+ - lib/rspactor/listener.rb
37
+ - lib/rspactor/runner.rb
38
+ - lib/rspactor.rb
39
+ - lib/rspec_growler.rb
40
+ - images/failed.png
41
+ - images/pending.png
42
+ - images/success.png
43
+ - spec/inspector_spec.rb
44
+ - spec/listener_spec.rb
45
+ - spec/runner_spec.rb
46
+ - LICENSE
47
+ has_rdoc: false
48
+ homepage: http://github.com/mislav/rspactor
52
49
  post_install_message:
53
- rdoc_options:
54
- - --line-numbers
55
- - --inline-source
56
- - --title
57
- - Rspactor
50
+ rdoc_options: []
51
+
58
52
  require_paths:
59
53
  - lib
60
54
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -67,14 +61,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
67
61
  requirements:
68
62
  - - ">="
69
63
  - !ruby/object:Gem::Version
70
- version: "1.2"
64
+ version: "0"
71
65
  version:
72
66
  requirements: []
73
67
 
74
- rubyforge_project: rspactor
68
+ rubyforge_project:
75
69
  rubygems_version: 1.2.0
76
70
  signing_key:
77
71
  specification_version: 3
78
- summary: RSpactor is a little command line tool to automatically run your changed specs (much like autotest).
72
+ summary: RSpactor is a command line tool to automatically run your changed specs (much like autotest).
79
73
  test_files: []
80
74
 
data/Manifest DELETED
@@ -1,10 +0,0 @@
1
- asset/rails_fail.png
2
- asset/rails_ok.png
3
- bin/rspactor
4
- lib/inspector.rb
5
- lib/interactor.rb
6
- lib/listener.rb
7
- lib/resulting.rb
8
- lib/runner.rb
9
- Rakefile
10
- Manifest
data/lib/inspector.rb DELETED
@@ -1,92 +0,0 @@
1
- # The inspector make some assumptions about how your project is structured and where your spec files are located.
2
- # That said: The 'spec' directory, containing all your test files, must rest in the root directory of your project.
3
- # Futhermore it tries to locate controller, model, helper and view specs for a rails app (or projects with an identical structure)
4
- # in root/spec/controllers, root/spec/models, root/spec/helpers and root/spec/views.
5
-
6
- class Inspector
7
-
8
- attr_accessor :base_spec_root
9
-
10
- def self.file_is_invalid?(file)
11
- return true unless File.basename(file) =~ /.rb\z|.rhtml\z|.erb\z|.haml\z/
12
- false
13
- end
14
-
15
- def find_spec_file(file)
16
- begin
17
- return file if file_is_a_spec?(file)
18
- spec_root = find_base_spec_root_by_file(file)
19
- if spec_root
20
- guessed_spec_location = guess_spec_location(file, spec_root)
21
- if File.exist?(guessed_spec_location)
22
- @base_spec_root = spec_root
23
- return guessed_spec_location
24
- end
25
- end
26
- nil
27
- rescue => e
28
- puts "Error while parsing a file: '#{file}'"
29
- puts e
30
- end
31
- end
32
-
33
- def inner_spec_directory(path)
34
- spec_base_root = find_base_spec_root_by_file(Dir.pwd + "/.")
35
- inner_location = extract_inner_project_location(Dir.pwd, spec_base_root)
36
- File.join(spec_base_root, inner_location)
37
- end
38
-
39
- def find_base_spec_root_by_file(file)
40
- if @base_spec_root
41
- return @base_spec_root
42
- else
43
- dir_parts = File.dirname(file).split("/")
44
- dir_parts.size.times do |i|
45
- search_dir = dir_parts[0..dir_parts.length - i - 1].join("/") + "/"
46
- if Dir.entries(search_dir).include?('spec')
47
- @assumed_spec_root = search_dir + "spec"
48
- break
49
- end
50
- end
51
- return @assumed_spec_root
52
- end
53
- end
54
-
55
- def guess_spec_location(file, spec_root)
56
- inner_location = extract_inner_project_location(file, spec_root)
57
- append_spec_file_extension(File.join(spec_root, inner_location))
58
- end
59
-
60
- def project_root(spec_root)
61
- spec_root.split("/")[0...-1].join("/")
62
- end
63
-
64
- def extract_inner_project_location(file, spec_root)
65
- location = file.sub(project_root(spec_root), "")
66
- adapt_rails_specific_app_structure(location)
67
- end
68
-
69
- def adapt_rails_specific_app_structure(location)
70
- # Removing 'app' if its a rails controller, model, helper or view
71
- fu = location.split("/")
72
- if fu[1] == "app" && (fu[2] == 'controllers' || fu[2] == 'routing' || fu[2] == 'helpers' || fu[2] == 'models' || fu[2] == 'views')
73
- return "/" + fu[2..fu.length].join("/")
74
- end
75
- location
76
- end
77
-
78
- def append_spec_file_extension(spec_file)
79
- if File.extname(spec_file) == ".rb"
80
- return File.join(File.dirname(spec_file), File.basename(spec_file, ".rb")) + "_spec.rb"
81
- else
82
- return spec_file + "_spec.rb"
83
- end
84
- end
85
-
86
- def file_is_a_spec?(file)
87
- if file.split("/").include?('spec') && File.basename(file).match(/_spec.rb\z/)
88
- return true
89
- end
90
- false
91
- end
92
- end
data/lib/interactor.rb DELETED
@@ -1,65 +0,0 @@
1
- require 'timeout'
2
-
3
- class Interactor
4
-
5
- def initialize(options = {})
6
- @options = options
7
- ticker
8
- end
9
-
10
- def wait_for_enter_key(msg, seconds_to_wait, clear = false)
11
- begin
12
- Timeout::timeout(seconds_to_wait) do
13
- system("clear;") if clear
14
- ticker(:start => true, :msg => msg)
15
- $stdin.gets
16
- return true
17
- end
18
- rescue Timeout::Error
19
- false
20
- ensure
21
- ticker(:stop => true)
22
- end
23
- end
24
-
25
- def start_termination_handler
26
- @main_thread = Thread.current
27
- Thread.new do
28
- loop do
29
- sleep 0.5
30
- if $stdin.gets
31
- if wait_for_enter_key("** Running all specs.. Hit <enter> again to exit RSpactor", 3, @options[:clear])
32
- @main_thread.exit
33
- exit
34
- end
35
- Runner.run_all_specs
36
- end
37
- end
38
- end
39
- end
40
-
41
-
42
- private
43
-
44
- def ticker(opts = {})
45
- if opts[:stop]
46
- $stdout.puts "\n"
47
- @pointer_running = false
48
- elsif opts[:start]
49
- @pointer_running = true
50
- write(opts[:msg]) if opts[:msg]
51
- else
52
- Thread.new do
53
- loop do
54
- write('.') if @pointer_running == true
55
- sleep 1.0
56
- end
57
- end
58
- end
59
- end
60
-
61
- def write(msg)
62
- $stdout.print(msg)
63
- $stdout.flush
64
- end
65
- end