tty-spinner 0.8.0 → 0.9.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.
Files changed (61) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +120 -0
  3. data/README.md +28 -10
  4. data/Rakefile +8 -0
  5. data/examples/auto_spin.rb +8 -0
  6. data/examples/basic.rb +8 -0
  7. data/examples/clear.rb +9 -0
  8. data/examples/color.rb +12 -0
  9. data/examples/error.rb +9 -0
  10. data/examples/formats.rb +11 -0
  11. data/examples/hide_cursor.rb +12 -0
  12. data/examples/multi/basic.rb +13 -0
  13. data/examples/multi/basic_top_level.rb +13 -0
  14. data/examples/multi/custom_style.rb +26 -0
  15. data/examples/multi/files.rb +14 -0
  16. data/examples/multi/jobs.rb +10 -0
  17. data/examples/multi/multi.rb +17 -0
  18. data/examples/multi/multi_top_level.rb +18 -0
  19. data/examples/multi/pause.rb +26 -0
  20. data/examples/multi/threaded.rb +30 -0
  21. data/examples/pause.rb +19 -0
  22. data/examples/run.rb +18 -0
  23. data/examples/success.rb +9 -0
  24. data/examples/threaded.rb +11 -0
  25. data/examples/update.rb +11 -0
  26. data/lib/tty-spinner.rb +0 -2
  27. data/lib/tty/spinner.rb +40 -30
  28. data/lib/tty/spinner/formats.rb +3 -3
  29. data/lib/tty/spinner/multi.rb +31 -12
  30. data/lib/tty/spinner/version.rb +2 -2
  31. data/spec/spec_helper.rb +51 -0
  32. data/spec/unit/auto_spin_spec.rb +27 -0
  33. data/spec/unit/clear_spec.rb +18 -0
  34. data/spec/unit/error_spec.rb +46 -0
  35. data/spec/unit/events_spec.rb +37 -0
  36. data/spec/unit/formats_spec.rb +9 -0
  37. data/spec/unit/frames_spec.rb +33 -0
  38. data/spec/unit/hide_cursor_spec.rb +53 -0
  39. data/spec/unit/job_spec.rb +14 -0
  40. data/spec/unit/join_spec.rb +12 -0
  41. data/spec/unit/multi/auto_spin_spec.rb +34 -0
  42. data/spec/unit/multi/error_spec.rb +109 -0
  43. data/spec/unit/multi/line_inset_spec.rb +59 -0
  44. data/spec/unit/multi/on_spec.rb +13 -0
  45. data/spec/unit/multi/register_spec.rb +47 -0
  46. data/spec/unit/multi/spin_spec.rb +103 -0
  47. data/spec/unit/multi/stop_spec.rb +97 -0
  48. data/spec/unit/multi/success_spec.rb +110 -0
  49. data/spec/unit/new_spec.rb +26 -0
  50. data/spec/unit/pause_spec.rb +25 -0
  51. data/spec/unit/reset_spec.rb +21 -0
  52. data/spec/unit/run_spec.rb +32 -0
  53. data/spec/unit/spin_spec.rb +90 -0
  54. data/spec/unit/stop_spec.rb +64 -0
  55. data/spec/unit/success_spec.rb +46 -0
  56. data/spec/unit/update_spec.rb +87 -0
  57. data/tasks/console.rake +11 -0
  58. data/tasks/coverage.rake +11 -0
  59. data/tasks/spec.rake +29 -0
  60. data/tty-spinner.gemspec +27 -0
  61. metadata +62 -9
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+
3
+ RSpec.describe TTY::Spinner, '#run' do
4
+ let(:output) { StringIO.new('', 'w+') }
5
+
6
+ it "runs animation while executing block" do
7
+ spinner = TTY::Spinner.new(output: output, interval: 100)
8
+ allow(spinner).to receive(:spin)
9
+ spinner.run("done") { sleep(0.1) }
10
+ expect(spinner).to have_received(:spin).at_least(5).times
11
+ end
12
+
13
+ it "runs animation and executes block within context" do
14
+ context = spy('context')
15
+ spinner = TTY::Spinner.new(":title", output: output)
16
+
17
+ spinner.run("done") do
18
+ context.call
19
+ spinner.update(title: 'executing')
20
+ end
21
+
22
+ expect(context).to have_received(:call).once
23
+ end
24
+
25
+ it "yields spinner instance when block argument is provided" do
26
+ spinner = TTY::Spinner.new(":title", output: output)
27
+
28
+ expect { |job|
29
+ spinner.run("done", &job)
30
+ }.to yield_with_args(spinner)
31
+ end
32
+ end
@@ -0,0 +1,90 @@
1
+ # coding: utf-8
2
+
3
+ RSpec.describe TTY::Spinner, '#spin' do
4
+ let(:output) { StringIO.new('', 'w+') }
5
+ let(:save) { TTY::Cursor.save }
6
+ let(:restore) { TTY::Cursor.restore }
7
+
8
+ it "spins default frames" do
9
+ spinner = TTY::Spinner.new(output: output)
10
+
11
+ expect(spinner.done?).to eq(false)
12
+
13
+ 5.times { spinner.spin }
14
+ output.rewind
15
+ expect(output.read).to eq([
16
+ "\e[1G|",
17
+ "\e[1G/",
18
+ "\e[1G-",
19
+ "\e[1G\\",
20
+ "\e[1G|"
21
+ ].join)
22
+ end
23
+
24
+ it "spins chosen frame" do
25
+ spinner = TTY::Spinner.new(output: output, format: :spin)
26
+ 5.times { spinner.spin }
27
+ output.rewind
28
+ expect(output.read).to eq([
29
+ "\e[1G◴",
30
+ "\e[1G◷",
31
+ "\e[1G◶",
32
+ "\e[1G◵",
33
+ "\e[1G◴"
34
+ ].join)
35
+ end
36
+
37
+ it "spins with message" do
38
+ spinner = TTY::Spinner.new("Loading ... :spinner", output: output)
39
+ 4.times { spinner.spin }
40
+ output.rewind
41
+ expect(output.read).to eq([
42
+ "\e[1GLoading ... |",
43
+ "\e[1GLoading ... /",
44
+ "\e[1GLoading ... -",
45
+ "\e[1GLoading ... \\"
46
+ ].join)
47
+ end
48
+
49
+ it "can spin and redraw indent" do
50
+ multi_spinner = double("MultiSpinner")
51
+ allow(multi_spinner).to receive(:synchronize).and_yield
52
+ allow(multi_spinner).to receive(:next_row).and_return(1)
53
+ allow(multi_spinner).to receive(:rows).and_return(1)
54
+ allow(multi_spinner).to receive(:line_inset).and_return("--- ")
55
+
56
+ spinner = TTY::Spinner.new(output: output)
57
+ spinner.attach_to(multi_spinner)
58
+ spinner.spin
59
+ spinner.redraw_indent
60
+
61
+ output.rewind
62
+ expect(output.read).to eq([
63
+ "\e[1G--- |\n",
64
+ save,
65
+ "\e[1A",
66
+ "--- ",
67
+ restore,
68
+ ].join)
69
+ end
70
+
71
+ it "spins with many threads" do
72
+ spinner = TTY::Spinner.new(output: output)
73
+
74
+ th1 = Thread.new { 3.times { spinner.spin; sleep(0.05) } }
75
+ th2 = Thread.new { 4.times { spinner.spin; sleep(0.05) } }
76
+
77
+ [th1, th2].each(&:join)
78
+
79
+ output.rewind
80
+ expect(output.read).to eq([
81
+ "\e[1G|",
82
+ "\e[1G/",
83
+ "\e[1G-",
84
+ "\e[1G\\",
85
+ "\e[1G|",
86
+ "\e[1G/",
87
+ "\e[1G-"
88
+ ].join)
89
+ end
90
+ end
@@ -0,0 +1,64 @@
1
+ # coding: utf-8
2
+
3
+ RSpec.describe TTY::Spinner, '#stop' do
4
+ let(:output) { StringIO.new('', 'w+') }
5
+
6
+ it "doesn't reprint stop message" do
7
+ spinner = TTY::Spinner.new(output: output)
8
+ spinner.spin
9
+ 3.times { spinner.stop }
10
+ output.rewind
11
+ expect(output.read).to eq([
12
+ "\e[1G|",
13
+ "\e[0m\e[2K",
14
+ "\e[1G|\n",
15
+ ].join)
16
+ end
17
+
18
+ it "stops after 2 spins" do
19
+ spinner = TTY::Spinner.new(output: output)
20
+ 5.times do |n|
21
+ spinner.spin
22
+ spinner.stop if n == 1
23
+ end
24
+ output.rewind
25
+ expect(output.read).to eq([
26
+ "\e[1G|",
27
+ "\e[1G/",
28
+ "\e[0m\e[2K",
29
+ "\e[1G/\n"
30
+ ].join)
31
+ end
32
+
33
+ it "stops after 2 spins and prints stop message" do
34
+ spinner = TTY::Spinner.new(output: output)
35
+ 5.times do |n|
36
+ spinner.spin
37
+ spinner.stop('Done!') if n == 1
38
+ end
39
+ output.rewind
40
+ expect(output.read).to eq([
41
+ "\e[1G|",
42
+ "\e[1G/",
43
+ "\e[0m\e[2K",
44
+ "\e[1G/ Done!\n"
45
+ ].join)
46
+
47
+ expect(spinner.done?).to eq(true)
48
+ end
49
+
50
+ it "stops after 2 spins with message and prints stop message" do
51
+ spinner = TTY::Spinner.new("Loading ... :spinner", output: output)
52
+ 5.times do |n|
53
+ spinner.spin
54
+ spinner.stop('Done!') if n == 1
55
+ end
56
+ output.rewind
57
+ expect(output.read).to eq([
58
+ "\e[1GLoading ... |",
59
+ "\e[1GLoading ... /",
60
+ "\e[0m\e[2K",
61
+ "\e[1GLoading ... / Done!\n"
62
+ ].join)
63
+ end
64
+ end
@@ -0,0 +1,46 @@
1
+ # coding: utf-8
2
+
3
+ RSpec.describe TTY::Spinner, '#success' do
4
+ let(:output) { StringIO.new('', 'w+') }
5
+
6
+ it "marks spinner as success" do
7
+ spinner = TTY::Spinner.new(output: output)
8
+ 3.times { spinner.spin }
9
+ spinner.success
10
+ output.rewind
11
+ expect(output.read).to eq([
12
+ "\e[1G|",
13
+ "\e[1G/",
14
+ "\e[1G-",
15
+ "\e[0m\e[2K",
16
+ "\e[1G#{TTY::Spinner::TICK}\n"
17
+ ].join)
18
+
19
+ expect(spinner.success?).to eq(true)
20
+ end
21
+
22
+ it "marks spinner as success with message" do
23
+ spinner = TTY::Spinner.new(output: output)
24
+ 3.times { spinner.spin }
25
+ spinner.success('Successful')
26
+ output.rewind
27
+ expect(output.read).to eq([
28
+ "\e[1G|",
29
+ "\e[1G/",
30
+ "\e[1G-",
31
+ "\e[0m\e[2K",
32
+ "\e[1G#{TTY::Spinner::TICK} Successful\n"
33
+ ].join)
34
+
35
+ expect(spinner.success?).to be(true)
36
+ end
37
+
38
+ it "changes success spinner marker" do
39
+ spinner = TTY::Spinner.new(success_mark: '*', output: output)
40
+ spinner.success('(successful)')
41
+ output.rewind
42
+ expect(output.read).to eq("\e[0m\e[2K\e[1G* (successful)\n")
43
+
44
+ expect(spinner.success?).to be(true)
45
+ end
46
+ end
@@ -0,0 +1,87 @@
1
+ # encoding: utf-8
2
+
3
+ RSpec.describe TTY::Spinner, '#update' do
4
+ let(:output) { StringIO.new('', 'w+') }
5
+
6
+ it "updates message content with custom token" do
7
+ spinner = TTY::Spinner.new(":title :spinner", output: output, interval: 100)
8
+ spinner.update(title: 'task')
9
+ 5.times { spinner.spin }
10
+ spinner.stop('done')
11
+ output.rewind
12
+ expect(output.read).to eq([
13
+ "\e[1Gtask |",
14
+ "\e[1Gtask /",
15
+ "\e[1Gtask -",
16
+ "\e[1Gtask \\",
17
+ "\e[1Gtask |",
18
+ "\e[0m\e[2K",
19
+ "\e[1Gtask | done\n"
20
+ ].join)
21
+ end
22
+
23
+ it "updates message many times before stopping" do
24
+ spinner = TTY::Spinner.new(":title :spinner", output: output)
25
+
26
+ spinner.update(title: 'task_a')
27
+ 2.times { spinner.spin }
28
+ spinner.update(title: 'task_b')
29
+ 2.times { spinner.spin }
30
+ spinner.stop('done')
31
+ output.rewind
32
+
33
+ expect(output.read).to eq([
34
+ "\e[1Gtask_a |",
35
+ "\e[1Gtask_a /",
36
+ "\e[0m\e[2K\e[1G",
37
+ "\e[1Gtask_b -",
38
+ "\e[1Gtask_b \\",
39
+ "\e[0m\e[2K",
40
+ "\e[1Gtask_b \\ done\n"
41
+ ].join)
42
+ end
43
+
44
+ it "updates message after stopping" do
45
+ spinner = TTY::Spinner.new(":title :spinner", output: output)
46
+
47
+ spinner.update(title: 'task_a')
48
+ 2.times { spinner.spin }
49
+ spinner.stop('done')
50
+
51
+ spinner.start
52
+ spinner.update(title: 'task_b')
53
+ 2.times { spinner.spin }
54
+ spinner.stop('done')
55
+
56
+ output.rewind
57
+ expect(output.read).to eq([
58
+ "\e[1Gtask_a |",
59
+ "\e[1Gtask_a /",
60
+ "\e[0m\e[2K",
61
+ "\e[1Gtask_a / done\n",
62
+ "\e[1Gtask_b |",
63
+ "\e[1Gtask_b /",
64
+ "\e[0m\e[2K",
65
+ "\e[1Gtask_b / done\n"
66
+ ].join)
67
+ end
68
+
69
+ it "maintains current tokens" do
70
+ spinner = TTY::Spinner.new(":foo :bar", output: output)
71
+ expect(spinner.tokens).to eq({})
72
+
73
+ spinner.update(foo: 'FOO')
74
+ spinner.update(bar: 'BAR')
75
+
76
+ expect(spinner.tokens).to include({foo: 'FOO', bar: 'BAR'})
77
+ end
78
+
79
+ it "updates more than one token" do
80
+ spinner = TTY::Spinner.new(":foo :bar", output: output)
81
+ expect(spinner.tokens).to eq({})
82
+
83
+ spinner.update(foo: 'FOO', bar: 'BAR')
84
+
85
+ expect(spinner.tokens).to include({foo: 'FOO', bar: 'BAR'})
86
+ end
87
+ end
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+
3
+ desc 'Load gem inside irb console'
4
+ task :console do
5
+ require 'irb'
6
+ require 'irb/completion'
7
+ require_relative '../lib/tty-spinner'
8
+ ARGV.clear
9
+ IRB.start
10
+ end
11
+ task :c => :console
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+
3
+ desc 'Measure code coverage'
4
+ task :coverage do
5
+ begin
6
+ original, ENV['COVERAGE'] = ENV['COVERAGE'], 'true'
7
+ Rake::Task['spec'].invoke
8
+ ensure
9
+ ENV['COVERAGE'] = original
10
+ end
11
+ end
@@ -0,0 +1,29 @@
1
+ # encoding: utf-8
2
+
3
+ begin
4
+ require 'rspec/core/rake_task'
5
+
6
+ desc 'Run all specs'
7
+ RSpec::Core::RakeTask.new(:spec) do |task|
8
+ task.pattern = 'spec/{unit,integration}{,/*/**}/*_spec.rb'
9
+ end
10
+
11
+ namespace :spec do
12
+ desc 'Run unit specs'
13
+ RSpec::Core::RakeTask.new(:unit) do |task|
14
+ task.pattern = 'spec/unit{,/*/**}/*_spec.rb'
15
+ end
16
+
17
+ desc 'Run integration specs'
18
+ RSpec::Core::RakeTask.new(:integration) do |task|
19
+ task.pattern = 'spec/integration{,/*/**}/*_spec.rb'
20
+ end
21
+ end
22
+
23
+ rescue LoadError
24
+ %w[spec spec:unit spec:integration].each do |name|
25
+ task name do
26
+ $stderr.puts "In order to run #{name}, do `gem install rspec`"
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,27 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'tty/spinner/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'tty-spinner'
7
+ spec.version = TTY::Spinner::VERSION
8
+ spec.authors = ['Piotr Murach']
9
+ spec.email = ['pmurach@gmail.com']
10
+ spec.summary = %q{A terminal spinner for tasks that have non-deterministic time frame.}
11
+ spec.description = %q{A terminal spinner for tasks that have non-deterministic time frame.}
12
+ spec.homepage = "https://piotrmurach.github.io/tty"
13
+ spec.license = 'MIT'
14
+
15
+ spec.files = Dir['{lib,spec,examples}/**/*.rb']
16
+ spec.files += Dir['{bin,tasks}/*', 'tty-spinner.gemspec']
17
+ spec.files += Dir['README.md', 'CHANGELOG.md', 'LICENSE.txt', 'Rakefile']
18
+ spec.require_paths = ['lib']
19
+
20
+ spec.required_ruby_version = '>= 2.0.0'
21
+
22
+ spec.add_runtime_dependency 'tty-cursor', '~> 0.6.0'
23
+
24
+ spec.add_development_dependency 'bundler', '>= 1.5.0', '< 2.0'
25
+ spec.add_development_dependency 'rspec', '~> 3.1'
26
+ spec.add_development_dependency 'rake'
27
+ end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tty-spinner
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Murach
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-01-11 00:00:00.000000000 Z
11
+ date: 2018-12-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: tty-cursor
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.5.0
19
+ version: 0.6.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.5.0
26
+ version: 0.6.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -79,14 +79,67 @@ executables: []
79
79
  extensions: []
