Skip to content

Commit

Permalink
Merge branch 'allow-minimalist-bar-formats' into development
Browse files Browse the repository at this point in the history
* allow-minimalist-bar-formats:
  Update the formatting to make sure the %b and %i formatting molecules can coexist with each other
  Now that we can use the %b and %i flags, we can create a mirrored bar simply by using a format string of '%i%b' and therefore this extra code is no longer necessary
  Allow %i to be used display the incomplete space of the bar
  Allow the %b molecule to be used to display the bar only without incomplete space
  Update the %B format test to be more reasonable
  Make the %w molecule only return the bar with the percentage instead of including empty space
  Remove the `length` argument when calling `ProgressBar::Components::Bar#to_s` and instead set the attribute
  Rename `ProgressBar::Formatter#bar` to `#complete_bar`
  Change the %b (bar with percentage) format molecule to %w
  Swap the meaning of the %b and %B molecules

* commit 'ee8c0e9704a0d0da93c84a3d4eeb109de986469f':
  Update the formatting to make sure the %b and %i formatting molecules can coexist with each other
  Now that we can use the %b and %i flags, we can create a mirrored bar simply by using a format string of '%i%b' and therefore this extra code is no longer necessary
  Allow %i to be used display the incomplete space of the bar
  Allow the %b molecule to be used to display the bar only without incomplete space
  Update the %B format test to be more reasonable
  Make the %w molecule only return the bar with the percentage instead of including empty space
  Remove the `length` argument when calling `ProgressBar::Components::Bar#to_s` and instead set the attribute
  Rename `ProgressBar::Formatter#bar` to `#complete_bar`
  Change the %b (bar with percentage) format molecule to %w
  Swap the meaning of the %b and %B molecules
  • Loading branch information
