tty-progressbar 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 86f9a4188616553d3453e6f8d5e35d4d3b434e7f
4
+ data.tar.gz: 57c8b9d98eca275035f392fa58d4b30b16f5c34d
5
+ SHA512:
6
+ metadata.gz: e04221654464e622d50a1dd349d65c4d557c957b8d7df1999bd6186eeb087f286221a6c0e13f0102e8af8c93fe5b7227a550e0cd790aff4c4b5d6a69d5111ea7
7
+ data.tar.gz: 4997afe3c9e855bcb433dc9209a8d41e6a9df9b560797cca911d5a066557ff5ad2fa542412a4e63c83197a9052bf26c8728275b3f59f4547897bde7088f62ee9
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.0.0
data/Gemfile ADDED
@@ -0,0 +1,16 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'rake', '~> 10.3.2'
7
+ gem 'rspec', '~> 3.1.0'
8
+ gem 'yard', '~> 0.8.7'
9
+ gem 'timecop', '~> 0.7.1'
10
+ end
11
+
12
+ group :metrics do
13
+ gem 'coveralls', '~> 0.7.0'
14
+ gem 'simplecov', '~> 0.8.2'
15
+ gem 'yardstick', '~> 0.9.9'
16
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Piotr Murach
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,157 @@
1
+ # TTY::Progressbar
2
+ [![Gem Version](https://badge.fury.io/rb/tty-progressbar.png)][gem]
3
+ [![Build Status](https://secure.travis-ci.org/peter-murach/tty-progressbar.png?branch=master)][travis]
4
+ [![Code Climate](https://codeclimate.com/github/peter-murach/tty-progressbar.png)][codeclimate]
5
+
6
+ [gem]: http://badge.fury.io/rb/tty-progressbar
7
+ [travis]: http://travis-ci.org/peter-murach/tty-progressbar
8
+ [codeclimate]: https://codeclimate.com/github/peter-murach/tty-progressbar
9
+
10
+ A flexible progress bars drawing in terminal emulators.
11
+
12
+ ## Features
13
+
14
+ * Extremly flexible progress display formatting
15
+ * Ability to define your custom format tokens
16
+ * Works on all ECMA-48 compatible terminals
17
+
18
+ ## Installation
19
+
20
+ Add this line to your application's Gemfile:
21
+
22
+ ```ruby
23
+ gem 'tty-progressbar'
24
+ ```
25
+
26
+ And then execute:
27
+
28
+ $ bundle
29
+
30
+ Or install it yourself as:
31
+
32
+ $ gem install tty-progressbar
33
+
34
+ ## Contents
35
+
36
+ * [1. Usage](#1-usage)
37
+ * [1.1 advance](#11-advance)
38
+ * [1.1 finish](#12-finish)
39
+ * [2. Configuration](#2-configuration)
40
+ * [3. Formatting](#3-formatting)
41
+ * [3.1 Tokens](#31-tokens)
42
+ * [3.2 Custom Formatter](#31-custom-formatter)
43
+
44
+ ## 1. Usage
45
+
46
+ **TTY::ProgressBar** requires only format string and total number of steps to completion. Once initialized, use `advance` method to indicated the progress like so:
47
+
48
+ ```ruby
49
+ bar = TTY::ProgressBar.new("downloading [:bar]", total: 30)
50
+ 30.times do
51
+ sleep(0.1)
52
+ bar.advance(1)
53
+ end
54
+ ```
55
+
56
+ This would produce anmiation in your terminal:
57
+
58
+ ```ruby
59
+ downloading [======================= ]
60
+ ```
61
+
62
+ ### 1.1 advance
63
+
64
+ Once you have **ProgressBar** instance, you can progress the display by calling `advance` method. By default it will increase by `1` but you can pass any number of steps, for instance, when used to advance number of bytes of downloaded file.
65
+
66
+ ```ruby
67
+ bar.advance(1000)
68
+ ```
69
+
70
+ ### 1.2 finish
71
+
72
+ In order to immediately stop and finish the bar call `finish`. This will finish drawing the progress and return to new line.
73
+
74
+ ```ruby
75
+ bar.finish
76
+ ```
77
+
78
+ ## 2. Configuration
79
+
80
+ There are number of configuration options that can be provided:
81
+
82
+ * `total` total number of steps to completion
83
+ * `width` for the bars display including formatting options defaulting to total
84
+ * `complete` completion character by default `=`
85
+ * `incomplete` incomplete character by default single space
86
+ * `output` the output stream defaulting to `stderr`
87
+ * `frequency` used to throttle the output, by default `false`
88
+ * `hide_cursor` to hide display cursor defaulting to `false`
89
+
90
+ ## 3. Formatting
91
+
92
+ Every **TTY::ProgressBar** instance requires a format string, which apart from regular characters accepts special tokens to display dynamic information. For instance, a format to measure download progress could be:
93
+
94
+ ```ruby
95
+ "downloading [:bar] :elapsed :percent"
96
+ ```
97
+
98
+ ### 3.1 Tokens
99
+
100
+ These are the tokens that are currently supported:
101
+
102
+ * `:bar` the progress bar
103
+ * `:current` the current progress number
104
+ * `:total` the total progress number
105
+ * `:percent` the completion percentage
106
+ * `:elapsed` the elapsed time in seconds
107
+
108
+ ### 3.2 Custom formatter
109
+
110
+ If the provided tokens do not meet your needs, you can instrument formatting pipeline to use a custome formatter.
111
+
112
+ For example, begin by creating custom formatter called `TimeFormatter` that will dynamicly update `:time` token in format string as follows:
113
+
114
+ ```
115
+ class TimeFormatter
116
+ def initialize(progress)
117
+ @progress = progress
118
+ end
119
+
120
+ def format(value)
121
+ transformed = transform(value)
122
+ value.gsub(/:time/, transformed.to_s) # => :time token
123
+ end
124
+
125
+ private
126
+
127
+ def transfrom
128
+ value * (Time.now - @progress.start_at).to_i
129
+ end
130
+ end
131
+ ```
132
+
133
+ Notice that you have access to all the configuration options inside the formatter by simply invoking them on the `@progress` instance.
134
+
135
+ Create **TTY::ProgressBar** instance with new token:
136
+
137
+ ```ruby
138
+ bar = TTY::ProgressBar.new(":time", total: 30)
139
+ ```
140
+
141
+ Then add `TimeFormatter` to the pipeline like so:
142
+
143
+ ```ruby
144
+ bar.use TimeFormatter
145
+ ```
146
+
147
+ ## Contributing
148
+
149
+ 1. Fork it ( https://github.com/peter-murach/tty-progressbar/fork )
150
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
151
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
152
+ 4. Push to the branch (`git push origin my-new-feature`)
153
+ 5. Create a new Pull Request
154
+
155
+ ## Copyright
156
+
157
+ Copyright (c) 2014 Piotr Murach. See LICENSE for further details.
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # encoding: utf-8
2
+
3
+ require "bundler/gem_tasks"
4
+
5
+ FileList['tasks/**/*.rake'].each(&method(:import))
6
+
7
+ desc 'Run all specs'
8
+ task ci: %w[ spec ]
@@ -0,0 +1,7 @@
1
+ require'tty-progressbar'
2
+
3
+ bar = TTY::ProgressBar.new("downloading [:bar] :elapsed :percent", total: 30)
4
+ 30.times do
5
+ sleep(0.1)
6
+ bar.advance
7
+ end
@@ -0,0 +1,34 @@
1
+ # coding: utf-8
2
+
3
+ module TTY
4
+ class ProgressBar
5
+ # Used by {Pipeline} to format bar
6
+ #
7
+ # @api private
8
+ class BarFormatter
9
+ def initialize(progress, *args, &block)
10
+ @progress = progress
11
+ end
12
+
13
+ # Format :bar token
14
+ #
15
+ # @param [String] value
16
+ # the value being formatted
17
+ #
18
+ # @api public
19
+ def format(value)
20
+ available_space = [0, @progress.max_columns - value.gsub(/:bar/, '').length].max
21
+ width = [@progress.width, available_space].min
22
+ complete_length = (width * @progress.ratio).round
23
+ complete = Array.new(complete_length, @progress.complete)
24
+ incomplete = Array.new(width - complete_length, @progress.incomplete)
25
+
26
+ bar = ''
27
+ bar += complete.join
28
+ bar += incomplete.join
29
+
30
+ value.gsub(/:bar/, bar)
31
+ end
32
+ end # BarFormatter
33
+ end # ProgressBar
34
+ end # TTY
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+
3
+ module TTY
4
+ class ProgressBar
5
+ # Responsible for converting values to different formats
6
+ #
7
+ # @api public
8
+ class Converter
9
+ def to_time(seconds)
10
+ hours = (seconds / 3600.to_f).floor
11
+ seconds -= hours * 3600
12
+ minutes = (seconds / 60).floor
13
+ seconds -= minutes * 60
14
+
15
+ if hours > 99
16
+ sprintf('%dh', hours)
17
+ elsif hours > 0
18
+ sprintf('%2dh%2dm', hours, minutes)
19
+ elsif minutes > 0
20
+ sprintf('%2dm%2ds', minutes, seconds)
21
+ else
22
+ sprintf('%2ds', seconds)
23
+ end
24
+ end
25
+ end # Converter
26
+ end # ProgressBar
27
+ end # TTY
@@ -0,0 +1,21 @@
1
+ # coding: utf-8
2
+
3
+ module TTY
4
+ class ProgressBar
5
+ class CurrentFormatter
6
+ def initialize(progress, *args, &block)
7
+ @progress = progress
8
+ end
9
+
10
+ # Format :current token
11
+ #
12
+ # @param [String] value
13
+ # the value being formatted
14
+ #
15
+ # @api public
16
+ def format(value)
17
+ value.gsub(/:current/, @progress.current.to_s)
18
+ end
19
+ end # CurrentFormatter
20
+ end # ProgressBar
21
+ end # TTY
@@ -0,0 +1,17 @@
1
+ # coding: utf-8
2
+
3
+ module TTY
4
+ class ProgressBar
5
+ class ElapsedFormatter
6
+ def initialize(progress, *args, &block)
7
+ @progress = progress
8
+ @converter = TTY::ProgressBar::Converter.new
9
+ end
10
+
11
+ def format(value)
12
+ elapsed = (Time.now - @progress.start_at)
13
+ value.gsub(/:elapsed/, @converter.to_time(elapsed))
14
+ end
15
+ end # ElapsedFormatter
16
+ end # ProgressBar
17
+ end # TTY
@@ -0,0 +1,16 @@
1
+ # coding: utf-8
2
+
3
+ module TTY
4
+ class ProgressBar
5
+ class PercentFormatter
6
+ def initialize(progress, *args, &block)
7
+ @progress = progress
8
+ end
9
+
10
+ def format(value)
11
+ percent = @progress.width == 0 ? 100 : (@progress.ratio * 100).to_i
12
+ value.gsub(/:percent/, percent.to_s + '%')
13
+ end
14
+ end # PercentFormatter
15
+ end # ProgressBar
16
+ end # TTY
@@ -0,0 +1,41 @@
1
+ # coding: utf-8
2
+
3
+ module TTY
4
+ class ProgressBar
5
+ # Used by {ProgressBar} to decorate format string
6
+ #
7
+ # @api private
8
+ class Pipeline
9
+ include Enumerable
10
+
11
+ def initialize(formatters = [])
12
+ @formatters = formatters
13
+ end
14
+
15
+ # Add new formatter
16
+ #
17
+ # @ api public
18
+ def use(formatter, *args, &block)
19
+ formatters << proc { |progress| formatter.new(progress, *args, &block) }
20
+ end
21
+
22
+ def decorate(progress, tokenized)
23
+ base = tokenized.dup
24
+ formatters.inject(base) do |formatted, formatter|
25
+ formatter.call(progress).format(formatted)
26
+ end
27
+ end
28
+
29
+ # Iterate over formatters
30
+ #
31
+ # @api public
32
+ def each(&block)
33
+ formatters.each(&block)
34
+ end
35
+
36
+ protected
37
+
38
+ attr_reader :formatters
39
+ end # Pipeline
40
+ end # ProgressBar
41
+ end # TTY
@@ -0,0 +1,15 @@
1
+ # coding: utf-8
2
+
3
+ module TTY
4
+ class ProgressBar
5
+ class TotalFormatter
6
+ def initialize(progress, *args, &block)
7
+ @progress = progress
8
+ end
9
+
10
+ def format(value)
11
+ value.gsub(/:total/, @progress.total.to_s)
12
+ end
13
+ end # TotalFormatter
14
+ end # ProgressBar
15
+ end # TTY
@@ -0,0 +1,7 @@
1
+ # coding: utf-8
2
+
3
+ module TTY
4
+ class ProgressBar
5
+ VERSION = "0.1.0"
6
+ end # ProgressBar
7
+ end # TTY
@@ -0,0 +1,230 @@
1
+ # coding: utf-8
2
+
3
+ require 'io/console'
4
+ require 'forwardable'
5
+
6
+ require 'tty/progressbar/converter'
7
+ require 'tty/progressbar/version'
8
+ require 'tty/progressbar/pipeline'
9
+ require 'tty/progressbar/bar_formatter'
10
+ require 'tty/progressbar/current_formatter'
11
+ require 'tty/progressbar/elapsed_formatter'
12
+ require 'tty/progressbar/percent_formatter'
13
+ require 'tty/progressbar/total_formatter'
14
+
15
+ module TTY
16
+ # Used for creating terminal progress bar
17
+ #
18
+ # @api public
19
+ class ProgressBar
20
+ extend Forwardable
21
+
22
+ ECMA_ESC = "\x1b"
23
+ ECMA_CSI = "\x1b["
24
+ ECMA_CHA = 'G'
25
+
26
+ DEC_RST = 'l'
27
+ DEC_SET = 'h'
28
+ DEC_TCEM = '?25'
29
+
30
+ attr_reader :format
31
+
32
+ attr_reader :total
33
+
34
+ attr_reader :width
35
+
36
+ attr_reader :no_width
37
+
38
+ attr_reader :current
39
+
40
+ attr_reader :start_at
41
+
42
+ attr_reader :complete
43
+
44
+ attr_reader :incomplete
45
+
46
+ attr_reader :hide_cursor
47
+
48
+ def_delegator :@pipeline, :use
49
+
50
+ # Create progress bar
51
+ #
52
+ # @param [String] format
53
+ # the tokenized string that displays the output
54
+ #
55
+ # @param [Hash] options
56
+ # @option options [Numeric] :total
57
+ # the total number of steps to completion
58
+ # @option options [Numeric] :width
59
+ # the maximum width for the bars display including
60
+ # all formatting options
61
+ # @option options [Boolean] :no_width
62
+ # true when progression is unknown defaulting to false
63
+ # @option options [Boolean] :clear
64
+ # whether or not to clear the progress line
65
+ # @option options [Boolean] :hide_cursor
66
+ # display or hide cursor
67
+ # @option options [Object] :output
68
+ # the object that responds to print call defaulting to stderr
69
+ # @option options [Number] :frequency
70
+ # the frequency with which to display bars
71
+ #
72
+ # @api public
73
+ def initialize(format, options = {})
74
+ @format = format
75
+ @total = options.fetch(:total) { fail ArgumentError }
76
+ @width = options.fetch(:width) { @total }
77
+ @no_width = options.fetch(:no_width) { false }
78
+ @clear = options.fetch(:clear) { false }
79
+ @incomplete = options.fetch(:incomplete) { ' ' }
80
+ @complete = options.fetch(:complete) { '=' }
81
+ @hide_cursor = options.fetch(:hide_cursor) { false }
82
+ @output = options.fetch(:output) { $stderr }
83
+ @frequency = options.fetch(:frequency) { 0 } # 0Hz
84
+
85
+ @width = 0 if @no_width
86
+ @render_period = @frequency == 0 ? 0 : 1.0 / @frequency
87
+ @current = 0
88
+ @readings = 0
89
+ @last_render_time = Time.now
90
+ @last_render_width = 0
91
+ @done = false
92
+ @pipeline = TTY::ProgressBar::Pipeline.new
93
+
94
+ default_pipeline
95
+ register_callbacks
96
+ end
97
+
98
+ # Advance the progress bar
99
+ #
100
+ # @param [Object|Number] progress
101
+ #
102
+ # @api public
103
+ def advance(progress = 1)
104
+ return if @done
105
+
106
+ @start_at = Time.now if @current.zero?
107
+ @readings += 1
108
+ @current += progress
109
+
110
+ if !no_width && @current >= total
111
+ finish && return
112
+ end
113
+
114
+ now = Time.now
115
+ return if (now - @last_render_time) < @render_period
116
+ render
117
+ end
118
+
119
+ # Ratio of completed over total steps
120
+ #
121
+ # @return [Float]
122
+ #
123
+ # @api public
124
+ def ratio
125
+ proportion = (@current.to_f / @total)
126
+ [[proportion, 0].max, 1].min
127
+ end
128
+
129
+ # Determine terminal width
130
+ #
131
+ # @api public
132
+ def max_columns
133
+ IO.console.winsize.last
134
+ end
135
+
136
+ # Render progress to the output
137
+ #
138
+ # @api private
139
+ def render
140
+ return if @done
141
+ now = Time.now
142
+
143
+ if @hide_cursor && @last_render_time == 0
144
+ write(ECMA_CSI + DEC_RST + DEC_TCEM)
145
+ end
146
+
147
+ # Setup formatting values
148
+ percent = width == 0 ? 100 : (ratio * 100).to_i
149
+ elapsed = (now - @start_at) * 1000.0
150
+ estimated = (percent == 100) ? 0 : elapsed * (total / @current - 1)
151
+
152
+ formatted = @pipeline.decorate(self, @format)
153
+ write(formatted, true)
154
+
155
+ @last_render_time = Time.now
156
+ @last_render_width = formatted.length
157
+ end
158
+
159
+ # Write out to the output
160
+ #
161
+ # @param [String] data
162
+ #
163
+ # @api private
164
+ def write(data, clear_first = false)
165
+ @output.print(ECMA_CSI + '1' + ECMA_CHA) if clear_first
166
+ @output.print(data)
167
+ @output.flush
168
+ end
169
+
170
+ # Resize progress bar with new configuration
171
+ #
172
+ # @api public
173
+ def resize(new_width)
174
+ fail 'Cannot resize finished progress bar' if @done
175
+
176
+ if new_width
177
+ @no_width = false
178
+ @width = new_width
179
+ else
180
+ @no_width = true
181
+ @width = 0
182
+ end
183
+
184
+ advance(0) # rerender with new configuration
185
+ end
186
+
187
+ # End the progress
188
+ #
189
+ # @api public
190
+ def finish
191
+ # reenable cursor if it is turned off
192
+ write(ECMA_CSI + DEC_RST + DEC_TCEM, false) if @hide_cursor
193
+ return if @done
194
+ @current = @width if @no_width
195
+ render
196
+ write("\n", false)
197
+ @done = true
198
+ end
199
+
200
+ # Terminates the progress bar
201
+ #
202
+ # @api public
203
+ def terminate
204
+ @done = true
205
+ end
206
+
207
+ private
208
+
209
+ # Prepare default pipeline formatters
210
+ #
211
+ # @api private
212
+ def default_pipeline
213
+ @pipeline.use TTY::ProgressBar::CurrentFormatter
214
+ @pipeline.use TTY::ProgressBar::TotalFormatter
215
+ @pipeline.use TTY::ProgressBar::ElapsedFormatter
216
+ @pipeline.use TTY::ProgressBar::PercentFormatter
217
+ @pipeline.use TTY::ProgressBar::BarFormatter
218
+ end
219
+
220
+ # Handle resize and kill signals
221
+ #
222
+ # @api private
223
+ def register_callbacks
224
+ callback = proc { send(:resize, max_columns) }
225
+ Signal.trap('SIGWINCH', &callback)
226
+
227
+ Signal.trap('KILL') { @terminate }
228
+ end
229
+ end # ProgressBar
230
+ end # TTY
@@ -0,0 +1 @@
1
+ require 'tty/progressbar'
@@ -0,0 +1,31 @@
1
+ # encoding: utf-8
2
+
3
+ require 'timecop'
4
+ require 'tty-progressbar'
5
+
6
+ RSpec.configure do |config|
7
+ config.expect_with :rspec do |expectations|
8
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
9
+ end
10
+
11
+ config.mock_with :rspec do |mocks|
12
+ mocks.verify_partial_doubles = true
13
+ end
14
+
15
+ # Limits the available syntax to the non-monkey patched syntax that is recommended.
16
+ config.disable_monkey_patching!
17
+
18
+ # This setting enables warnings. It's recommended, but in some cases may
19
+ # be too noisy due to issues in dependencies.
20
+ config.warnings = true
21
+
22
+ if config.files_to_run.one?
23
+ config.default_formatter = 'doc'
24
+ end
25
+
26
+ config.profile_examples = 2
27
+
28
+ config.order = :random
29
+
30
+ Kernel.srand config.seed
31
+ end
@@ -0,0 +1,20 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe TTY::ProgressBar, 'bar' do
6
+ let(:output) { StringIO.new('', 'w+') }
7
+
8
+ it "animates bar" do
9
+ progress = TTY::ProgressBar.new("[:bar]", output: output, total: 5)
10
+ 5.times { progress.advance }
11
+ output.rewind
12
+ expect(output.read).to eq([
13
+ "\e[1G[= ]",
14
+ "\e[1G[== ]",
15
+ "\e[1G[=== ]",
16
+ "\e[1G[==== ]",
17
+ "\e[1G[=====]\n"
18
+ ].join)
19
+ end
20
+ end
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe TTY::ProgressBar::Converter, '.to_time' do
6
+ subject(:converter) { described_class.new }
7
+
8
+ it "converts seconds to seconds" do
9
+ expect(converter.to_time(15)).to eq("15s")
10
+ end
11
+
12
+ it "converts seconds to minutes" do
13
+ expect(converter.to_time(100)).to eq(" 1m40s")
14
+ end
15
+
16
+ it "converts seconds to small hours" do
17
+ expect(converter.to_time(3600)).to eq(" 1h 0m")
18
+ end
19
+
20
+ it "converts secodns to hours" do
21
+ expect(converter.to_time(100 * 3600)).to eq("100h")
22
+ end
23
+ end
@@ -0,0 +1,18 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe TTY::ProgressBar, 'current' do
6
+ let(:output) { StringIO.new('', 'w+') }
7
+
8
+ it "displays current value" do
9
+ progress = TTY::ProgressBar.new("|:current|", output: output, total: 10)
10
+ 3.times { progress.advance }
11
+ output.rewind
12
+ expect(output.read).to eq([
13
+ "\e[1G|1|",
14
+ "\e[1G|2|",
15
+ "\e[1G|3|"
16
+ ].join)
17
+ end
18
+ end
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe TTY::ProgressBar, 'custom' do
6
+ let(:output) { StringIO.new('', 'w+') }
7
+
8
+ it "allows for custom tag" do
9
+ progress = TTY::ProgressBar.new(":hi", output: output, total: 10)
10
+
11
+ HiFormatter = Class.new do
12
+ def initialize(progress)
13
+ @progress = progress
14
+ end
15
+
16
+ def format(value)
17
+ value.gsub(/:hi/, "Hello")
18
+ end
19
+ end
20
+
21
+ progress.use(HiFormatter)
22
+ progress.advance
23
+ output.rewind
24
+ expect(output.read).to eq("\e[1GHello")
25
+ end
26
+ end
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe TTY::ProgressBar, '.new' do
6
+ let(:output) { StringIO.new('', 'w+') }
7
+
8
+ before { Timecop.safe_mode = false }
9
+
10
+ it "displays elapsed time" do
11
+ time_now = Time.local(2014, 10, 5, 12, 0, 0)
12
+ Timecop.freeze(time_now)
13
+ progress = TTY::ProgressBar.new(":elapsed", output: output, total: 10)
14
+
15
+ 5.times do |sec|
16
+ time_now = Time.local(2014, 10, 5, 12, 0, sec)
17
+ Timecop.freeze(time_now)
18
+ progress.advance
19
+ end
20
+
21
+ output.rewind
22
+ expect(output.read).to eq([
23
+ "\e[1G 0s",
24
+ "\e[1G 1s",
25
+ "\e[1G 2s",
26
+ "\e[1G 3s",
27
+ "\e[1G 4s"
28
+ ].join)
29
+ Timecop.return
30
+ end
31
+ end
@@ -0,0 +1,52 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe TTY::ProgressBar, '.new' do
6
+ let(:output) { StringIO.new('', 'w+') }
7
+
8
+ it "displays output where width == total" do
9
+ progress = TTY::ProgressBar.new("[:bar]", output: output, total: 10)
10
+ progress.advance
11
+ output.rewind
12
+ expect(output.read).to eq("\e[1G[= ]")
13
+ end
14
+
15
+ it "displays output where width > total" do
16
+ progress = TTY::ProgressBar.new("[:bar]", output: output, total: 5, width: 10)
17
+ 5.times { progress.advance }
18
+ output.rewind
19
+ expect(output.read).to eq([
20
+ "\e[1G[== ]",
21
+ "\e[1G[==== ]",
22
+ "\e[1G[====== ]",
23
+ "\e[1G[======== ]",
24
+ "\e[1G[==========]\n"
25
+ ].join)
26
+ end
27
+
28
+ it "displays output where width < total" do
29
+ progress = TTY::ProgressBar.new("[:bar]", output: output, total: 10, width: 5)
30
+ 10.times { progress.advance }
31
+ output.rewind
32
+ expect(output.read).to eq([
33
+ "\e[1G[= ]",
34
+ "\e[1G[= ]",
35
+ "\e[1G[== ]",
36
+ "\e[1G[== ]",
37
+ "\e[1G[=== ]",
38
+ "\e[1G[=== ]",
39
+ "\e[1G[==== ]",
40
+ "\e[1G[==== ]",
41
+ "\e[1G[=====]",
42
+ "\e[1G[=====]\n"
43
+ ].join)
44
+ end
45
+
46
+ it "displays total value" do
47
+ progress = TTY::ProgressBar.new("|:total|", output: output, total: 10)
48
+ progress.advance(3)
49
+ output.rewind
50
+ expect(output.read).to eq("\e[1G|10|")
51
+ end
52
+ end
@@ -0,0 +1,20 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe TTY::ProgressBar, 'percent' do
6
+ let(:output) { StringIO.new('', 'w+') }
7
+
8
+ it "displays percent finished" do
9
+ progress = TTY::ProgressBar.new(":percent", output: output, total: 5)
10
+ 5.times { progress.advance }
11
+ output.rewind
12
+ expect(output.read).to eq([
13
+ "\e[1G20%",
14
+ "\e[1G40%",
15
+ "\e[1G60%",
16
+ "\e[1G80%",
17
+ "\e[1G100%\n"
18
+ ].join)
19
+ end
20
+ end
@@ -0,0 +1,15 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe TTY::ProgressBar::Pipeline, '.decorate' do
6
+ subject(:pipeline) { described_class.new }
7
+
8
+ it "decorates tokenized string with pipeline formatters" do
9
+ pipeline.use TTY::ProgressBar::CurrentFormatter
10
+ pipeline.use TTY::ProgressBar::TotalFormatter
11
+ progress_bar = double(current: '3', total: '10')
12
+ tokenized = "[:current/:total]"
13
+ expect(pipeline.decorate(progress_bar, tokenized)).to eq("[3/10]")
14
+ end
15
+ end
@@ -0,0 +1,10 @@
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 File.join(__FILE__, '../../lib/tty-progresbar')
8
+ ARGV.clear
9
+ IRB.start
10
+ end
@@ -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
data/tasks/spec.rake ADDED
@@ -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,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'tty/progressbar/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "tty-progressbar"
8
+ spec.version = TTY::ProgressBar::VERSION
9
+ spec.authors = ["Piotr Murach"]
10
+ spec.email = [""]
11
+ spec.summary = %q{A flexible progress bars drawing in terminal emulators.}
12
+ spec.description = %q{A flexible progress bars drawing in terminal emulators.}
13
+ spec.homepage = "https://github.com/peter-murach/tty-progressbar"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ end
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tty-progressbar
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Piotr Murach
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-11-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: A flexible progress bars drawing in terminal emulators.
42
+ email:
43
+ - ''
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - .gitignore
49
+ - .rspec
50
+ - .ruby-version
51
+ - Gemfile
52
+ - LICENSE.txt
53
+ - README.md
54
+ - Rakefile
55
+ - examples/simple.rb
56
+ - lib/tty-progressbar.rb
57
+ - lib/tty/progressbar.rb
58
+ - lib/tty/progressbar/bar_formatter.rb
59
+ - lib/tty/progressbar/converter.rb
60
+ - lib/tty/progressbar/current_formatter.rb
61
+ - lib/tty/progressbar/elapsed_formatter.rb
62
+ - lib/tty/progressbar/percent_formatter.rb
63
+ - lib/tty/progressbar/pipeline.rb
64
+ - lib/tty/progressbar/total_formatter.rb
65
+ - lib/tty/progressbar/version.rb
66
+ - spec/spec_helper.rb
67
+ - spec/unit/bar_formatter_spec.rb
68
+ - spec/unit/converter_spec.rb
69
+ - spec/unit/current_formatter_spec.rb
70
+ - spec/unit/custom_formatter_spec.rb
71
+ - spec/unit/elapsed_formatter_spec.rb
72
+ - spec/unit/new_spec.rb
73
+ - spec/unit/percent_formatter_spec.rb
74
+ - spec/unit/pipeline_spec.rb
75
+ - tasks/console.rake
76
+ - tasks/coverage.rake
77
+ - tasks/spec.rake
78
+ - tty-progressbar.gemspec
79
+ homepage: https://github.com/peter-murach/tty-progressbar
80
+ licenses:
81
+ - MIT
82
+ metadata: {}
83
+ post_install_message:
84
+ rdoc_options: []
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - '>='
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ requirements: []
98
+ rubyforge_project:
99
+ rubygems_version: 2.0.3
100
+ signing_key:
101
+ specification_version: 4
102
+ summary: A flexible progress bars drawing in terminal emulators.
103
+ test_files:
104
+ - spec/spec_helper.rb
105
+ - spec/unit/bar_formatter_spec.rb
106
+ - spec/unit/converter_spec.rb
107
+ - spec/unit/current_formatter_spec.rb
108
+ - spec/unit/custom_formatter_spec.rb
109
+ - spec/unit/elapsed_formatter_spec.rb
110
+ - spec/unit/new_spec.rb
111
+ - spec/unit/percent_formatter_spec.rb
112
+ - spec/unit/pipeline_spec.rb
113
+ has_rdoc: