whirly 0.1.1 → 0.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.
- checksums.yaml +4 -4
- data/.travis.yml +5 -0
- data/CHANGELOG.md +18 -1
- data/Gemfile +1 -0
- data/README.md +201 -19
- data/Rakefile +23 -2
- data/data/{spinners.json → cli-spinners.json} +92 -0
- data/data/whirly-static-spinners.json +86 -0
- data/examples/all_spinners.rb +21 -0
- data/examples/asciinema_bundled_spinners.rb +12 -0
- data/{euruko.rb → examples/euruko.rb} +4 -42
- data/examples/multi_lines.rb +20 -0
- data/examples/single.rb +6 -0
- data/examples/status.rb +7 -0
- data/lib/whirly.rb +187 -76
- data/lib/whirly/spinners.rb +5 -4
- data/lib/whirly/spinners/cli.rb +7 -0
- data/lib/whirly/spinners/whirly.rb +20 -0
- data/lib/whirly/version.rb +1 -1
- data/spec/whirly_spec.rb +231 -10
- data/whirly.gemspec +5 -2
- metadata +29 -9
- data/lib/whirly/.spinners.rb.swp +0 -0
- data/spec/.whirly_spec.rb.swp +0 -0
data/lib/whirly/spinners.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
-
require "json"
|
2
|
-
|
3
1
|
module Whirly
|
4
|
-
|
5
|
-
|
2
|
+
module Spinners
|
3
|
+
end
|
6
4
|
end
|
5
|
+
|
6
|
+
require_relative "spinners/whirly"
|
7
|
+
require_relative "spinners/cli"
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
module Whirly
|
4
|
+
module Spinners
|
5
|
+
WHIRLY = {
|
6
|
+
"whirly" => { "proc" => ->(){ [0x1F600 + rand(55) ].pack("U") }, "interval" => 200 },
|
7
|
+
"random_dots" => { "proc" => ->(){ [ 0x2800 + rand(256)].pack("U") }, "interval" => 100 },
|
8
|
+
"circled_letter" => { "proc" => ->(){ [ 0x24B6 + rand(26) ].pack("U") }, "interval" => 120 },
|
9
|
+
"circled_number" => { "proc" => ->(){ [ 0x2460 + rand(9) ].pack("U") }, "interval" => 120 },
|
10
|
+
"starlike" => { "proc" => ->(){ [ 0x2729 + rand(34) ].pack("U") }, "interval" => 120 },
|
11
|
+
"mahjong" => { "proc" => ->(){ [0x1F000 + rand(44)].pack("U") }, "interval" => 200 },
|
12
|
+
"domino" => { "proc" => ->(){ [0x1F030 + rand(50)].pack("U") }, "interval" => 200 },
|
13
|
+
"vertical_domino" => { "proc" => ->(){ [0x1F062 + rand(50)].pack("U") }, "interval" => 200 },
|
14
|
+
"letters_with_parens" => { "proc" => ->(){ [0x1F110 + rand(26)].pack("U") }, "interval" => 150 },
|
15
|
+
}
|
16
|
+
WHIRLY.merge! JSON.load(File.read(File.dirname(__FILE__) + "/../../../data/whirly-static-spinners.json"))
|
17
|
+
|
18
|
+
WHIRLY.freeze
|
19
|
+
end
|
20
|
+
end
|
data/lib/whirly/version.rb
CHANGED
data/spec/whirly_spec.rb
CHANGED
@@ -1,29 +1,250 @@
|
|
1
1
|
require_relative "../lib/whirly"
|
2
2
|
require "minitest/autorun"
|
3
|
+
# require "irbtools/binding"
|
4
|
+
require "stringio"
|
5
|
+
|
6
|
+
def short_sleep
|
7
|
+
sleep 0.1
|
8
|
+
end
|
9
|
+
|
10
|
+
def medium_sleep
|
11
|
+
sleep 0.4
|
12
|
+
end
|
13
|
+
|
14
|
+
def long_sleep
|
15
|
+
sleep 1
|
16
|
+
end
|
3
17
|
|
4
18
|
describe Whirly do
|
5
|
-
|
19
|
+
before do
|
20
|
+
Whirly.reset
|
21
|
+
@capture = StringIO.new
|
22
|
+
Whirly.configure(non_tty: true, stream: @capture)
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "General Usage" do
|
6
26
|
it "outputs every frame of the spinner" do
|
7
|
-
spinner = { "frames" => ["first", "second", "third"], "interval" =>
|
27
|
+
spinner = { "frames" => ["first", "second", "third"], "interval" => 5 }
|
28
|
+
|
29
|
+
Whirly.start(spinner: spinner)
|
30
|
+
short_sleep
|
31
|
+
Whirly.stop
|
32
|
+
|
33
|
+
assert_match /first.*second.*third/m, @capture.string
|
34
|
+
end
|
35
|
+
|
36
|
+
it "calls spinner proc instead of frames if proc is given" do
|
37
|
+
spinner = { "proc" => ->(){ "frame" }, "interval" => 5 }
|
8
38
|
|
9
|
-
|
10
|
-
|
11
|
-
|
39
|
+
Whirly.start(spinner: spinner)
|
40
|
+
short_sleep
|
41
|
+
Whirly.stop
|
42
|
+
|
43
|
+
assert_match /frame/, @capture.string
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "Status Updates" do
|
48
|
+
it "shows status text alongside spinner" do
|
49
|
+
Whirly.start
|
50
|
+
Whirly.status = "Fetching…"
|
51
|
+
medium_sleep
|
52
|
+
Whirly.status = "Updates…"
|
53
|
+
medium_sleep
|
54
|
+
Whirly.stop
|
55
|
+
|
56
|
+
assert_match /Fetching.*Updates…/m, @capture.string
|
57
|
+
end
|
58
|
+
|
59
|
+
it "shows initial status" do
|
60
|
+
Whirly.start(status: "Initial")
|
61
|
+
short_sleep
|
62
|
+
Whirly.stop
|
63
|
+
|
64
|
+
assert_match /Initial/, @capture.string
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "Finishing" do
|
69
|
+
it "shows spinner finished frame if stop is set in spinner definition" do
|
70
|
+
spinner = { "frames" => ["first", "second", "third"], "stop" => "STOP", "interval" => 5 }
|
71
|
+
|
72
|
+
Whirly.start(spinner: spinner)
|
73
|
+
short_sleep
|
74
|
+
Whirly.stop
|
75
|
+
|
76
|
+
assert_match /STOP/, @capture.string
|
77
|
+
end
|
78
|
+
|
79
|
+
it "shows spinner finished frame if stop frame is passed when stopping" do
|
80
|
+
spinner = { "frames" => ["first", "second", "third"], "interval" => 5 }
|
81
|
+
|
82
|
+
Whirly.start(spinner: spinner)
|
83
|
+
short_sleep
|
84
|
+
Whirly.stop("STOP")
|
85
|
+
|
86
|
+
assert_match /STOP/, @capture.string
|
87
|
+
end
|
88
|
+
|
89
|
+
it "shows spinner finished frame if stop frame is passed when starting" do
|
90
|
+
spinner = { "frames" => ["first", "second", "third"], "interval" => 5 }
|
91
|
+
|
92
|
+
Whirly.start(spinner: spinner, stop: "STOP")
|
93
|
+
short_sleep
|
94
|
+
Whirly.stop
|
95
|
+
|
96
|
+
assert_match /STOP/, @capture.string
|
97
|
+
end
|
98
|
+
|
99
|
+
it "appends newline when stopping" do
|
100
|
+
Whirly.start(hide_cursor: false)
|
101
|
+
short_sleep
|
102
|
+
Whirly.stop
|
103
|
+
|
104
|
+
assert_match /\n\z/, @capture.string
|
105
|
+
end
|
106
|
+
|
107
|
+
it "appends no newline when stopping when :append_newline option is false" do
|
108
|
+
Whirly.start(hide_cursor: false, append_newline: false)
|
109
|
+
short_sleep
|
110
|
+
Whirly.stop
|
111
|
+
|
112
|
+
assert_match /[^\n]\z/, @capture.string
|
113
|
+
end
|
114
|
+
|
115
|
+
it "removes the spinner after stopping when :remove_after_stop is true" do
|
116
|
+
Whirly.start(hide_cursor: false, remove_after_stop: true)
|
117
|
+
short_sleep
|
118
|
+
Whirly.stop
|
119
|
+
|
120
|
+
assert_match /\e\[u\n\z/, @capture.string
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe "Spinner" do
|
125
|
+
describe "Passing a Spinner" do
|
126
|
+
it "can be the name of a bundled spinner (whirly-spinners)" do
|
127
|
+
Whirly.start(spinner: "pencil")
|
128
|
+
medium_sleep
|
129
|
+
Whirly.stop
|
130
|
+
|
131
|
+
assert_match /✎/, @capture.string
|
132
|
+
end
|
133
|
+
|
134
|
+
it "can be the name of a bundled spinner (cli-spinners)" do
|
135
|
+
Whirly.start(spinner: "dots3")
|
136
|
+
medium_sleep
|
137
|
+
Whirly.stop
|
138
|
+
|
139
|
+
assert_match /⠋/, @capture.string
|
140
|
+
end
|
141
|
+
|
142
|
+
it "can be an Array of frames" do
|
143
|
+
Whirly.start(spinner: ["A", "B"])
|
144
|
+
medium_sleep
|
12
145
|
Whirly.stop
|
146
|
+
|
147
|
+
assert_match /A.*B/m, @capture.string
|
148
|
+
end
|
149
|
+
|
150
|
+
it "can be an Enumerator of frames" do
|
151
|
+
Whirly.start(spinner: "A".."B")
|
152
|
+
medium_sleep
|
153
|
+
Whirly.stop
|
154
|
+
|
155
|
+
assert_match /A.*B/m, @capture.string
|
156
|
+
end
|
157
|
+
|
158
|
+
it "can be a Proc which generates frames" do
|
159
|
+
Whirly.start(spinner: ->(){ "frame" })
|
160
|
+
medium_sleep
|
161
|
+
Whirly.stop
|
162
|
+
|
163
|
+
assert_match /frame/m, @capture.string
|
13
164
|
end
|
14
165
|
end
|
15
166
|
|
16
|
-
|
17
|
-
|
167
|
+
describe "Frame Mode" do
|
168
|
+
it "can be set to random" do
|
169
|
+
spinner = { "frames" => "A".."H", "mode" => "random", "interval" => 10 }
|
170
|
+
|
171
|
+
Whirly.start(spinner: spinner)
|
172
|
+
medium_sleep
|
173
|
+
Whirly.stop
|
174
|
+
|
175
|
+
refute /A.*B.*C.*D.*E.*F.*G.*H/m =~ @capture.string
|
176
|
+
end
|
177
|
+
|
178
|
+
it "can be set to reverse" do
|
179
|
+
spinner = { "frames" => "A".."H", "mode" => "reverse", "interval" => 10 }
|
180
|
+
|
181
|
+
Whirly.start(spinner: spinner)
|
182
|
+
medium_sleep
|
183
|
+
Whirly.stop
|
184
|
+
|
185
|
+
assert_match /H.*G.*F.*E.*D.*C.*B.*A/m, @capture.string
|
186
|
+
end
|
187
|
+
|
188
|
+
it "can be set to swing" do
|
189
|
+
spinner = { "frames" => "A".."H", "mode" => "swing", "interval" => 10 }
|
18
190
|
|
19
|
-
|
20
|
-
|
21
|
-
sleep 0.1
|
191
|
+
Whirly.start(spinner: spinner)
|
192
|
+
medium_sleep
|
22
193
|
Whirly.stop
|
194
|
+
|
195
|
+
assert_match /A.*B.*C.*D.*E.*F.*G.*H.*G.*F.*E.*D.*C.*B.*A/m, @capture.string
|
23
196
|
end
|
24
197
|
end
|
25
198
|
end
|
26
199
|
|
200
|
+
describe "Ansi Escape Mode" do
|
201
|
+
it "will use save and restore ANSI sequences as default (or when 'restore') is given" do
|
202
|
+
Whirly.start
|
203
|
+
short_sleep
|
204
|
+
Whirly.stop
|
205
|
+
assert_match /\e\[s.*\e\[u/m, @capture.string
|
206
|
+
end
|
207
|
+
|
208
|
+
it "will use beginning of line and clear line ANSI sequences when 'line' is given" do
|
209
|
+
Whirly.start(ansi_escape_mode: 'line')
|
210
|
+
medium_sleep
|
211
|
+
Whirly.stop
|
212
|
+
assert_match /\e\[G.*\e\[1K/m, @capture.string
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
describe "Positioning" do
|
217
|
+
it "will render spinner 1 line further below (useful for spinning while git cloning)" do
|
218
|
+
Whirly.start(position: "below")
|
219
|
+
short_sleep
|
220
|
+
Whirly.stop
|
221
|
+
|
222
|
+
assert_match /\n.*\e\[1A/m, @capture.string
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
describe "Configure and Reset" do
|
227
|
+
it "can be configured before starting" do
|
228
|
+
Whirly.configure spinner: "dots", interval: 5
|
229
|
+
|
230
|
+
Whirly.start
|
231
|
+
short_sleep
|
232
|
+
Whirly.stop
|
233
|
+
|
234
|
+
assert_match /⠧/, @capture.string
|
235
|
+
end
|
236
|
+
|
237
|
+
it "can be reset using .reset" do
|
238
|
+
Whirly.configure spinner: "dots", interval: 5
|
239
|
+
Whirly.reset
|
240
|
+
|
241
|
+
Whirly.start(non_tty: true, stream: @capture)
|
242
|
+
short_sleep
|
243
|
+
Whirly.stop
|
244
|
+
assert_match /\A[^⠧]+\z/, @capture.string
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
27
248
|
describe ".enabled?" do
|
28
249
|
it "returns false if whirly was not started yet" do
|
29
250
|
refute_predicate Whirly, :enabled?
|
data/whirly.gemspec
CHANGED
@@ -6,18 +6,21 @@ Gem::Specification.new do |gem|
|
|
6
6
|
gem.name = "whirly"
|
7
7
|
gem.version = Whirly::VERSION
|
8
8
|
gem.summary = "Whirly: The friendly terminal spinner"
|
9
|
-
gem.description = "
|
9
|
+
gem.description = "Simple terminal spinner with support for custom spinners. Includes spinners from npm's cli-spinners."
|
10
10
|
gem.authors = ["Jan Lelis"]
|
11
11
|
gem.email = ["mail@janlelis.de"]
|
12
12
|
gem.homepage = "https://github.com/janlelis/whirly"
|
13
13
|
gem.license = "MIT"
|
14
14
|
|
15
15
|
gem.files = Dir["{**/}{.*,*}"].select{ |path| File.file?(path) && path !~ /^(pkg|data)/ } + %w[
|
16
|
-
data/spinners.json
|
16
|
+
data/cli-spinners.json
|
17
|
+
data/whirly-static-spinners.json
|
17
18
|
]
|
18
19
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
19
20
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
20
21
|
gem.require_paths = ["lib"]
|
21
22
|
|
23
|
+
gem.add_dependency "unicode-display_width", "~> 1.1"
|
24
|
+
|
22
25
|
gem.required_ruby_version = "~> 2.0"
|
23
26
|
end
|
metadata
CHANGED
@@ -1,16 +1,31 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: whirly
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jan Lelis
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
12
|
-
dependencies:
|
13
|
-
|
11
|
+
date: 2016-10-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: unicode-display_width
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.1'
|
27
|
+
description: Simple terminal spinner with support for custom spinners. Includes spinners
|
28
|
+
from npm's cli-spinners.
|
14
29
|
email:
|
15
30
|
- mail@janlelis.de
|
16
31
|
executables: []
|
@@ -27,13 +42,19 @@ files:
|
|
27
42
|
- MIT-LICENSE.txt
|
28
43
|
- README.md
|
29
44
|
- Rakefile
|
30
|
-
- data/spinners.json
|
31
|
-
-
|
45
|
+
- data/cli-spinners.json
|
46
|
+
- data/whirly-static-spinners.json
|
47
|
+
- examples/all_spinners.rb
|
48
|
+
- examples/asciinema_bundled_spinners.rb
|
49
|
+
- examples/euruko.rb
|
50
|
+
- examples/multi_lines.rb
|
51
|
+
- examples/single.rb
|
52
|
+
- examples/status.rb
|
32
53
|
- lib/whirly.rb
|
33
|
-
- lib/whirly/.spinners.rb.swp
|
34
54
|
- lib/whirly/spinners.rb
|
55
|
+
- lib/whirly/spinners/cli.rb
|
56
|
+
- lib/whirly/spinners/whirly.rb
|
35
57
|
- lib/whirly/version.rb
|
36
|
-
- spec/.whirly_spec.rb.swp
|
37
58
|
- spec/whirly_spec.rb
|
38
59
|
- whirly.gemspec
|
39
60
|
homepage: https://github.com/janlelis/whirly
|
@@ -61,5 +82,4 @@ signing_key:
|
|
61
82
|
specification_version: 4
|
62
83
|
summary: 'Whirly: The friendly terminal spinner'
|
63
84
|
test_files:
|
64
|
-
- spec/.whirly_spec.rb.swp
|
65
85
|
- spec/whirly_spec.rb
|
data/lib/whirly/.spinners.rb.swp
DELETED
Binary file
|
data/spec/.whirly_spec.rb.swp
DELETED
Binary file
|