80
80
  extra_rdoc_files: []
81
81
  files:
82
+ - CHANGELOG.md
82
83
  - LICENSE.txt
83
84
  - README.md
85
+ - Rakefile
86
+ - examples/auto_spin.rb
87
+ - examples/basic.rb
88
+ - examples/clear.rb
89
+ - examples/color.rb
90
+ - examples/error.rb
91
+ - examples/formats.rb
92
+ - examples/hide_cursor.rb
93
+ - examples/multi/basic.rb
94
+ - examples/multi/basic_top_level.rb
95
+ - examples/multi/custom_style.rb
96
+ - examples/multi/files.rb
97
+ - examples/multi/jobs.rb
98
+ - examples/multi/multi.rb
99
+ - examples/multi/multi_top_level.rb
100
+ - examples/multi/pause.rb
101
+ - examples/multi/threaded.rb
102
+ - examples/pause.rb
103
+ - examples/run.rb
104
+ - examples/success.rb
105
+ - examples/threaded.rb
106
+ - examples/update.rb
84
107
  - lib/tty-spinner.rb
85
108
  - lib/tty/spinner.rb
86
109
  - lib/tty/spinner/formats.rb
87
110
  - lib/tty/spinner/multi.rb
88
111
  - lib/tty/spinner/version.rb
89
- homepage: https://github.com/piotrmurach/tty-spinner
112
+ - spec/spec_helper.rb
113
+ - spec/unit/auto_spin_spec.rb
114
+ - spec/unit/clear_spec.rb
115
+ - spec/unit/error_spec.rb
116
+ - spec/unit/events_spec.rb
117
+ - spec/unit/formats_spec.rb
118
+ - spec/unit/frames_spec.rb
119
+ - spec/unit/hide_cursor_spec.rb
120
+ - spec/unit/job_spec.rb
121
+ - spec/unit/join_spec.rb
122
+ - spec/unit/multi/auto_spin_spec.rb
123
+ - spec/unit/multi/error_spec.rb
124
+ - spec/unit/multi/line_inset_spec.rb
125
+ - spec/unit/multi/on_spec.rb
126
+ - spec/unit/multi/register_spec.rb
127
+ - spec/unit/multi/spin_spec.rb
128
+ - spec/unit/multi/stop_spec.rb
129
+ - spec/unit/multi/success_spec.rb
130
+ - spec/unit/new_spec.rb
131
+ - spec/unit/pause_spec.rb
132
+ - spec/unit/reset_spec.rb
133
+ - spec/unit/run_spec.rb
134
+ - spec/unit/spin_spec.rb
135
+ - spec/unit/stop_spec.rb
136
+ - spec/unit/success_spec.rb
137
+ - spec/unit/update_spec.rb
138
+ - tasks/console.rake
139
+ - tasks/coverage.rake
140
+ - tasks/spec.rake
141
+ - tty-spinner.gemspec
142
+ homepage: https://piotrmurach.github.io/tty
90
143
  licenses:
91
144
  - MIT
92
145
  metadata: {}
@@ -98,7 +151,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
98
151
  requirements:
99
152
  - - ">="
100
153
  - !ruby/object:Gem::Version
101
- version: '0'
154
+ version: 2.0.0
102
155
  required_rubygems_version: !ruby/object:Gem::Requirement
103
156
  requirements:
104
157
  - - ">="
@@ -106,7 +159,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
106
159
  version: '0'
107
160
  requirements: []
108
161
  rubyforge_project:
109
- rubygems_version: 2.5.1
162
+ rubygems_version: 2.7.3
110
163
  signing_key:
111
164
  specification_version: 4
112
165
  summary: A terminal spinner for tasks that have non-deterministic time frame.