Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions README.mkd
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ lots of progress bar alternatives, and we thank you for using ProgressBar!

## The Easy Way


require 'progress_bar'
bar = ProgressBar.new

Expand All @@ -39,11 +38,16 @@ it.*

## Setting the Max

Usually, the defaults should be fine, the only thing you'll need to
tweak is the max.

bar = ProgressBar.new(1000)

## Setting the progress bar characters

By default, ProgressBar will use a default bar character to show progress and
side delimiters. You can set any valid character that is supported by your
terminal for either the bar character or the delimiters.

bar = ProgressBar.new(bar: '█', delimiters: '||')

## Larger Steps

If you want to process several things, and update less often, you can
Expand Down
32 changes: 20 additions & 12 deletions lib/progress_bar.rb
Original file line number Diff line number Diff line change
@@ -1,23 +1,30 @@

require 'options'
require 'highline'

class ProgressBar
Error = Class.new(StandardError)
ArgumentError = Class.new(Error)

attr_accessor :count, :max, :meters
DEFAULT_METERS = [:bar, :counter, :percentage, :elapsed, :eta, :rate]

def initialize(*args)
attr_accessor :count, :max, :meters, :bar, :delimiters

def initialize(*args, bar: '#', delimiters: '[]')
@count = 0
@max = 100
@meters = [:bar, :counter, :percentage, :elapsed, :eta, :rate]

@max = args.shift if args.first.is_a? Numeric
raise ArgumentError, "Max must be a positive integer" unless @max >= 0

@meters = args unless args.empty?
@meters = args.empty? ? DEFAULT_METERS : args

@bar = bar # can be an emoji which itself can be a sequence of characters
raise ArgumentError, 'Bar must be a valid string' unless @bar&.is_a?(String)
Copy link
Author

@TRex22 TRex22 Sep 17, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to remove the character limit because lots of new emojis are multi-sequence characters. This isn't supported everywhere but in modern terminals it is. I dont see a reason to limit this functionality and its up to the developer using this Gem to make sure the character doesnt mess up for their use case if they select a multi-character sequence


@delimiters = delimiters
unless @delimiters&.size == 2
raise ArgumentError, 'Delimiters must be two characters'
end

@last_write = ::Time.at(0)
@start = ::Time.now
Expand Down Expand Up @@ -73,8 +80,8 @@ def eta

def to_s
self.count = max if count > max
meters.inject("") do |text, meter|
text << render(meter) + " "
meters.inject('') do |text, meter|
text << render(meter) + ' '
end.strip
end

Expand All @@ -98,12 +105,14 @@ def width_of(meter)

def render_bar
return '' if bar_width < 2

progress_width = (ratio * (bar_width - 2)).floor
remainder_width = bar_width - 2 - progress_width
"[" +
"#" * progress_width +
" " * remainder_width +
"]"

delimiters[0] +
bar * progress_width +
' ' * remainder_width +
delimiters[-1]
end

def render_counter
Expand Down Expand Up @@ -188,7 +197,6 @@ def format_interval(interval)
"%02i:%02i" % [interval/60, interval%60]
end
end

end

require_relative 'progress_bar/with_progress'
48 changes: 41 additions & 7 deletions spec/arguments_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,69 @@
@default_meters = [:bar, :counter, :percentage, :elapsed, :eta, :rate]
end

it "should set appropriate defaults without any arguments" do
it 'should set appropriate defaults without any arguments' do
bar = ProgressBar.new
bar.max.should == @default_max
bar.meters.should == @default_meters
end

it "should allow a single argument specifying the max" do
it 'should allow a single argument specifying the max' do
bar = ProgressBar.new(123)
bar.max.should == 123
bar.meters.should == @default_meters
end

it "should allow specifying just the meters" do
it 'should allow specifying just the meters' do
bar = ProgressBar.new(:bar, :eta)
bar.max.should == @default_max
bar.meters.should == [:bar, :eta]
end

it "should allow specyfing the max and meters" do
it 'should allow specifying the max and meters' do
bar = ProgressBar.new(123, :bar, :eta)
bar.max.should == 123
bar.meters.should == [:bar, :eta]
end

it "should raise an error when initial max is nonsense" do
it 'should allow specifying the bar and delimiters' do
bar = ProgressBar.new(bar: '$', delimiters: '||')
bar.bar.should == '$'
bar.delimiters.should == '||'
end

