tty-progressbar 0.14.0 → 0.15.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b9e021f67756883c39075abe088ad0861ef85582
4
- data.tar.gz: 08b1cd0a9925899b0a7c6ace9dddeef1a1545953
3
+ metadata.gz: c2470861861ae00abd4f276cede9731c712d2508
4
+ data.tar.gz: 38d29289ddfd613781defa037dc1181654ef7a3a
5
5
  SHA512:
6
- metadata.gz: 7719a9ffa8814c51e301dd5e441a4516e87230ee7f66780ba40c3b29556bdd086f5dc18b6ee024b2b54b1344bb52996c51048837bafffcc560164c4b44165f0e
7
- data.tar.gz: 98974cccbbad3174dcbf24dfd66957db87aca29f79ba94f4f287c6fff789251130a042c6e2ed8ae9831ea1be95380f433c3b14093a9ae01b282d4a4331f0ef97
6
+ metadata.gz: 1e2e6a01da4dcb082e8e55e1ecfc18841dd42a1cf1a2d622aa6d081d13f112a9f28fa4ef32cec33ffa68f50578a979eb3e4398f28145ac7204114a18a4145eaa
7
+ data.tar.gz: 5226faf2809e8939088d0d9ab4b91f391c687bc7e92149df9b13d0fbd6a7ea0a7a337863d9c1c54a59a6cbe92088605b0e915f6c7640d4b88d9e32b71fb6111a
@@ -7,9 +7,10 @@ script: "bundle exec rake ci"
7
7
  rvm:
8
8
  - 2.0.0
9
9
  - 2.1.10
10
- - 2.2.8
10
+ - 2.2.9
11
11
  - 2.3.6
12
- - 2.4.3
12
+ - 2.4.4
13
+ - 2.5.1
13
14
  - ruby-head
14
15
  - jruby-9.1.5.0
15
16
  - jruby-head
@@ -1,6 +1,25 @@
1
1
  # Change log
2
2
 
3
- ## [v0.14.0] - 2017-01-17
3
+ ## [v0.15.0] - 2018-06-24
4
+
5
+ ### Added
6
+ * Add #format= for overriding formatting string
7
+ * Add #display_columns for determining display width of multibyte characters
8
+ * Add :inset option to bar configuration options
9
+ * Add ability to configure width for multi bar with top level bar
10
+ * Add unicode-display_width dependency
11
+
12
+ ### Changed
13
+ * Change #update to only set configuration if actually present
14
+ * Change bar formatter to handle multibyte characters
15
+
16
+ ### Fixed
17
+ * Fix to stop reseting multibar state when registered bar reset by Eric Hodel(@drbrain)
18
+ * Fix rendered bar to pad formatted output when it gets shorter by Eric Hodel(@drbrain)
19
+ * Fix multi bar to advance in steps matching each bar advance progress
20
+ * Fix multi bar rendering for widths exceeding screen columns count
21
+
22
+ ## [v0.14.0] - 2018-01-17
4
23
 
5
24
  ### Changed
6
25
  * Change to only output to a console and stop output to a file, pipe etc...
@@ -160,6 +179,7 @@
160
179
 
161
180
  * Initial implementation and release
162
181
 
182
+ [v0.15.0]: https://github.com/peter-murach/tty-progressbar/compare/v0.14.0...v0.15.0
163
183
  [v0.14.0]: https://github.com/peter-murach/tty-progressbar/compare/v0.13.0...v0.14.0
164
184
  [v0.13.0]: https://github.com/peter-murach/tty-progressbar/compare/v0.12.2...v0.13.0
165
185
  [v0.12.2]: https://github.com/peter-murach/tty-progressbar/compare/v0.12.1...v0.12.2