jfelchner committed Jul 30, 2012
2 parents 2af7422 + ee8c0e9 commit 0530682
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 107 deletions.
18 changes: 10 additions & 8 deletions README.md
Expand Up @@ -84,7 +84,7 @@ The following are the list of options you can use:
* `:total` - _(Defaults to `100`)_ The total number of the items that can be completed.
* `:starting_at` - _(Defaults to `0`)_ The number of items that should be considered completed when the bar first starts. This is also the default number that the bar will be set to if `#reset` is called.
* `:progress_mark` - _(Defaults to `o`)_ The mark which indicates the amount of progress that has been made.
* `:format` - _(Defaults to `%t: |%b|`)_ The format string which determines how the bar is displayed. See [**Formatting**](#formatting) below.
* `:format` - _(Defaults to `%t: |%B|`)_ The format string which determines how the bar is displayed. See [**Formatting**](#formatting) below.
* `:length` - _(Defaults to full width if possible, otherwise `80`)_ The preferred width of the entire progress bar including any format options.
* `:output` - _(Defaults to `STDOUT`)_ All output will be sent to this object. Can be any object which responds to `.print`.
* `:smoothing` - _(Defaults to `0.1`)_ See [**Smoothing Out Estimated Time Jitters**](#smoothing-out-estimated-time-jitters) below.
Expand Down Expand Up @@ -132,27 +132,29 @@ The flags you can use in the format string are as follows:
* `%P`: Percentage complete represented as a decimal number (eg: `82.33`)
* `%c`: Number of items currently completed
* `%C`: Total number of items to be completed
* `%b`: Progress bar itself
* `%B`: Bar With Integrated Percentage (eg: `|oooo 75 oooo |`)
* `%m`: Mirrored progress bar (accumulates from the right)
* `%B`: The full progress bar including 'incomplete' space (eg: `oooooooooo    `)
* `%b`: Progress bar only (eg: `oooooooooo`)
* `%w`: Bar With Integrated Percentage (eg: `oooo 75 oooo`)
* `%i`: Display the incomplete space of the bar (this string will only contain whitespace eg: `    `)
* `%%`: A literal percent sign `%`

All values have an absolute length with the exception of the bar flags (eg `%b`, `%r`) which will occupy any leftover space.
More than one bar flag can be used (although I'm not sure why you would :). If so, the remaining space will be divided up equally among them.
All values have an absolute length with the exception of the bar flags (eg `%B`, `%r`, etc) which will occupy any leftover space.
You can use as many bar flags as you'd like, but if you do weird things, weird things will happen; so be wary. If so, the remaining
space will be divided up equally among them.

### Example

If you would like a bar with the elapsed time on the left and the percentage complete followed by the title on the right, you'd do this:

ProgressBar.create(:format => '%a %b %p%% %t')
ProgressBar.create(:format => '%a %B %p%% %t')

Which will output something like this:

Time: --:--:-- 0% Progress

Hard to see where the bar is? Just add your own end caps, whatever you'd like. Like so:

ProgressBar.create(:format => '%a <%b> %p%% %t')
ProgressBar.create(:format => '%a <%B> %p%% %t')

Becomes:

Expand Down
30 changes: 9 additions & 21 deletions lib/progress_bar/components/bar.rb
Expand Up @@ -5,50 +5,38 @@ class Bar

DEFAULT_PROGRESS_MARK = 'o'

attr_accessor :mirrored
attr_accessor :progress_mark
attr_accessor :length

def initialize(options = {})
super

self.mirrored = false
self.progress_mark = options[:progress_mark] || DEFAULT_PROGRESS_MARK
end

def mirror
self.mirrored = !mirrored
end

def mirrored?
mirrored
end

def to_s(length, options = {:format => :standard})
self.length = length
def to_s(options = {:format => :standard})
completed_string = send(:"#{options[:format]}_complete_string")
empty_string = ' ' * (length - completed_string.length)

mirrored? ? "#{empty_string}#{completed_string}" : "#{completed_string}#{empty_string}"
"#{completed_string}#{empty_string}"
end

private
attr_accessor :length
def integrated_percentage_complete_string
" #{percentage_completed} ".to_s.center(completed_length, progress_mark)
end

def standard_complete_string
progress_mark * completed_length
end

def integrated_percentage_complete_string
" #{percentage_completed} ".to_s.center(completed_length, progress_mark)
def empty_string
' ' * (length - completed_length)
end

private
def completed_length
length * percentage_completed / 100
end

def empty_string
' ' * (length - completed_length)
end
end
end
end
8 changes: 4 additions & 4 deletions lib/progress_bar/format/molecule.rb
Expand Up @@ -12,13 +12,13 @@ class Molecule
:e => [:estimated_time_with_unknown, :estimated_time_with_unknown_oob],
:E => [:estimated_time_with_greater_than, :estimated_time_with_friendly_oob],
:f => [:force_estimated_time, :estimated_time_with_no_oob],
:B => [:complete_bar, :complete_bar],
:b => [:bar, :bar],
:B => [:bar_with_percentage, :bar_with_percentage],
:m => [:mirrored_bar, :mirrored_bar]
# :mirrored_bar_with_percentage => '%R'
:w => [:bar_with_percentage, :bar_with_percentage],
:i => [:incomplete_space, :incomplete_space]
}

BAR_MOLECULES = %w{b B m}
BAR_MOLECULES = %w{w B b i}

attr_reader :key
attr_reader :method_name
Expand Down
47 changes: 26 additions & 21 deletions lib/progress_bar/formatter.rb
@@ -1,6 +1,6 @@
class ProgressBar
module Formatter
DEFAULT_FORMAT_STRING = '%t: |%b|'
DEFAULT_FORMAT_STRING = '%t: |%B|'
DEFAULT_TITLE = 'Progress'

def initialize(options)
Expand Down Expand Up @@ -31,25 +31,23 @@ def total

private
def process
processed_string = @format_string.dup
@format_string.dup.tap do |processed_string|
@format.non_bar_molecules.each do |molecule|
processed_string.gsub!("%#{molecule.key}", self.send(molecule.method_name).to_s)
end

@format.non_bar_molecules.each do |molecule|
processed_string.gsub!("%#{molecule.key}", self.send(molecule.method_name).to_s)
end

remaining_molecule_match_data = processed_string.match(/%[^%]/) || []
remaining_molecules = remaining_molecule_match_data.size
placeholder_length = remaining_molecules * 2
remaining_molecule_match_data = processed_string.scan(/%[^%]/) || []
remaining_molecules = remaining_molecule_match_data.size
placeholder_length = remaining_molecules * 2

processed_string.gsub! '%%', '%'
processed_string.gsub! '%%', '%'

leftover_bar_length = length - processed_string.length + placeholder_length
leftover_bar_length = length - processed_string.length + placeholder_length

@format.bar_molecules.each do |molecule|
processed_string.gsub!("%#{molecule.key}", self.send(molecule.method_name, leftover_bar_length / remaining_molecules).to_s)
@format.bar_molecules.each do |molecule|
processed_string.gsub!("%#{molecule.key}", self.send(molecule.method_name, leftover_bar_length).to_s)
end
end

processed_string
end

# Format Methods
Expand Down Expand Up @@ -85,16 +83,23 @@ def estimated_time_with_friendly_oob
end

def bar(length)
@bar.to_s(length)
@bar.length = length
@bar.standard_complete_string
end

def bar_with_percentage(length)
@bar.to_s(length, :format => :integrated_percentage)
def complete_bar(length)
@bar.length = length
@bar.to_s
end

def mirrored_bar(length)
@bar.mirror unless @bar.mirrored?
@bar.to_s(length)
def incomplete_space(length)
@bar.length = length
@bar.empty_string
end

def bar_with_percentage(length)
@bar.length = length
@bar.integrated_percentage_complete_string
end

def estimated_time
Expand Down
40 changes: 23 additions & 17 deletions spec/progress_bar/base_spec.rb
Expand Up @@ -232,7 +232,7 @@

context 'when a new bar is created with a specific format' do
context '#format' do
before { @progressbar = ProgressBar::Base.new(:format => '%b %p%%') }
before { @progressbar = ProgressBar::Base.new(:format => '%B %p%%') }

context 'if called with no arguments' do
before { @progressbar.format }
Expand Down Expand Up @@ -260,30 +260,36 @@
@progressbar.to_s('%T').should match /^Progress\z/
end

it 'displays the bar when passed the "%b" format flag' do
@progressbar.to_s('%b').should match /^#{' ' * 80}\z/
it 'displays the bar when passed the "%B" format flag (including empty space)' do
@progressbar = ProgressBar::Base.new(:length => 100, :starting_at => 20)
@progressbar.to_s('%B').should match /^#{'o' * 20}#{' ' * 80}\z/
end

it 'displays the bar when passed the "%B" format flag' do
@progressbar = ProgressBar::Base.new(:output => @output, :length => 100, :starting_at => 0)
it 'displays the bar when passed the combined "%b%i" format flags' do
@progressbar = ProgressBar::Base.new(:length => 100, :starting_at => 20)
@progressbar.to_s('%b%i').should match /^#{'o' * 20}#{' ' * 80}\z/
end

@progressbar.to_s('%B').should match /^ 0#{' ' * 98}\z/
10.times { @progressbar.increment }
@progressbar.to_s('%B').should match /^ooo 10 ooo#{' ' * 90}\z/
@progressbar.decrement
@progressbar.to_s('%B').should match /^ooo 9 ooo#{' ' * 91}\z/
91.times { @progressbar.increment }
@progressbar.to_s('%B').should match /^#{'o' * 47} 100 #{'o' * 48}\z/
it 'displays the bar when passed the "%b" format flag (excluding empty space)' do
@progressbar = ProgressBar::Base.new(:length => 100, :starting_at => 20)
@progressbar.to_s('%b').should match /^#{'o' * 20}\z/
end

it 'displays the mirrored bar when passed the "%r" format flag' do
it 'displays the incomplete space when passed the "%i" format flag' do
@progressbar = ProgressBar::Base.new(:length => 100, :starting_at => 20)
@progressbar.to_s('%i').should match /^#{' ' * 80}\z/
end

it 'displays the bar when passed the "%w" format flag' do
@progressbar = ProgressBar::Base.new(:output => @output, :length => 100, :starting_at => 0)

@progressbar.to_s('%m').should match /^#{' ' * 100}\z/
@progressbar.increment
@progressbar.to_s('%m').should match /^#{' ' * 99}o\z/
@progressbar.to_s('%w').should match /^ 0 \z/
10.times { @progressbar.increment }
@progressbar.to_s('%w').should match /^ooo 10 ooo\z/
@progressbar.decrement
@progressbar.to_s('%m').should match /^#{' ' * 100}\z/
@progressbar.to_s('%w').should match /^ooo 9 ooo\z/
91.times { @progressbar.increment }
@progressbar.to_s('%w').should match /^#{'o' * 47} 100 #{'o' * 48}\z/
end

it 'displays the current capacity when passed the "%c" format flag' do
Expand Down
46 changes: 11 additions & 35 deletions spec/progress_bar/components/bar_spec.rb
Expand Up @@ -66,17 +66,10 @@
context 'when just begun' do
before do
@progressbar = ProgressBar::Components::Bar.new(:total => 50)
@progressbar.length = 100
@progressbar.start
end

context 'and the bar has been mirrored' do
before { @progressbar.mirror }

it 'displays the bar with no indication of progress' do
@progressbar.to_s(100).should eql ' '
end
end

describe '#percentage_completed' do
it 'calculates the amount' do
@progressbar.percentage_completed.should eql 0
Expand All @@ -85,14 +78,15 @@

describe '#to_s' do
it 'displays the bar with no indication of progress' do
@progressbar.to_s(100).should eql ' '
@progressbar.to_s.should eql ' '
end
end
end

context 'when nothing has been completed' do
before do
@progressbar = ProgressBar::Components::Bar.new(:total => 50)
@progressbar.length = 100
@progressbar.start
end

Expand All @@ -109,19 +103,9 @@
end
end

context 'and the bar has been mirrored' do
before { @progressbar.mirror }

describe '#to_s' do
it 'displays the bar with an indication of progress' do
@progressbar.to_s(100).should eql ' oo'
end
end
end

describe '#to_s' do
it 'displays the bar with an indication of progress' do
@progressbar.to_s(100).should eql 'oo '
@progressbar.to_s.should eql 'oo '
end
end
end
Expand All @@ -134,14 +118,15 @@

describe '#to_s' do
it 'displays the bar with no indication of progress' do
@progressbar.to_s(100).should eql ' '
@progressbar.to_s.should eql ' '
end
end
end

context 'when a fraction of a percentage has been completed' do
before do
@progressbar = ProgressBar::Components::Bar.new(:total => 200)
@progressbar.length = 100
@progressbar.start :at => 1
end

Expand All @@ -153,14 +138,15 @@

describe '#to_s' do
it 'displays the bar with no indication of progress' do
@progressbar.to_s(100).should eql ' '
@progressbar.to_s.should eql ' '
end
end
end

context 'when completed' do
before do
@progressbar = ProgressBar::Components::Bar.new(:total => 50)
@progressbar.length = 100
@progressbar.start :at => 50
end

Expand All @@ -174,7 +160,7 @@

describe '#to_s' do
it 'displays the bar as 100% complete' do
@progressbar.to_s(100).should eql 'o' * 100
@progressbar.to_s.should eql 'o' * 100
end
end
end
Expand All @@ -189,24 +175,14 @@

describe '#to_s' do
it 'displays the bar as 98% complete' do
@progressbar.to_s(100).should eql "#{'o' * 98} "
end
end
end

context 'and the bar has been mirrored' do
before { @progressbar.mirror }

describe '#to_s' do
it 'displays the bar with an indication of progress' do
@progressbar.to_s(100).should eql 'oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo'
@progressbar.to_s.should eql "#{'o' * 98} "
end
end
end

describe '#to_s' do
it 'displays the bar as 100% complete' do
@progressbar.to_s(100).should eql 'oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo'
@progressbar.to_s.should eql 'oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo'
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion spec/progress_bar/format/molecule_spec.rb
Expand Up @@ -15,7 +15,7 @@

describe '#bar_molecule?' do
it "is true if the molecule's key is a representation of the progress bar graphic" do
molecule = ProgressBar::Format::Molecule.new('b')
molecule = ProgressBar::Format::Molecule.new('B')
molecule.should be_bar_molecule
end
end
Expand Down

0 comments on commit 0530682

Please sign in to comment.