spinning_cursor 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +16 -1
- data/Gemfile +3 -3
- data/Gemfile.lock +60 -15
- data/README.md +14 -3
- data/TODO +2 -1
- data/VERSION +1 -1
- data/lib/spinning_cursor.rb +45 -63
- data/lib/spinning_cursor/console_helpers.rb +88 -0
- data/lib/spinning_cursor/cursor.rb +30 -46
- data/lib/spinning_cursor/parser.rb +29 -22
- data/lib/spinning_cursor/stop_watch.rb +78 -0
- data/spinning_cursor.gemspec +13 -11
- data/test/helper.rb +17 -2
- data/test/test_cursors.rb +61 -21
- data/test/test_exceptions.rb +0 -6
- data/test/test_parser.rb +56 -12
- data/test/test_spinning_cursor.rb +74 -9
- metadata +13 -11
data/CHANGELOG
CHANGED
@@ -1,6 +1,21 @@
|
|
1
1
|
CHANGELOG
|
2
2
|
===============================================================================
|
3
3
|
|
4
|
+
v0.2.0 (2013-07-13)
|
5
|
+
- Several bug fixes/internal API improvements (#4 #8 #9 #10 #11 #13)
|
6
|
+
- Suppress output from action block (#7)
|
7
|
+
- Add `output` option to display inline or all at once at the end (#13)
|
8
|
+
- Add `delay` option to specify cursor speed (#2)
|
9
|
+
- Hide terminal cursor during cursor animation (#11)
|
10
|
+
- Better exception handling (#13)
|
11
|
+
|
12
|
+
|
13
|
+
v0.1.1 - v0.1.2 (2012-04-25)
|
14
|
+
- Task timing is more concentrated (times, yields, works out the difference)
|
15
|
+
- Trying to set the message/banner after a task has finished raises an
|
16
|
+
exception
|
17
|
+
- Exceptions are showing now (promise this time D;)
|
18
|
+
|
4
19
|
v0.1.0 (2012-04-10)
|
5
20
|
- First non-pre release
|
6
21
|
- Exceptions in the task cause the cursor to stop and the exception is shown
|
@@ -15,4 +30,4 @@ v0.1.0.rc1 (2012-04-09)
|
|
15
30
|
- Set the loading message, type of spinner and finished message
|
16
31
|
- Pass in an action block to do the whole start stop loop, or don't and
|
17
32
|
call stop yourself
|
18
|
-
- Change the finish message within your task block
|
33
|
+
- Change the finish message within your task block
|
data/Gemfile
CHANGED
@@ -7,9 +7,9 @@ source "http://rubygems.org"
|
|
7
7
|
# Include everything needed to run rake, tests, features, etc.
|
8
8
|
group :development do
|
9
9
|
gem "shoulda", ">= 0"
|
10
|
-
gem "bundler", "~> 1.
|
11
|
-
gem "jeweler", "~> 1.8.
|
12
|
-
gem "yard"
|
10
|
+
gem "bundler", "~> 1.3.5"
|
11
|
+
gem "jeweler", "~> 1.8.4"
|
12
|
+
gem "yard", "~> 0.8.6.2"
|
13
13
|
gem "redcarpet"
|
14
14
|
gem "github-markup"
|
15
15
|
end
|
data/Gemfile.lock
CHANGED
@@ -1,32 +1,77 @@
|
|
1
1
|
GEM
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
|
+
activesupport (4.0.0)
|
5
|
+
i18n (~> 0.6, >= 0.6.4)
|
6
|
+
minitest (~> 4.2)
|
7
|
+
multi_json (~> 1.3)
|
8
|
+
thread_safe (~> 0.1)
|
9
|
+
tzinfo (~> 0.3.37)
|
10
|
+
addressable (2.3.5)
|
11
|
+
atomic (1.1.10)
|
12
|
+
builder (3.2.2)
|
13
|
+
faraday (0.8.7)
|
14
|
+
multipart-post (~> 1.1)
|
4
15
|
git (1.2.5)
|
5
|
-
github-markup (0.7.
|
6
|
-
|
16
|
+
github-markup (0.7.5)
|
17
|
+
github_api (0.10.1)
|
18
|
+
addressable
|
19
|
+
faraday (~> 0.8.1)
|
20
|
+
hashie (>= 1.2)
|
21
|
+
multi_json (~> 1.4)
|
22
|
+
nokogiri (~> 1.5.2)
|
23
|
+
oauth2
|
24
|
+
hashie (2.0.5)
|
25
|
+
highline (1.6.19)
|
26
|
+
httpauth (0.2.0)
|
27
|
+
i18n (0.6.4)
|
28
|
+
jeweler (1.8.6)
|
29
|
+
builder
|
7
30
|
bundler (~> 1.0)
|
8
31
|
git (>= 1.2.5)
|
32
|
+
github_api (= 0.10.1)
|
33
|
+
highline (>= 1.6.15)
|
34
|
+
nokogiri (= 1.5.10)
|
9
35
|
rake
|
10
36
|
rdoc
|
11
|
-
json (1.
|
12
|
-
|
13
|
-
|
37
|
+
json (1.8.0)
|
38
|
+
jwt (0.1.8)
|
39
|
+
multi_json (>= 1.5)
|
40
|
+
minitest (4.7.5)
|
41
|
+
multi_json (1.7.7)
|
42
|
+
multi_xml (0.5.4)
|
43
|
+
multipart-post (1.2.0)
|
44
|
+
nokogiri (1.5.10)
|
45
|
+
oauth2 (0.9.2)
|
46
|
+
faraday (~> 0.8)
|
47
|
+
httpauth (~> 0.2)
|
48
|
+
jwt (~> 0.1.4)
|
49
|
+
multi_json (~> 1.0)
|
50
|
+
multi_xml (~> 0.5)
|
51
|
+
rack (~> 1.2)
|
52
|
+
rack (1.5.2)
|
53
|
+
rake (10.1.0)
|
54
|
+
rdoc (4.0.1)
|
14
55
|
json (~> 1.4)
|
15
|
-
redcarpet (
|
16
|
-
shoulda (3.0
|
17
|
-
shoulda-context (~> 1.0.0)
|
18
|
-
shoulda-matchers (
|
19
|
-
shoulda-context (1.
|
20
|
-
shoulda-matchers (
|
21
|
-
|
56
|
+
redcarpet (3.0.0)
|
57
|
+
shoulda (3.5.0)
|
58
|
+
shoulda-context (~> 1.0, >= 1.0.1)
|
59
|
+
shoulda-matchers (>= 1.4.1, < 3.0)
|
60
|
+
shoulda-context (1.1.4)
|
61
|
+
shoulda-matchers (2.2.0)
|
62
|
+
activesupport (>= 3.0.0)
|
63
|
+
thread_safe (0.1.0)
|
64
|
+
atomic
|
65
|
+
tzinfo (0.3.37)
|
66
|
+
yard (0.8.6.2)
|
22
67
|
|
23
68
|
PLATFORMS
|
24
69
|
ruby
|
25
70
|
|
26
71
|
DEPENDENCIES
|
27
|
-
bundler (~> 1.
|
72
|
+
bundler (~> 1.3.5)
|
28
73
|
github-markup
|
29
|
-
jeweler (~> 1.8.
|
74
|
+
jeweler (~> 1.8.4)
|
30
75
|
redcarpet
|
31
76
|
shoulda
|
32
|
-
yard
|
77
|
+
yard (~> 0.8.6.2)
|
data/README.md
CHANGED
@@ -56,6 +56,11 @@ It's as easy as that!
|
|
56
56
|
* `action` - The stuff you want to do whilst the cursor is spinning.
|
57
57
|
* `message` - The message you want to show the user once the task is finished.
|
58
58
|
Defaults to "Done".
|
59
|
+
* `delay` - Sets the delay in seconds between the frames of the animation.
|
60
|
+
Defaults depend on type of cursor animation (spinner 0.5s, dots 1s)
|
61
|
+
* `output` - Sets how to display program output during cursor animation
|
62
|
+
(`:inline` or `:at_stop`).
|
63
|
+
Defaults to `:inline`.
|
59
64
|
|
60
65
|
### But the action block would get too messy!
|
61
66
|
|
@@ -82,7 +87,7 @@ SpinningCursor.stop
|
|
82
87
|
```
|
83
88
|
|
84
89
|
**Notice** the absence of the `action` option. The start method will only keep
|
85
|
-
the cursor running if an `action` block isn't passed
|
90
|
+
the cursor running if an `action` block isn't passed to it.
|
86
91
|
|
87
92
|
### I want to be able to change the finish message conditionally!
|
88
93
|
|
@@ -147,7 +152,7 @@ The hash contains the following, self-explanatory keys:
|
|
147
152
|
#### Suggestions
|
148
153
|
|
149
154
|
There isn't much this library should do, but a good suggestion is always
|
150
|
-
welcome. Make sure to use the issue
|
155
|
+
welcome. Make sure to use the issue tracker on GitHub to make suggestions -- and
|
151
156
|
fork & pull request if you want to implement it yourself, of course.
|
152
157
|
|
153
158
|
#### More Cursors!
|
@@ -166,7 +171,7 @@ indebted to you. It's a learning experience for me!
|
|
166
171
|
|
167
172
|
* Check out the latest master to make sure the feature hasn't been implemented
|
168
173
|
or the bug hasn't been fixed yet.
|
169
|
-
* Check out the issue tracker to make sure someone
|
174
|
+
* Check out the issue tracker to make sure someone hasn't already requested it
|
170
175
|
and/or contributed it.
|
171
176
|
* Fork the project.
|
172
177
|
* Start a feature/bugfix branch.
|
@@ -177,3 +182,9 @@ indebted to you. It's a learning experience for me!
|
|
177
182
|
to have your own version, or is otherwise necessary, that is fine, but
|
178
183
|
please isolate to its own commit so I can cherry-pick around it.
|
179
184
|
|
185
|
+
### List of contributors
|
186
|
+
|
187
|
+
A massive thanks to those who have taken some time out to help improve
|
188
|
+
Spinning Cursor!
|
189
|
+
|
190
|
+
* Abinoam P. Marques Jr. (@abinoam)
|
data/TODO
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
Suppress output and show later?
|
1
|
+
Suppress output and show later? (give option to produce log file, or just print it to the screen after it's finished),
|
2
|
+
default to hide though.
|
2
3
|
deal with returns?
|
3
4
|
test changes to spinning cursor, check diff for changes
|
4
5
|
refactor tests to use minitest
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/lib/spinning_cursor.rb
CHANGED
@@ -1,8 +1,12 @@
|
|
1
|
+
require "spinning_cursor/console_helpers"
|
1
2
|
require "spinning_cursor/cursor"
|
2
3
|
require "spinning_cursor/parser"
|
4
|
+
require "spinning_cursor/stop_watch"
|
3
5
|
|
4
6
|
module SpinningCursor
|
5
7
|
extend self
|
8
|
+
include self::ConsoleHelpers
|
9
|
+
extend self::ConsoleHelpers
|
6
10
|
|
7
11
|
#
|
8
12
|
# Sends passed block to Parser, and starts cursor thread
|
@@ -10,30 +14,36 @@ module SpinningCursor
|
|
10
14
|
# thread if an action block is passed.
|
11
15
|
#
|
12
16
|
def start(&block)
|
13
|
-
if
|
14
|
-
if @curs.alive?
|
15
|
-
stop
|
16
|
-
end
|
17
|
-
end
|
17
|
+
stop if alive?
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
save_stdout_sync_status
|
20
|
+
capture_console
|
21
|
+
hide_cursor
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
@parsed = Parser.new(&block)
|
24
|
+
@cursor = Cursor.new(@parsed)
|
25
|
+
@spinner = Thread.new do
|
26
|
+
abort_on_exception = true
|
27
|
+
@cursor.spin
|
27
28
|
end
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
29
|
+
|
30
|
+
@stop_watch = StopWatch.new
|
31
|
+
|
32
|
+
if @parsed.action
|
33
|
+
# The action
|
34
|
+
begin
|
35
|
+
@stop_watch.measure do
|
36
|
+
@parsed.outer_scope_object.instance_eval &@parsed.action
|
37
|
+
end
|
38
|
+
rescue StandardError => e
|
39
|
+
set_message "#{e.message}\n#{e.backtrace.join("\n")}"
|
40
|
+
raise
|
41
|
+
ensure
|
42
|
+
stop
|
32
43
|
end
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
return stop
|
44
|
+
else
|
45
|
+
# record start time
|
46
|
+
@stop_watch.start
|
37
47
|
end
|
38
48
|
end
|
39
49
|
|
@@ -43,20 +53,28 @@ module SpinningCursor
|
|
43
53
|
#
|
44
54
|
def stop
|
45
55
|
begin
|
46
|
-
|
56
|
+
restore_stdout_sync_status
|
57
|
+
if console_captured?
|
58
|
+
$console.print ESC_R_AND_CLR + $stdout.string
|
59
|
+
release_console
|
60
|
+
end
|
61
|
+
show_cursor
|
62
|
+
|
63
|
+
@spinner.kill
|
47
64
|
# Wait for the cursor to die -- can cause problems otherwise
|
48
|
-
|
65
|
+
@spinner.join
|
49
66
|
# Set cursor to nil so set_banner method only works
|
50
67
|
# when cursor is actually running.
|
51
68
|
@cursor = nil
|
52
69
|
reset_line
|
53
|
-
puts
|
70
|
+
puts @parsed.message
|
54
71
|
# Set parsed to nil so set_message method only works
|
55
72
|
# when cursor is actually running.
|
56
73
|
@parsed = nil
|
57
74
|
|
58
75
|
# Return execution time
|
59
|
-
|
76
|
+
@stop_watch.stop
|
77
|
+
@stop_watch.timing
|
60
78
|
rescue NameError
|
61
79
|
raise CursorNotRunning.new "Can't stop, no cursor running."
|
62
80
|
end
|
@@ -66,11 +84,7 @@ module SpinningCursor
|
|
66
84
|
# Determines whether the cursor thread is still running
|
67
85
|
#
|
68
86
|
def alive?
|
69
|
-
|
70
|
-
return false
|
71
|
-
else
|
72
|
-
@curs.alive?
|
73
|
-
end
|
87
|
+
@spinner and @spinner.alive?
|
74
88
|
end
|
75
89
|
|
76
90
|
#
|
@@ -91,47 +105,15 @@ module SpinningCursor
|
|
91
105
|
#
|
92
106
|
def set_banner(banner)
|
93
107
|
begin
|
94
|
-
@
|
108
|
+
@parsed.banner banner
|
95
109
|
rescue NameError
|
96
110
|
raise CursorNotRunning.new "Cursor isn't running... are you sure " +
|
97
111
|
"you're calling this from an action block?"
|
98
112
|
end
|
99
113
|
end
|
100
114
|
|
101
|
-
#
|
102
|
-
# Retrieves execution time information
|
103
|
-
#
|
104
|
-
def get_exec_time
|
105
|
-
if not @start.nil?
|
106
|
-
if @finish.nil? && @curs.alive? == false
|
107
|
-
do_exec_time
|
108
|
-
end
|
109
|
-
return { :started => @start, :finished => @finish,
|
110
|
-
:elapsed => @elapsed }
|
111
|
-
else
|
112
|
-
raise NoTaskError.new "An execution hasn't started or finished."
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
115
|
private
|
117
116
|
|
118
|
-
#
|
119
|
-
# Takes a block, and returns the start, finish and elapsed times
|
120
|
-
#
|
121
|
-
def do_exec_time
|
122
|
-
if @curs.alive?
|
123
|
-
@start = Time.now
|
124
|
-
if block_given?
|
125
|
-
yield
|
126
|
-
@finish = Time.now
|
127
|
-
@elapsed = @finish - @start
|
128
|
-
end
|
129
|
-
else
|
130
|
-
@finish = Time.now
|
131
|
-
@elapsed = @finish - @start
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
117
|
class NoTaskError < Exception ; end
|
136
118
|
class CursorNotRunning < NoTaskError ; end
|
137
|
-
end
|
119
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
|
3
|
+
$console = STDOUT
|
4
|
+
|
5
|
+
module SpinningCursor
|
6
|
+
module ConsoleHelpers
|
7
|
+
if RUBY_PLATFORM =~ /(win|w)32$/
|
8
|
+
# DOS
|
9
|
+
# Contains a string to clear the line in the shell
|
10
|
+
CLR = " \r"
|
11
|
+
else
|
12
|
+
# Unix
|
13
|
+
# Contains a string to clear the line in the shell
|
14
|
+
CLR = "\e[0K"
|
15
|
+
end
|
16
|
+
|
17
|
+
# ANSI escape sequence for hiding terminal cursor
|
18
|
+
ESC_CURS_INVIS = "\e[?25l"
|
19
|
+
# ANSI escape sequence for showing terminal cursor
|
20
|
+
ESC_CURS_VIS = "\e[?25h"
|
21
|
+
# ANSI escape sequence for clearing line in terminal
|
22
|
+
ESC_R_AND_CLR = "\r#{CLR}"
|
23
|
+
|
24
|
+
#
|
25
|
+
# Manages line reset in the console
|
26
|
+
#
|
27
|
+
def reset_line(text = "")
|
28
|
+
$console.print "#{ESC_R_AND_CLR}#{text}"
|
29
|
+
end
|
30
|
+
|
31
|
+
#
|
32
|
+
# Stores current `STDOUT.sync` value and sets it to true
|
33
|
+
#
|
34
|
+
def save_stdout_sync_status
|
35
|
+
@stdout_sync_saved_status = STDOUT.sync
|
36
|
+
STDOUT.sync = true
|
37
|
+
end
|
38
|
+
|
39
|
+
#
|
40
|
+
# Restores the previously stored `STDOUT.sync` value
|
41
|
+
#
|
42
|
+
def restore_stdout_sync_status
|
43
|
+
STDOUT.sync = @stdout_sync_saved_status
|
44
|
+
end
|
45
|
+
|
46
|
+
#
|
47
|
+
# Sets `$stdout` global variable to a `StringIO` object to buffer output
|
48
|
+
#
|
49
|
+
def capture_console
|
50
|
+
$stdout = StringIO.new
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
# Resets `$stdout` global variable to `STDOUT`
|
55
|
+
#
|
56
|
+
def release_console
|
57
|
+
$stdout = $console
|
58
|
+
end
|
59
|
+
|
60
|
+
#
|
61
|
+
# Returns true if `$stdout` is a `StringIO` object
|
62
|
+
#
|
63
|
+
def console_captured?
|
64
|
+
$stdout.is_a?(StringIO)
|
65
|
+
end
|
66
|
+
|
67
|
+
#
|
68
|
+
# Returns true if the output buffer is currently empty
|
69
|
+
#
|
70
|
+
def captured_console_empty?
|
71
|
+
console_captured? and $stdout.string.empty?
|
72
|
+
end
|
73
|
+
|
74
|
+
#
|
75
|
+
# Hides the terminal cursor
|
76
|
+
#
|
77
|
+
def hide_cursor
|
78
|
+
$console.print ESC_CURS_INVIS
|
79
|
+
end
|
80
|
+
|
81
|
+
#
|
82
|
+
# Shows the terminal cursor
|
83
|
+
#
|
84
|
+
def show_cursor
|
85
|
+
$console.print ESC_CURS_VIS
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -1,43 +1,30 @@
|
|
1
1
|
module SpinningCursor
|
2
|
-
if RUBY_PLATFORM =~ /(win|w)32$/
|
3
|
-
# DOS
|
4
|
-
# Contains a string to clear the line in the shell
|
5
|
-
CLR = " \r"
|
6
|
-
else
|
7
|
-
# Unix
|
8
|
-
# Contains a string to clear the line in the shell
|
9
|
-
CLR = "\e[0K"
|
10
|
-
end
|
11
|
-
|
12
|
-
#
|
13
|
-
# Manages line reset in the console
|
14
|
-
#
|
15
|
-
def reset_line(text = "")
|
16
|
-
print "\r#{CLR}#{text}"
|
17
|
-
end
|
18
|
-
|
19
2
|
#
|
20
3
|
# This class contains the cursor types (and their helper methods)
|
21
4
|
#
|
22
5
|
class Cursor
|
23
|
-
|
6
|
+
include SpinningCursor::ConsoleHelpers
|
24
7
|
|
25
8
|
#
|
26
9
|
# As of v0.1.0: only initializes the cursor class, use the spin
|
27
10
|
# method to start the printing. Takes only the banner argument as
|
28
11
|
# a result of this.
|
29
12
|
#
|
30
|
-
def initialize(
|
31
|
-
@
|
13
|
+
def initialize(parsed)
|
14
|
+
@parsed = parsed
|
32
15
|
end
|
33
16
|
|
34
17
|
#
|
35
|
-
# Takes a cursor type symbol and starts the printing
|
18
|
+
# Takes a cursor type symbol and delay, and starts the printing
|
36
19
|
#
|
37
|
-
def spin
|
20
|
+
def spin
|
38
21
|
$stdout.sync = true
|
39
|
-
print @banner
|
40
|
-
|
22
|
+
$console.print @parsed.banner
|
23
|
+
if @parsed.delay
|
24
|
+
send @parsed.type, @parsed.delay
|
25
|
+
else
|
26
|
+
send @parsed.type
|
27
|
+
end
|
41
28
|
end
|
42
29
|
|
43
30
|
private
|
@@ -45,33 +32,30 @@ module SpinningCursor
|
|
45
32
|
#
|
46
33
|
# Prints three dots and clears the line
|
47
34
|
#
|
48
|
-
def dots
|
49
|
-
|
50
|
-
loop do
|
51
|
-
sleep 1
|
52
|
-
if i % 4 == 0
|
53
|
-
SpinningCursor.reset_line @banner
|
54
|
-
i += 1
|
55
|
-
next
|
56
|
-
end
|
57
|
-
i += 1
|
58
|
-
print "."
|
59
|
-
end
|
35
|
+
def dots(delay = 1)
|
36
|
+
cycle_through ['.', '..', '...', ''], delay
|
60
37
|
end
|
61
38
|
|
62
39
|
#
|
63
40
|
# Cycles through '|', '/', '-', '\', resembling a spinning cursor
|
64
41
|
#
|
65
|
-
def spinner
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
42
|
+
def spinner(delay = 0.5)
|
43
|
+
cycle_through ['|', '/', '-', '\\'], delay
|
44
|
+
end
|
45
|
+
|
46
|
+
def cycle_through(chars, delay)
|
47
|
+
chars.cycle do |char|
|
48
|
+
unless @parsed.output==:at_stop or captured_console_empty?
|
49
|
+
$console.print "#{ESC_R_AND_CLR}"
|
50
|
+
$console.print $stdout.string
|
51
|
+
$console.print "\n" unless $stdout.string[-1,1] == "\n"
|
52
|
+
$stdout.string = "" # TODO: Check for race condition.
|
53
|
+
end
|
54
|
+
$console.print "#{ESC_R_AND_CLR}#{@parsed.banner}"
|
55
|
+
$console.print " " unless @parsed.banner.empty?
|
56
|
+
$console.print "#{char}"
|
57
|
+
sleep delay
|
74
58
|
end
|
75
59
|
end
|
76
60
|
end
|
77
|
-
end
|
61
|
+
end
|
@@ -1,43 +1,50 @@
|
|
1
1
|
module SpinningCursor
|
2
2
|
class Parser
|
3
|
-
|
3
|
+
attr_accessor :outer_scope_object
|
4
4
|
|
5
5
|
#
|
6
6
|
# Parses proc
|
7
7
|
#
|
8
|
-
def initialize(
|
9
|
-
@banner
|
10
|
-
@type
|
8
|
+
def initialize(&block)
|
9
|
+
@banner = "Loading"
|
10
|
+
@type = :spinner
|
11
11
|
@message = "Done"
|
12
|
+
@delay = nil
|
13
|
+
@action = nil
|
14
|
+
@output = :inline
|
12
15
|
|
13
|
-
if
|
14
|
-
|
15
|
-
|
16
|
-
instance_eval &proc
|
16
|
+
if block_given?
|
17
|
+
@outer_scope_object = eval("self", block.binding)
|
18
|
+
instance_eval &block
|
17
19
|
end
|
18
|
-
|
19
|
-
self
|
20
20
|
end
|
21
21
|
|
22
22
|
#
|
23
23
|
# Getter and setter for the action block
|
24
24
|
#
|
25
25
|
def action(&block)
|
26
|
-
@action = block
|
26
|
+
@action = block if block
|
27
27
|
|
28
28
|
@action
|
29
29
|
end
|
30
30
|
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
|
37
|
-
|
31
|
+
# @method banner(banner)
|
32
|
+
# @method type(type)
|
33
|
+
# @method message(message)
|
34
|
+
# @method delay(delay)
|
35
|
+
# @method output(output)
|
36
|
+
# Getters and setters for `banner`, `type`, `message`, `delay` and `output`
|
37
|
+
# attributes
|
38
|
+
# @note For getting, use method without arguments
|
39
|
+
# e.g. `banner`<br />
|
40
|
+
# For setting, use method with arguments
|
41
|
+
# e.g. `banner "my banner"`
|
42
|
+
#
|
43
|
+
%w[banner type message delay output].each do |method|
|
44
|
+
define_method(method) do |*args|
|
38
45
|
var = "@#{method}"
|
39
|
-
return instance_variable_get(var)
|
40
|
-
instance_variable_set(var,
|
46
|
+
return instance_variable_get(var) unless args.first
|
47
|
+
instance_variable_set(var, args.first)
|
41
48
|
end
|
42
49
|
end
|
43
50
|
|
@@ -47,7 +54,7 @@ module SpinningCursor
|
|
47
54
|
# Pass any other methods to the calling class
|
48
55
|
#
|
49
56
|
def method_missing(method, *args, &block)
|
50
|
-
@
|
57
|
+
@outer_scope_object.send method, *args, &block
|
51
58
|
end
|
52
59
|
end
|
53
|
-
end
|
60
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
class StopWatch
|
2
|
+
|
3
|
+
#
|
4
|
+
# Instantiate class and call {#measure}
|
5
|
+
#
|
6
|
+
def self.measure(&block)
|
7
|
+
sw = self.new
|
8
|
+
sw.measure &block
|
9
|
+
end
|
10
|
+
|
11
|
+
#
|
12
|
+
# Measures the time taken to process the passed block and returns the
|
13
|
+
# measurment (see {timing})
|
14
|
+
#
|
15
|
+
def measure(&block)
|
16
|
+
start
|
17
|
+
yield
|
18
|
+
stop
|
19
|
+
timing
|
20
|
+
end
|
21
|
+
|
22
|
+
#
|
23
|
+
# Starts timer
|
24
|
+
#
|
25
|
+
def start
|
26
|
+
@start_time = Time.now
|
27
|
+
@stop_time = nil
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
#
|
32
|
+
# Stops timer
|
33
|
+
#
|
34
|
+
def stop
|
35
|
+
if @start_time
|
36
|
+
@stop_time = Time.now
|
37
|
+
end
|
38
|
+
self
|
39
|
+
end
|
40
|
+
|
41
|
+
#
|
42
|
+
# Resets timer
|
43
|
+
#
|
44
|
+
def reset
|
45
|
+
@start_time = @stop_time = nil
|
46
|
+
end
|
47
|
+
|
48
|
+
#
|
49
|
+
# Returns the elapsed time
|
50
|
+
# @note If the timer has not yet stopped, the time elapsed from the start of
|
51
|
+
# the timer till `Time.now` is returned
|
52
|
+
#
|
53
|
+
def elapsed_time
|
54
|
+
time_now = Time.now
|
55
|
+
(@stop_time || time_now ) - (@start_time || time_now)
|
56
|
+
end
|
57
|
+
|
58
|
+
alias old_inspect inspect
|
59
|
+
|
60
|
+
def inspect
|
61
|
+
puts "#{old_inspect} #{{:elapsed_time => elapsed_time}}"
|
62
|
+
end
|
63
|
+
|
64
|
+
#
|
65
|
+
# Returns the measurement in a hash containing
|
66
|
+
# * the start time
|
67
|
+
# * the stop time
|
68
|
+
# * the total elapsed time
|
69
|
+
#
|
70
|
+
def timing
|
71
|
+
{ :start_time => @start_time,
|
72
|
+
:stop_time => @stop_time,
|
73
|
+
:elapsed_time => elapsed_time }
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
|
data/spinning_cursor.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "spinning_cursor"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Adnan Abdulhussein"]
|
12
|
-
s.date = "
|
12
|
+
s.date = "2013-07-13"
|
13
13
|
s.description = "Spinning Cursor is a flexible DSL that allows you to easily produce a customizable waiting/loading message for your Ruby command line program. Beautifully keep your users informed with what your program is doing when a more complex solution, such as a progress bar, doesn't fit your needs."
|
14
14
|
s.email = "adnan@prydoni.us"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -29,8 +29,10 @@ Gem::Specification.new do |s|
|
|
29
29
|
"TODO",
|
30
30
|
"VERSION",
|
31
31
|
"lib/spinning_cursor.rb",
|
32
|
+
"lib/spinning_cursor/console_helpers.rb",
|
32
33
|
"lib/spinning_cursor/cursor.rb",
|
33
34
|
"lib/spinning_cursor/parser.rb",
|
35
|
+
"lib/spinning_cursor/stop_watch.rb",
|
34
36
|
"spinning_cursor.gemspec",
|
35
37
|
"test/helper.rb",
|
36
38
|
"test/test_cursors.rb",
|
@@ -49,24 +51,24 @@ Gem::Specification.new do |s|
|
|
49
51
|
|
50
52
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
51
53
|
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
52
|
-
s.add_development_dependency(%q<bundler>, ["~> 1.
|
53
|
-
s.add_development_dependency(%q<jeweler>, ["~> 1.8.
|
54
|
-
s.add_development_dependency(%q<yard>, ["
|
54
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.3.5"])
|
55
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
|
56
|
+
s.add_development_dependency(%q<yard>, ["~> 0.8.6.2"])
|
55
57
|
s.add_development_dependency(%q<redcarpet>, [">= 0"])
|
56
58
|
s.add_development_dependency(%q<github-markup>, [">= 0"])
|
57
59
|
else
|
58
60
|
s.add_dependency(%q<shoulda>, [">= 0"])
|
59
|
-
s.add_dependency(%q<bundler>, ["~> 1.
|
60
|
-
s.add_dependency(%q<jeweler>, ["~> 1.8.
|
61
|
-
s.add_dependency(%q<yard>, ["
|
61
|
+
s.add_dependency(%q<bundler>, ["~> 1.3.5"])
|
62
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
|
63
|
+
s.add_dependency(%q<yard>, ["~> 0.8.6.2"])
|
62
64
|
s.add_dependency(%q<redcarpet>, [">= 0"])
|
63
65
|
s.add_dependency(%q<github-markup>, [">= 0"])
|
64
66
|
end
|
65
67
|
else
|
66
68
|
s.add_dependency(%q<shoulda>, [">= 0"])
|
67
|
-
s.add_dependency(%q<bundler>, ["~> 1.
|
68
|
-
s.add_dependency(%q<jeweler>, ["~> 1.8.
|
69
|
-
s.add_dependency(%q<yard>, ["
|
69
|
+
s.add_dependency(%q<bundler>, ["~> 1.3.5"])
|
70
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
|
71
|
+
s.add_dependency(%q<yard>, ["~> 0.8.6.2"])
|
70
72
|
s.add_dependency(%q<redcarpet>, [">= 0"])
|
71
73
|
s.add_dependency(%q<github-markup>, [">= 0"])
|
72
74
|
end
|
data/test/helper.rb
CHANGED
@@ -18,16 +18,31 @@ require 'spinning_cursor'
|
|
18
18
|
# (http://thinkingdigitally.com/archive/capturing-output-from-puts-in-ruby/)
|
19
19
|
|
20
20
|
require 'stringio'
|
21
|
+
|
22
|
+
def kill_other_threads
|
23
|
+
other_threads = Thread.list - [Thread.current]
|
24
|
+
other_threads.each do |th|
|
25
|
+
th.kill
|
26
|
+
th.join
|
27
|
+
end
|
28
|
+
end
|
21
29
|
|
22
30
|
module Kernel
|
23
31
|
def capture_stdout
|
32
|
+
SpinningCursor.capture_console
|
24
33
|
out = StringIO.new
|
25
|
-
$
|
34
|
+
$console = out
|
26
35
|
yield out
|
27
36
|
ensure
|
28
|
-
|
37
|
+
kill_other_threads
|
38
|
+
$console = STDOUT
|
39
|
+
SpinningCursor.release_console
|
29
40
|
end
|
30
41
|
end
|
31
42
|
|
43
|
+
include SpinningCursor
|
44
|
+
|
45
|
+
Thread.abort_on_exception=true
|
46
|
+
|
32
47
|
class Test::Unit::TestCase
|
33
48
|
end
|
data/test/test_cursors.rb
CHANGED
@@ -2,40 +2,80 @@ require 'helper'
|
|
2
2
|
|
3
3
|
class TestSpinningCursorCursor < Test::Unit::TestCase
|
4
4
|
context "dots" do
|
5
|
-
|
5
|
+
parsed = Parser.new { type :dots; delay 0.2; banner ""}
|
6
|
+
delay = parsed.delay
|
7
|
+
should "change 'frames' with correct delay" do
|
6
8
|
capture_stdout do |out|
|
7
9
|
dots = Thread.new do
|
8
|
-
SpinningCursor::Cursor.new(
|
10
|
+
SpinningCursor::Cursor.new(parsed).spin
|
9
11
|
end
|
10
|
-
|
12
|
+
# slight delay to get things started
|
13
|
+
sleep (delay/4.0)
|
14
|
+
buffer = "#{ESC_R_AND_CLR}" << "."
|
15
|
+
assert_equal buffer, out.string
|
16
|
+
|
17
|
+
sleep delay
|
18
|
+
buffer << "#{ESC_R_AND_CLR}" << ".."
|
19
|
+
assert_equal buffer, out.string
|
20
|
+
|
21
|
+
sleep delay
|
22
|
+
buffer << "#{ESC_R_AND_CLR}" << "..."
|
23
|
+
assert_equal buffer, out.string
|
24
|
+
|
25
|
+
sleep delay
|
26
|
+
buffer << "#{ESC_R_AND_CLR}"
|
27
|
+
assert_equal buffer, out.string
|
28
|
+
# don't need to go through the whole thing, otherwise test will take
|
29
|
+
# too long
|
11
30
|
dots.kill
|
12
|
-
# \r\e[0K is move cursor to the start of the line and clear line
|
13
|
-
# in bash
|
14
|
-
assert_equal "...\r\e[0K", out.string
|
15
31
|
end
|
16
32
|
end
|
17
33
|
end
|
18
34
|
|
19
35
|
context "spinner" do
|
20
36
|
should "cycle through correctly" do
|
37
|
+
parsed = Parser.new { type :spinner; delay 0.2; banner ""}
|
38
|
+
delay = parsed.delay
|
39
|
+
capture_stdout do |out|
|
40
|
+
spinner = Thread.new do
|
41
|
+
SpinningCursor::Cursor.new(parsed).spin
|
42
|
+
end
|
43
|
+
# slight delay to get things started
|
44
|
+
sleep (delay/3.0)
|
45
|
+
buffer = (ESC_R_AND_CLR + "|")
|
46
|
+
assert_equal buffer, out.string
|
47
|
+
buffer += (ESC_R_AND_CLR + "/")
|
48
|
+
sleep delay
|
49
|
+
assert_equal buffer, out.string
|
50
|
+
buffer += (ESC_R_AND_CLR + "-")
|
51
|
+
sleep delay
|
52
|
+
assert_equal buffer, out.string
|
53
|
+
buffer += (ESC_R_AND_CLR + "\\")
|
54
|
+
sleep delay
|
55
|
+
assert_equal buffer, out.string
|
56
|
+
sleep delay
|
57
|
+
buffer += (ESC_R_AND_CLR + "|")
|
58
|
+
assert_equal buffer, out.string
|
59
|
+
spinner.kill
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
should "changes 'frames' with correct delay" do
|
64
|
+
parsed = Parser.new { type :spinner; delay 0.2; banner ""}
|
65
|
+
delay = parsed.delay
|
21
66
|
capture_stdout do |out|
|
22
67
|
spinner = Thread.new do
|
23
|
-
SpinningCursor::Cursor.new(
|
68
|
+
SpinningCursor::Cursor.new(parsed).spin
|
24
69
|
end
|
25
|
-
sleep 0
|
26
|
-
|
27
|
-
buffer
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
sleep 0.5
|
35
|
-
assert_equal "#{buffer}\\", out.string
|
36
|
-
buffer += "\\\r\e[0K"
|
37
|
-
sleep 0.5
|
38
|
-
assert_equal "#{buffer}|", out.string
|
70
|
+
sleep (delay/4.0)
|
71
|
+
buffer = (ESC_R_AND_CLR + "|")
|
72
|
+
assert_equal buffer, out.string
|
73
|
+
buffer += (ESC_R_AND_CLR + "/")
|
74
|
+
sleep delay
|
75
|
+
# next frame after 'delay' second
|
76
|
+
assert_equal buffer, out.string
|
77
|
+
# don't need to go through the whole thing, otherwise test will take
|
78
|
+
# too long
|
39
79
|
spinner.kill
|
40
80
|
end
|
41
81
|
end
|
data/test/test_exceptions.rb
CHANGED
@@ -17,12 +17,6 @@ class TestSpinningCursor < Test::Unit::TestCase
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
should "a) raise NoTaskError when getting execution time if no task ran" do
|
21
|
-
assert_raise SpinningCursor::NoTaskError do
|
22
|
-
SpinningCursor.get_exec_time
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
20
|
should "raise CursorNotRunning errors when cursor has run and finished" do
|
27
21
|
SpinningCursor.start
|
28
22
|
SpinningCursor.stop
|
data/test/test_parser.rb
CHANGED
@@ -1,34 +1,78 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
3
|
class TestSpinningCursorParser < Test::Unit::TestCase
|
4
|
-
context "
|
5
|
-
should "
|
6
|
-
|
7
|
-
|
4
|
+
context "A Parser instance" do
|
5
|
+
should "always respond to outer_scope_object method" do
|
6
|
+
assert_respond_to Parser.new, :outer_scope_object
|
7
|
+
end
|
8
|
+
|
9
|
+
context "initialized WITHOUT a block" do
|
10
|
+
should "have outer_scope_object equal nil" do
|
11
|
+
assert_equal nil, Parser.new.outer_scope_object
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context "initialized WITH a block" do
|
16
|
+
should "have outer_scope_object point to 'caller'" do
|
17
|
+
parsed = Parser.new {}
|
18
|
+
assert_equal self, parsed.outer_scope_object
|
19
|
+
end
|
20
|
+
|
21
|
+
context "having an 'action' block within this block" do
|
22
|
+
should "have this action block retrievable with Parser#action" do
|
23
|
+
action_block = Proc.new { }
|
24
|
+
parsed = Parser.new do
|
25
|
+
action &action_block
|
26
|
+
end
|
27
|
+
assert_equal action_block, parsed.action
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "and instance evaluating this block at Parser context" do
|
32
|
+
should "NOT have access to instance variables of outer_scope_object from inside the block" do
|
33
|
+
@outer_instance_variable = 1
|
34
|
+
parsed = Parser.new { @outer_instance_variable = 2 }
|
35
|
+
assert_not_equal 2, @outer_instance_variable
|
36
|
+
assert_equal 2, parsed.instance_variable_get(:@outer_instance_variable)
|
37
|
+
end
|
38
|
+
|
39
|
+
should "have direct access to instance variables of the Parser instance itself" do
|
40
|
+
parsed = Parser.new { @banner = "this is Parser instance"}
|
41
|
+
assert_equal parsed.banner, "this is Parser instance"
|
42
|
+
end
|
43
|
+
|
44
|
+
should "have access to methods of outer_scope_object from inside the block (thanks method_missing)" do
|
45
|
+
def outer_method
|
46
|
+
"Outer Method"
|
47
|
+
end
|
48
|
+
parsed = Parser.new { banner outer_method }
|
49
|
+
assert_equal outer_method, parsed.banner
|
50
|
+
end
|
8
51
|
end
|
9
|
-
parser = SpinningCursor::Parser.new Proc.new { banner banner_text }
|
10
|
-
assert_equal banner_text, (parser.banner nil)
|
11
52
|
end
|
12
53
|
end
|
13
54
|
|
14
|
-
context "banner, type, message and action methods" do
|
55
|
+
context "banner, type, message, delay and action methods" do
|
15
56
|
setup do
|
16
|
-
@parser = SpinningCursor::Parser.new
|
57
|
+
@parser = SpinningCursor::Parser.new
|
17
58
|
end
|
18
59
|
|
19
60
|
should "act as getters and setters" do
|
20
61
|
@parser.banner "a new banner"
|
21
|
-
assert_equal "a new banner",
|
62
|
+
assert_equal "a new banner", @parser.banner
|
22
63
|
|
23
64
|
@parser.type :dots
|
24
|
-
assert_equal :dots,
|
65
|
+
assert_equal :dots, @parser.type
|
25
66
|
|
26
67
|
@parser.message "a message"
|
27
|
-
assert_equal "a message",
|
68
|
+
assert_equal "a message", @parser.message
|
69
|
+
|
70
|
+
@parser.delay 5
|
71
|
+
assert_equal 5, @parser.delay
|
28
72
|
|
29
73
|
proc = Proc.new { }
|
30
74
|
@parser.action &proc
|
31
75
|
assert_equal proc, @parser.action
|
32
76
|
end
|
33
77
|
end
|
34
|
-
end
|
78
|
+
end
|
@@ -6,13 +6,22 @@ class TestSpinningCursor < Test::Unit::TestCase
|
|
6
6
|
# Hide any output
|
7
7
|
capture_stdout do |out|
|
8
8
|
SpinningCursor.start do
|
9
|
-
action { sleep 1 }
|
9
|
+
action { sleep 0.1 }
|
10
10
|
end
|
11
11
|
# Give it some time to abort
|
12
12
|
assert_equal false, SpinningCursor.alive?
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
+
should "Parser#outer_scope_object point to 'caller'" do
|
17
|
+
capture_stdout do |out|
|
18
|
+
SpinningCursor.start { }
|
19
|
+
parsed = SpinningCursor.instance_variable_get(:@parsed)
|
20
|
+
assert_equal self, parsed.outer_scope_object
|
21
|
+
SpinningCursor.stop
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
16
25
|
should "evalute the block from the calling class" do
|
17
26
|
@num = 1
|
18
27
|
capture_stdout do |out|
|
@@ -23,6 +32,17 @@ class TestSpinningCursor < Test::Unit::TestCase
|
|
23
32
|
assert_equal 2, @num
|
24
33
|
end
|
25
34
|
end
|
35
|
+
|
36
|
+
should "raise an exception if something wrong inside the 'action' block" do
|
37
|
+
class SomethingWrongHappened < StandardError; end
|
38
|
+
assert_raise SomethingWrongHappened do
|
39
|
+
capture_stdout do |out|
|
40
|
+
SpinningCursor.start do
|
41
|
+
action { raise SomethingWrongHappened }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
26
46
|
end
|
27
47
|
|
28
48
|
context "when an action block isn't passed it" do
|
@@ -31,7 +51,7 @@ class TestSpinningCursor < Test::Unit::TestCase
|
|
31
51
|
SpinningCursor.start do
|
32
52
|
banner "no action block"
|
33
53
|
end
|
34
|
-
sleep
|
54
|
+
sleep 0.5
|
35
55
|
assert_equal true, SpinningCursor.alive?
|
36
56
|
SpinningCursor.stop
|
37
57
|
sleep 0.1
|
@@ -56,12 +76,14 @@ class TestSpinningCursor < Test::Unit::TestCase
|
|
56
76
|
|
57
77
|
should "stop and display error if an unmanaged exception is thrown" do
|
58
78
|
capture_stdout do |out|
|
59
|
-
|
60
|
-
|
61
|
-
|
79
|
+
begin
|
80
|
+
SpinningCursor.start do
|
81
|
+
action do
|
82
|
+
raise "An exception!"
|
83
|
+
end
|
62
84
|
end
|
85
|
+
rescue # Just to let the test go on
|
63
86
|
end
|
64
|
-
|
65
87
|
assert_equal true, (out.string.include? "An exception!")
|
66
88
|
end
|
67
89
|
end
|
@@ -85,18 +107,61 @@ class TestSpinningCursor < Test::Unit::TestCase
|
|
85
107
|
should "allow you to change the banner" do
|
86
108
|
capture_stdout do |out|
|
87
109
|
SpinningCursor.start do
|
110
|
+
delay 0.2
|
88
111
|
action do
|
89
112
|
# Have to give it time to print the banners
|
90
113
|
sleep 0.1
|
91
|
-
assert_equal true, (out.string.include? "Loading")
|
114
|
+
assert_equal true, (out.string.include? "Loading"), "It should initialy show default banner"
|
92
115
|
sleep 0.1
|
93
116
|
SpinningCursor.set_banner "Finishing up"
|
94
|
-
sleep 0.
|
95
|
-
assert_equal true, (out.string.include? "Finishing up")
|
117
|
+
sleep 0.2
|
118
|
+
assert_equal true, (out.string.include? "Finishing up"), "It should have changed banner"
|
96
119
|
sleep 0.1
|
97
120
|
end
|
98
121
|
end
|
99
122
|
end
|
100
123
|
end
|
101
124
|
end
|
125
|
+
|
126
|
+
context "when running for the second time" do
|
127
|
+
should "(without a block) return similar timing values" do
|
128
|
+
capture_stdout do |out|
|
129
|
+
SpinningCursor.start
|
130
|
+
sleep 0.2
|
131
|
+
result = SpinningCursor.stop
|
132
|
+
timing_1 = result[:elapsed_time]
|
133
|
+
|
134
|
+
SpinningCursor.start
|
135
|
+
sleep 0.2
|
136
|
+
result = SpinningCursor.stop
|
137
|
+
timing_2 = result[:elapsed_time]
|
138
|
+
|
139
|
+
assert_equal (timing_1*10).round, (timing_2*10).round,
|
140
|
+
"t1 #{timing_1} and t2 #{timing_2} should be equal"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
should "(with a block) return similar timing values" do
|
145
|
+
capture_stdout do |out|
|
146
|
+
result =
|
147
|
+
SpinningCursor.start do
|
148
|
+
action do
|
149
|
+
sleep 0.2
|
150
|
+
end
|
151
|
+
end
|
152
|
+
timing_1 = result[:elapsed_time]
|
153
|
+
|
154
|
+
result =
|
155
|
+
SpinningCursor.start do
|
156
|
+
action do
|
157
|
+
sleep 0.2
|
158
|
+
end
|
159
|
+
end
|
160
|
+
timing_2 = result[:elapsed_time]
|
161
|
+
|
162
|
+
assert_equal (timing_1*10).round, (timing_2*10).round,
|
163
|
+
"t1 #{timing_1} and t2 #{timing_2} should be equal"
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
102
167
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spinning_cursor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-07-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: shoulda
|
@@ -34,7 +34,7 @@ dependencies:
|
|
34
34
|
requirements:
|
35
35
|
- - ~>
|
36
36
|
- !ruby/object:Gem::Version
|
37
|
-
version: 1.
|
37
|
+
version: 1.3.5
|
38
38
|
type: :development
|
39
39
|
prerelease: false
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -42,7 +42,7 @@ dependencies:
|
|
42
42
|
requirements:
|
43
43
|
- - ~>
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
version: 1.
|
45
|
+
version: 1.3.5
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
47
|
name: jeweler
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -50,7 +50,7 @@ dependencies:
|
|
50
50
|
requirements:
|
51
51
|
- - ~>
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: 1.8.
|
53
|
+
version: 1.8.4
|
54
54
|
type: :development
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -58,23 +58,23 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 1.8.
|
61
|
+
version: 1.8.4
|
62
62
|
- !ruby/object:Gem::Dependency
|
63
63
|
name: yard
|
64
64
|
requirement: !ruby/object:Gem::Requirement
|
65
65
|
none: false
|
66
66
|
requirements:
|
67
|
-
- -
|
67
|
+
- - ~>
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version:
|
69
|
+
version: 0.8.6.2
|
70
70
|
type: :development
|
71
71
|
prerelease: false
|
72
72
|
version_requirements: !ruby/object:Gem::Requirement
|
73
73
|
none: false
|
74
74
|
requirements:
|
75
|
-
- -
|
75
|
+
- - ~>
|
76
76
|
- !ruby/object:Gem::Version
|
77
|
-
version:
|
77
|
+
version: 0.8.6.2
|
78
78
|
- !ruby/object:Gem::Dependency
|
79
79
|
name: redcarpet
|
80
80
|
requirement: !ruby/object:Gem::Requirement
|
@@ -130,8 +130,10 @@ files:
|
|
130
130
|
- TODO
|
131
131
|
- VERSION
|
132
132
|
- lib/spinning_cursor.rb
|
133
|
+
- lib/spinning_cursor/console_helpers.rb
|
133
134
|
- lib/spinning_cursor/cursor.rb
|
134
135
|
- lib/spinning_cursor/parser.rb
|
136
|
+
- lib/spinning_cursor/stop_watch.rb
|
135
137
|
- spinning_cursor.gemspec
|
136
138
|
- test/helper.rb
|
137
139
|
- test/test_cursors.rb
|
@@ -153,7 +155,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
153
155
|
version: '0'
|
154
156
|
segments:
|
155
157
|
- 0
|
156
|
-
hash:
|
158
|
+
hash: 2712039492645402918
|
157
159
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
158
160
|
none: false
|
159
161
|
requirements:
|