data/README.md CHANGED
@@ -26,6 +26,7 @@
26
26
  * Includes many predefined tokens to calculate ETA, Bytes ... [tokens](#41-tokens)
27
27
  * Allows to define your [custom tokens](#42-custom-formatters)
28
28
  * Supports parallel multi progress bars [multi](#6-ttyprogressbarmulti-api)
29
+ * Handles Unicode characters in progress bar [unicode](#44-unicode)
29
30
  * Works on all ECMA-48 compatible terminals
30
31
 
31
32
  ## Installation
@@ -70,6 +71,7 @@ Or install it yourself as:
70
71
  * [4.1 Tokens](#41-tokens)
71
72
  * [4.2 Custom Formatters](#42-custom-formatters)
72
73
  * [4.3 Custom Tokens](#43-custom-tokens)
74
+ * [4.4 Unicode](#44-unicode)
73
75
  * [5. Logging](#5-logging)
74
76
  * [6. TTY::ProgressBar::Multi API](#6-ttyprogressbarmulti-api)
75
77
  * [6.1 new](#61-new)
@@ -302,10 +304,10 @@ trap(:WINCH) { bar.resize }
302
304
 
303
305
  The progress bar fires events when it is progressing, stopped or finished. You can register to listen for events using the `on` message.
304
306
 
305
- Every time an `advance` is called the `:progress` event gets fired which you can listen for:
307
+ Every time an `advance` is called the `:progress` event gets fired which you can listen for inside a block which includes the actual amount of progress as a first yielded argument:
306
308
 
307
309
  ```ruby
308
- bar.on(:progress) { ... }
310
+ bar.on(:progress) { |amount| ... }
309
311
  ```
310
312
 
311
313
  When the progress bar finishes and completes then the `:done` event is fired. You can listen for this event:
@@ -474,6 +476,26 @@ which outputs:
474
476
  (4) Bye Piotr!
475
477
  ```
476
478
 
479
+ ### 4.4 Unicode
480
+
481
+ The format string as well as `:complete`, `:head` and `:incompelte` configuration options can contain Unicode characters that aren't monospaced.
482
+
483
+ For example, you can specify complete bar progression character to be Unicode non-monospaced:
484
+
485
+ ```ruby
486
+ bar = TTY::ProgressBar.new("Unicode [:bar]", total: 30, complete: 'あ')
487
+ #
488
+ # => Unicode [あああああああああああああああ]
489
+ ```
490
+
491
+ Similarly, the formatted string can include Unicode characters:
492
+
493
+ ```ruby
494
+ bar = TTY::ProgressBar.new("あめかんむり[:bar]", total: 20)
495
+ #
496
+ # => あめかんむり[== ]
497
+ ```
498
+
477
499
  ## 5. Logging
478
500
 
479
501
  If you want to print messages out to terminal along with the progress bar use the `log` method. The messages will appear above the progress bar and will continue scrolling up as more are logged out.
@@ -19,3 +19,5 @@ environment:
19
19
  - ruby_version: "23-x64"
20
20
  - ruby_version: "24"
21
21
  - ruby_version: "24-x64"
22
+ - ruby_version: "25"
23
+ - ruby_version: "25-x64"
@@ -0,0 +1,13 @@
1
+ require_relative '../../lib/tty-progressbar'
2
+
3
+ bars = TTY::ProgressBar::Multi.new("main [:bar] :percent")
4
+
5
+ bar1 = bars.register "foo [:bar] :percent", total: 150
6
+ bar2 = bars.register "bar [:bar] :percent", total: 250
7
+ bar3 = bars.register "baz [:bar] :percent", total: 100
8
+
9
+ th1 = Thread.new { 15.times { sleep(0.1); bar1.advance(10) } }
10
+ th2 = Thread.new { 50.times { sleep(0.1); bar2.advance(5)} }
11
+ th3 = Thread.new { 50.times { sleep(0.1); bar3.advance(5) } }
12
+
13
+ [th1, th2, th3].each(&:join)
@@ -0,0 +1,7 @@
1
+ require_relative '../lib/tty-progressbar'
2
+
3
+ bar = TTY::ProgressBar.new("Unicode [:bar]", total: 30, complete: 'あ')
4
+ 30.times do
5
+ sleep(0.1)
6
+ bar.advance
7
+ end
@@ -5,6 +5,7 @@ require 'forwardable'
5
5
  require 'monitor'
6
6
  require 'tty-cursor'
7
7
  require 'tty-screen'
8
+ require 'unicode/display_width'
8
9
 
9
10
  require_relative 'progressbar/configuration'
10
11
  require_relative 'progressbar/formatter'
@@ -23,7 +24,7 @@ module TTY
23
24
 
24
25
  CURSOR_LOCK = Monitor.new
25
26
 
26
- attr_reader :format
27
+ attr_accessor :format
27
28
 
28
29
  attr_reader :current
29
30
 
@@ -33,12 +34,33 @@ module TTY
33
34
 
34
35
  def_delegators :@configuration, :total, :width, :no_width,
35
36
  :complete, :incomplete, :head, :hide_cursor, :clear,
36
- :output, :frequency, :interval, :width=
37
+ :output, :frequency, :interval, :inset, :width=
37
38
 
38
39
  def_delegators :@meter, :rate, :mean_rate
39
40
 
40
41
  def_delegator :@formatter, :use
41
42
 
43
+ # Determine terminal width
44
+ #
45
+ # @return [Integer]
46
+ #
47
+ # @api public
48
+ def self.max_columns
49
+ TTY::Screen.width
50
+ end
51
+
52
+ # Determine the monospace display width of a string
53
+ #
54
+ # @param [String] value
55
+ # the value to determine width of
56
+ #
57
+ # @return [Integer]
58
+ #
59
+ # @api public
60
+ def self.display_columns(value)
61
+ Unicode::DisplayWidth.of(value)
62
+ end
63
+
42
64
  # Create progress bar
43
65
  #
44
66
  # @param [String] format
@@ -80,6 +102,10 @@ module TTY
80
102
 
81
103
  @formatter.load
82
104
  reset
105
+
106
+ @first_render = true
107
+ @multibar = nil
108
+ @row = nil
83
109
  end
84
110
 
85
111
  # Reset progress to default configuration
@@ -96,9 +122,6 @@ module TTY
96
122
  @start_at = Time.now
97
123
  @started = false
98
124
  @tokens = {}
99
- @multibar = nil
100
- @row = nil
101
- @first_render = true
102
125
 
103
126
  @meter.clear
104
127
  end
@@ -135,7 +158,7 @@ module TTY
135
158
  return if done?
136
159
 
137
160
  synchronize do
138
- emit(:progress)
161
+ emit(:progress, progress)
139
162
  if progress.respond_to?(:to_hash)
140
163
  tokens, progress = progress, 1
141
164
  end
@@ -201,7 +224,9 @@ module TTY
201
224
  def update(options = {})
202
225
  synchronize do
203
226
  options.each do |name, val|
204
- @configuration.public_send("#{name}=", val)
227
+ if @configuration.respond_to?("#{name}=")
228
+ @configuration.public_send("#{name}=", val)
229
+ end
205
230
  end
206
231
  end
207
232
  end
@@ -250,14 +275,22 @@ module TTY
250
275
  write(TTY::Cursor.hide)
251
276
  end
252
277
 
278
+ if @multibar
279
+ characters_in = @multibar.line_inset(self)
280
+ update(inset: self.class.display_columns(characters_in))
281
+ end
282
+
253
283
  formatted = @formatter.decorate(self, @format)
254
284
  @tokens.each do |token, val|
255
285
  formatted = formatted.gsub(":#{token}", val)
256
286
  end
257
- write(formatted, true)
287
+
288
+ padded = padout(formatted)
289
+
290
+ write(padded, true)
258
291
 
259
292
  @last_render_time = Time.now
260
- @last_render_width = formatted.length
293
+ @last_render_width = self.class.display_columns(formatted)
261
294
  end
262
295
 
263
296
  # Move cursor to a row of the current bar if the bar is rendered
@@ -420,15 +453,6 @@ module TTY
420
453
  render
421
454
  end
422
455
 
423
- # Determine terminal width
424
- #
425
- # @return [Integer]
426
- #
427
- # @api public
428
- def max_columns
429
- TTY::Screen.width
430
- end
431
-
432
456
  # Show bar format
433
457
  #
434
458
  # @return [String]
@@ -461,8 +485,10 @@ module TTY
461
485
  #
462
486
  # @api private
463
487
  def padout(message)
464
- if @last_render_width > message.length
465
- remaining_width = @last_render_width - message.length
488
+ message_length = self.class.display_columns(message)
489
+
490
+ if @last_render_width > message_length
491
+ remaining_width = @last_render_width - message_length
466
492
  message += ' ' * remaining_width
467
493
  end
468
494
  message
@@ -5,6 +5,7 @@ module TTY
5
5
  attr_reader :total
6
6
 
7
7
  attr_accessor :width
8
+ #attr_reader :width
8
9
 
9
10
  attr_accessor :no_width
10
11
 
@@ -24,9 +25,11 @@ module TTY
24
25
 
25
26
  attr_accessor :interval
26
27
 
28
+ attr_accessor :inset
29
+
27
30
  def initialize(options)
28
31
  self.total = options[:total] if options[:total]
29
- @width = options.fetch(:width) { total }
32
+ @width = options.fetch(:width) { total }
30
33
  @no_width = options.fetch(:no_width) { false }
31
34
  @incomplete = options.fetch(:incomplete) { ' ' }
32
35
  @complete = options.fetch(:complete) { '=' }
@@ -36,12 +39,23 @@ module TTY
36
39
  @output = options.fetch(:output) { $stderr }
37
40
  @frequency = options.fetch(:frequency) { 0 } # 0Hz
38
41
  @interval = options.fetch(:interval) { 1 } # 1 sec
42
+ @inset = options.fetch(:inset) { 0 }
39
43
  end
40
44
 
45
+ # def width=(value)
46
+ # return if value.nil?
47
+
48
+ # if value < ProgressBar.max_columns
49
+ # @width = value
50
+ # else
51
+ # @width = ProgressBar.max_columns
52
+ # end
53
+ # end
54
+
41
55
  def total=(value)
42
56
  fail ArgumentError unless value
43
57
  @total = value
44
- @width = value unless width
58
+ self.width = value if width.nil?
45
59
  end
46
60
  end # Configuration
47
61
  end # ProgressBar
@@ -30,12 +30,23 @@ module TTY
30
30
  #
31
31
  # @api public
32
32
  def format(value)
33
- available_space = [0, @progress.max_columns - value.gsub(/:bar/, '').length].max
33
+ without_bar = value.gsub(/:bar/, '')
34
+ available_space = [0, ProgressBar.max_columns -
35
+ ProgressBar.display_columns(without_bar) -
36
+ @progress.inset].max
34
37
  width = [@progress.width, available_space].min
35
- complete_length = (width * @progress.ratio).round
36
- complete = Array.new(complete_length, @progress.complete)
37
- incomplete = Array.new(width - complete_length, @progress.incomplete)
38
- complete[-1] = @progress.head if complete_length > 0
38
+ complete_bar_length = (width * @progress.ratio).round
39
+ complete_char_length = ProgressBar.display_columns(@progress.complete)
40
+ incomplete_char_length = ProgressBar.display_columns(@progress.incomplete)
41
+
42
+ # decimal number of items only when unicode chars are used
43
+ # otherwise it has no effect on regular ascii chars
44
+ complete_items = (complete_bar_length / complete_char_length.to_f).round
45
+ incomplete_items = (width - complete_items * complete_char_length) / incomplete_char_length
46
+
47
+ complete = Array.new(complete_items, @progress.complete)
48
+ incomplete = Array.new(incomplete_items, @progress.incomplete)
49
+ complete[-1] = @progress.head if complete_bar_length > 0
39
50
 
40
51
  bar = ''
41
52
  bar += complete.join
@@ -18,6 +18,8 @@ module TTY
18
18
 
19
19
  def_delegators :@bars, :each, :empty?, :length, :[]
20
20
 
21
+ def_delegators :@top_bar, :width, :width=
22
+
21
23
  DEFAULT_INSET = {
22
24
  top: Gem.win_platform? ? '+ ' : "\u250c ",
23
25
  middle: Gem.win_platform? ? '|-- ' : "\u251c\u2500\u2500 ",
@@ -51,6 +53,9 @@ module TTY
51
53
  @top_bar = nil
52
54
  @top_bar = register(format, observable: false) if format
53
55
 
56
+ @width = @options[:width]
57
+ @top_bar.update(width: @width) if @width
58
+
54
59
  @callbacks = {
55
60
  progress: [],
56
61
  stopped: [],
@@ -73,7 +78,8 @@ module TTY
73
78
  @bars << bar
74
79
  observe(bar) if observable
75
80
  if @top_bar
76
- @top_bar.update(total: total, width: total)
81
+ @top_bar.update(total: total)
82
+ @top_bar.update(width: total) unless @width
77
83
  end
78
84
  end
79
85
 
@@ -105,9 +111,9 @@ module TTY
105
111
  #
106
112
  # @api private
107
113
  def progress_handler
108
- proc do
109
- @top_bar.advance if @top_bar
110
- emit(:progress)
114
+ -> (progress) do
115
+ @top_bar.advance(progress) if @top_bar
116
+ emit(:progress, progress)
111
117
  end
112
118
  end
113
119
 
@@ -1,5 +1,5 @@
1
1
  module TTY
2
2
  class ProgressBar
3
- VERSION = '0.14.0'.freeze
3
+ VERSION = '0.15.0'.freeze
4
4
  end # ProgressBar
5
5
  end # TTY
@@ -17,6 +17,7 @@ require 'timecop'
17
17
  require 'tty-progressbar'
18
18
 
19
19
  class StringIO
20
+ undef_method :tty?
20
21
  def tty?
21
22
  true
22
23
  end
@@ -8,7 +8,7 @@ RSpec.describe TTY::ProgressBar, 'custom token' do
8
8
  output.rewind
9
9
  expect(output.read).to eq([
10
10
  "\e[1G(1) Hello Piotr!",
11
- "\e[1G(4) Bye Piotr!\n"
11
+ "\e[1G(4) Bye Piotr! \n"
12
12
  ].join)
13
13
  end
14
14
  end
@@ -0,0 +1,28 @@
1
+ RSpec.describe TTY::ProgressBar::Multi, '#reset' do
2
+ let(:output) { StringIO.new('', 'w+') }
3
+
4
+ it "leaves multibar state alone" do
5
+ main = TTY::ProgressBar::Multi.new("", output: output, total: 10)
6
+ progress = main.register("[:bar]")
7
+ progress.advance(10)
8
+ expect(progress.complete?).to be(true)
9
+ progress.reset
10
+ expect(progress.complete?).to be(false)
11
+ progress.advance(10)
12
+ output.rewind
13
+
14
+ top = TTY::ProgressBar::Multi::DEFAULT_INSET[:top]
15
+ bottom = TTY::ProgressBar::Multi::DEFAULT_INSET[:bottom]
16
+
17
+ progress_updates =
18
+ output.read.scan(/#{Regexp.escape top}|#{Regexp.escape bottom}/)
19
+ expect(progress_updates.shift).to match(top)
20
+ expect(progress_updates.shift).to match(top)
21
+ expect(progress_updates.shift).to match(bottom)
22
+ expect(progress_updates.shift).to match(bottom)
23
+ expect(progress_updates.shift).to match(bottom)
24
+ expect(progress_updates.shift).to match(bottom)
25
+
26
+ expect(progress_updates).to be_empty
27
+ end
28
+ end
@@ -0,0 +1,118 @@
1
+ RSpec.describe TTY::ProgressBar::Multi, 'width' do
2
+ let(:output) { StringIO.new('', 'w+') }
3
+ let(:save) { TTY::Cursor.save }
4
+ let(:restore) { TTY::Cursor.restore }
5
+ let(:top) { TTY::ProgressBar::Multi::DEFAULT_INSET[:top] }
6
+ let(:middle) { TTY::ProgressBar::Multi::DEFAULT_INSET[:middle] }
7
+ let(:bottom) { TTY::ProgressBar::Multi::DEFAULT_INSET[:bottom] }
8
+
9
+ it "sets top level bar width to maximum columns when exceeds terminal width" do
10
+ allow(TTY::Screen).to receive(:width).and_return(15)
11
+
12
+ bars = TTY::ProgressBar::Multi.new("[:bar] main", output: output)
13
+
14
+ bar1 = bars.register("[:bar] one", total: 20)
15
+ bar2 = bars.register("[:bar] two", total: 20)
16
+
17
+ bar1.advance(10)
18
+ bar2.advance(10)
19
+
20
+ output.rewind
21
+ expect(output.read).to eq([
22
+ "\e[1G#{top}[== ] main\n",
23
+ "\e[1G#{bottom}[=== ] one\n",
24
+ save,
25
+ "\e[2A", # up 2 lines
26
+ "\e[1G#{top}[=== ] main",
27
+ restore,
28
+ "\e[1G#{bottom}[=== ] two\n"
29
+ ].join)
30
+
31
+ bar1.advance(10)
32
+
33
+ output.rewind
34
+ expect(output.read).to eq([
35
+ "\e[1G#{top}[== ] main\n",
36
+ "\e[1G#{bottom}[=== ] one\n",
37
+ save,
38
+ "\e[2A", # up 2 lines
39
+ "\e[1G#{top}[=== ] main",
40
+ restore,
41
+ "\e[1G#{bottom}[=== ] two\n",
42
+ save,
43
+ "\e[3A", # up 3 lines
44
+ "\e[1G#{top}[===== ] main",
45
+ restore,
46
+ save,
47
+ "\e[2A", # up 2 lines
48
+ "\e[1G#{middle}[=====] one",
49
+ restore,
50
+ save,
51
+ "\e[2A", # up 2 lines
52
+ "#{middle}\n", # bar finished
53
+ restore
54
+ ].join)
55
+
56
+ bar2.advance(10)
57
+
58
+ output.rewind
59
+ expect(output.read).to eq([
60
+ "\e[1G#{top}[== ] main\n",
61
+ "\e[1G#{bottom}[=== ] one\n",
62
+ save,
63
+ "\e[2A", # up 2 lines
64
+ "\e[1G#{top}[=== ] main",
65
+ restore,
66
+ "\e[1G#{bottom}[=== ] two\n",
67
+ save,
68
+ "\e[3A", # up 3 lines
69
+ "\e[1G#{top}[===== ] main",
70
+ restore,
71
+ save,
72
+ "\e[2A", # up 2 lines
73
+ "\e[1G#{middle}[=====] one",
74
+ restore,
75
+ save,
76
+ "\e[2A", # up 2 lines
77
+ "#{middle}\n", # bar finished
78
+ restore,
79
+ save,
80
+ "\e[3A", # up 3 lines
81
+ "\e[1G#{top}[======] main",
82
+ restore,
83
+ save,
84
+ "\e[3A", # up 1 line
85
+ "#{top}\n",
86
+ restore,
87
+ save,
88
+ "\e[1A", # up 1 line
89
+ "\e[1G#{bottom}[=====] two",
90
+ restore,
91
+ save,
92
+ "\e[1A", # up 1 line
93
+ "#{bottom}\n",
94
+ restore
95
+ ].join)
96
+ end
97
+
98
+ it "sets top level bar width to a custom value" do
99
+ bars = TTY::ProgressBar::Multi.new("[:bar] main", output: output, width: 20)
100
+
101
+ bar1 = bars.register("[:bar] one", total: 20)
102
+ bar2 = bars.register("[:bar] two", total: 20)
103
+
104
+ bar1.advance(10)
105
+ bar2.advance(10)
106
+
107
+ output.rewind
108
+ expect(output.read).to eq([
109
+ "\e[1G#{top}[===== ] main\n",
110
+ "\e[1G#{bottom}[========== ] one\n",
111
+ save,
112
+ "\e[2A", # up 2 lines
113
+ "\e[1G#{top}[========== ] main",
114
+ restore,
115
+ "\e[1G#{bottom}[========== ] two\n"
116
+ ].join)
117
+ end
118
+ end
@@ -7,6 +7,16 @@ RSpec.describe TTY::ProgressBar, '::new' do
7
7
  }.to raise_error(ArgumentError, /Expected bar formatting string, got `{:output=>#{output}}` instead\./)
8
8
  end
9
9
 
10
+ it "allows to change formatting string" do
11
+ bar = TTY::ProgressBar.new("[:bar]", output: output, total: 4)
12
+ bar.advance(2)
13
+ bar.format = "(:bar)"
14
+ bar.advance(2)
15
+ output.rewind
16
+
17
+ expect(output.read).to eq("\e[1G[== ]\e[1G(====)\n")
18
+ end
19
+
10
20
  it "displays output where width == total" do
11
21
  progress = TTY::ProgressBar.new("[:bar]", output: output, total: 10)
12
22
  progress.advance
@@ -0,0 +1,25 @@
1
+ RSpec.describe TTY::ProgressBar, "#render" do
2
+ let(:output) { StringIO.new("", "w+") }
3
+
4
+ it "pads out longer previous lines" do
5
+ progress = TTY::ProgressBar.new ":current_byte" do |config|
6
+ config.no_width = true
7
+ config.output = output
8
+ config.total = 1_048_577
9
+ end
10
+
11
+ progress.advance(1)
12
+ progress.advance(1_048_574)
13
+ progress.advance(1)
14
+ progress.advance(1)
15
+
16
+ output.rewind
17
+
18
+ expect(output.read).to eq([
19
+ "\e[1G1B",
20
+ "\e[1G1024.00KB", # must not pad, line is longer
21
+ "\e[1G1.00MB ", # must pad out "0KB"
22
+ "\e[1G1.00MB", # must not pad, line is equal
23
+ ].join)
24
+ end
25
+ end
@@ -11,7 +11,7 @@ RSpec.describe TTY::ProgressBar, '#resize' do
11
11
  "\e[1G[== ]",
12
12
  "\e[1G[==== ]",
13
13
  "\e[0m\e[2K\e[1G",
14
- "\e[1G[=== ]",
14
+ "\e[1G[=== ] ",
15
15
  "\e[1G[==== ]",
16
16
  "\e[1G[=====]\n"
17
17
  ].join)
@@ -8,8 +8,10 @@ RSpec.describe TTY::ProgressBar, '#width' do
8
8
  config.width = 1024
9
9
  end
10
10
  allow(TTY::Screen).to receive(:width).and_return(20)
11
+
11
12
  5.times { progress.advance }
12
13
  output.rewind
14
+
13
15
  expect(output.read).to eq([
14
16
  "\e[1G[==== ]",
15
17
  "\e[1G[======= ]",
@@ -18,4 +20,67 @@ RSpec.describe TTY::ProgressBar, '#width' do
18
20
  "\e[1G[==================]\n"
19
21
  ].join)
20
22
  end
23
+
24
+ it "handles unicode characters width in formatting string" do
25
+ bar = TTY::ProgressBar.new("あめかんむり[:bar]", output: output, total: 20)
26
+ allow(TTY::Screen).to receive(:width).and_return(20)
27
+
28
+ 4.times { bar.advance(5) }
29
+ output.rewind
30
+
31
+ expect(output.read).to eq([
32
+ "\e[1Gあめかんむり[== ]",
33
+ "\e[1Gあめかんむり[=== ]",
34
+ "\e[1Gあめかんむり[===== ]",
35
+ "\e[1Gあめかんむり[======]\n"
36
+ ].join)
37
+ end
38
+
39
+ it "handles unicodes characters within bar" do
40
+ bar = TTY::ProgressBar.new("[:bar]", output: output, total: 20,
41
+ complete: 'あ', incomplete: 'め')
42
+ allow(TTY::Screen).to receive(:width).and_return(20)
43
+
44
+ 4.times { bar.advance(5) }
45
+ output.rewind
46
+
47
+ expect(output.read).to eq([
48
+ "\e[1G[あああめめめめめめ]",
49
+ "\e[1G[あああああめめめめ]",
50
+ "\e[1G[あああああああめめ]",
51
+ "\e[1G[あああああああああ]\n"
52
+ ].join)
53
+ end
54
+
55
+ it "handles unicodes characters within bar" do
56
+ bar = TTY::ProgressBar.new("[:bar]", output: output, total: 20,
57
+ complete: 'あ', incomplete: ' ')
58
+ allow(TTY::Screen).to receive(:width).and_return(20)
59
+
60
+ 4.times { bar.advance(5) }
61
+ output.rewind
62
+
63
+ expect(output.read).to eq([
64
+ "\e[1G[あああ ]",
65
+ "\e[1G[あああああ ]",
66
+ "\e[1G[あああああああ ]",
67
+ "\e[1G[あああああああああ]\n"
68
+ ].join)
69
+ end
70
+
71
+ it "handles unicodes characters within bar" do
72
+ bar = TTY::ProgressBar.new("[:bar]", output: output, total: 20,
73
+ complete: 'x', incomplete: 'め')
74
+ allow(TTY::Screen).to receive(:width).and_return(20)
75
+
76
+ 4.times { bar.advance(5) }
77
+ output.rewind
78
+
79
+ expect(output.read).to eq([
80
+ "\e[1G[xxxxxめめめめめめ]",
81
+ "\e[1G[xxxxxxxxxめめめめ]",
82
+ "\e[1G[xxxxxxxxxxxxxxめめ]",
83
+ "\e[1G[xxxxxxxxxxxxxxxxxx]\n"
84
+ ].join)
85
+ end
21
86
  end
@@ -20,8 +20,9 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.required_ruby_version = '>= 2.0.0'
22
22
 
23
- spec.add_dependency "tty-cursor", '~> 0.5.0'
24
- spec.add_dependency "tty-screen", '~> 0.6.4'
23
+ spec.add_dependency 'tty-cursor', '~> 0.5.0'
24
+ spec.add_dependency 'tty-screen', '~> 0.6.4'
25
+ spec.add_dependency 'unicode-display_width', '~> 1.3'
25
26
 
26
27
  spec.add_development_dependency 'bundler', '>= 1.5.0', '< 2.0'
27
28
  spec.add_development_dependency 'rspec', '~> 3.1'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tty-progressbar
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.0
4
+ version: 0.15.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-17 00:00:00.000000000 Z
11
+ date: 2018-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: tty-cursor
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: 0.6.4
41
+ - !ruby/object:Gem::Dependency
42
+ name: unicode-display_width
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.3'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.3'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: bundler
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -124,11 +138,13 @@ files:
124
138
  - examples/lazy.rb
125
139
  - examples/multi/main_bar.rb
126
140
  - examples/multi/simple.rb
141
+ - examples/multi/width.rb
127
142
  - examples/simple.rb
128
143
  - examples/slow_process.rb
129
144
  - examples/speed.rb
130
145
  - examples/threaded.rb
131
146
  - examples/tokens.rb
147
+ - examples/unicode.rb
132
148
  - lib/tty-progressbar.rb
133
149
  - lib/tty/progressbar.rb
134
150
  - lib/tty/progressbar/configuration.rb
@@ -185,10 +201,13 @@ files:
185
201
  - spec/unit/multi/finish_spec.rb
186
202
  - spec/unit/multi/line_inset_spec.rb
187
203
  - spec/unit/multi/register_spec.rb
204
+ - spec/unit/multi/reset_spec.rb
188
205
  - spec/unit/multi/stop_spec.rb
206
+ - spec/unit/multi/width_spec.rb
189
207
  - spec/unit/new_spec.rb
190
208
  - spec/unit/pipeline_spec.rb
191
209
  - spec/unit/ratio_spec.rb
210
+ - spec/unit/render_spec.rb
192
211
  - spec/unit/reset_spec.rb
193
212
  - spec/unit/resize_spec.rb
194
213
  - spec/unit/set_current_spec.rb
@@ -260,10 +279,13 @@ test_files:
260
279
  - spec/unit/multi/finish_spec.rb
261
280
  - spec/unit/multi/line_inset_spec.rb
262
281
  - spec/unit/multi/register_spec.rb
282
+ - spec/unit/multi/reset_spec.rb
263
283
  - spec/unit/multi/stop_spec.rb
284
+ - spec/unit/multi/width_spec.rb
264
285
  - spec/unit/new_spec.rb
265
286
  - spec/unit/pipeline_spec.rb
266
287
  - spec/unit/ratio_spec.rb
288
+ - spec/unit/render_spec.rb
267
289
  - spec/unit/reset_spec.rb
268
290
  - spec/unit/resize_spec.rb
269
291
  - spec/unit/set_current_spec.rb