it 'should raise an error when initial max is nonsense' do
lambda {
bar = ProgressBar.new(-1)
_bar = ProgressBar.new(-1)
}.should raise_error(ProgressBar::ArgumentError)
end

end
it 'should raise an error when bar is not a string' do
lambda {
_bar = ProgressBar.new(bar: 5)
}.should raise_error(ProgressBar::ArgumentError)
end

it 'should raise an error when bar is empty' do
lambda {
_bar = ProgressBar.new(bar: nil)
}.should raise_error(ProgressBar::ArgumentError)
end

it 'should raise an error when delimiters is less than two characters' do
lambda {
_bar = ProgressBar.new(delimiters: '|')
}.should raise_error(ProgressBar::ArgumentError)
end

it 'should raise an error when delimiters is more than two characters' do
lambda {
_bar = ProgressBar.new(delimiters: '|||')
}.should raise_error(ProgressBar::ArgumentError)
end

it 'should raise an error when delimiters is empty' do
lambda {
_bar = ProgressBar.new(delimiters: '')
}.should raise_error(ProgressBar::ArgumentError)
end
end
2 changes: 0 additions & 2 deletions spec/bar_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,4 @@
end
end
end

end

1 change: 0 additions & 1 deletion spec/counter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,4 @@

it { should == '[ 0/4242]' }
end

end
3 changes: 0 additions & 3 deletions spec/elapsed_spec.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))

describe 'ProgressBar elapsed output' do
Expand Down Expand Up @@ -43,6 +42,4 @@

it { should == '[02:00:00]' }
end

end

4 changes: 0 additions & 4 deletions spec/eta_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,4 @@

it { should == '[02:00:00]' }
end

end



2 changes: 0 additions & 2 deletions spec/percentage_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,4 @@

it { should == '[ 50.00%]' }
end

end

53 changes: 53 additions & 0 deletions spec/progress_bar_characters_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))

describe 'ProgressBar bar output with custom characters' do
before do
Timecop.freeze Time.utc(2010, 3, 10, 0, 0, 0)
@progress_bar = ProgressBar.new(100, bar: '█', delimiters: '▕▏')
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, there is kind of a test for multibyte characters I guess. Why are there two separate spec files?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasnt certain the arguments_spec really covered the use case. I was more of an interface positive negative check. I wanted a test that specifically checked the feature and its output

@progress_bar.stub(:terminal_width) { 60 }
Timecop.freeze Time.utc(2010, 3, 10, 0, 0, 10) # 10 seconds later
end

subject { @progress_bar.to_s }

describe 'at count=0' do
before do
@progress_bar.count = 0
end

it { should == '▕ ▏ [ 0/100] [ 0%] [00:10] [00:00] [ 0.00/s]' }
end

describe 'at count=50' do
before do
@progress_bar.count = 50
end

it { should == '▕███████ ▏ [ 50/100] [ 50%] [00:10] [00:10] [ 5.00/s]' }
end

describe 'at count=100' do
before do
@progress_bar.count = 100
end

it { should == '▕██████████████▏ [100/100] [100%] [00:10] [00:00] [ 10.00/s]' }
end

describe 'at count=105' do
before do
@progress_bar.count = 105
end

it { should == '▕██████████████▏ [100/100] [100%] [00:10] [00:00] [ 10.00/s]' }
end

describe 'at count=100 with a multi-sequence emoji' do
before do
@progress_bar.count = 100
@progress_bar.bar = "🏴‍☠️"
end

it { should == '▕🏴‍☠️🏴‍☠️🏴‍☠️🏴‍☠️🏴‍☠️🏴‍☠️🏴‍☠️🏴‍☠️🏴‍☠️🏴‍☠️🏴‍☠️🏴‍☠️🏴‍☠️🏴‍☠️▏ [100/100] [100%] [00:10] [00:00] [ 10.00/s]' }
end
end
3 changes: 0 additions & 3 deletions spec/progress_bar_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,4 @@

it { should == "[##############] [100/100] [100%] [00:10] [00:00] [ 10.00/s]" }
end

end


6 changes: 0 additions & 6 deletions spec/rate_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,4 @@

it { should == '[ 2.10/s]' }
end

end





2 changes: 0 additions & 2 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib/progress_bar'))

require 'rspec'
Expand All @@ -9,4 +8,3 @@
Timecop.return
end
end