Class: RubyProgress::Fill

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby-progress/fill.rb

Overview

Determinate progress bar with customizable fill styles

Constant Summary collapse

FILL_STYLES =

A simple determinate progress bar that can be advanced programmatically or used with the block-based convenience method progress.

Public API (instance): #advance, #percent=, #completed?, #render, #complete, #cancel Public API (class): .progress, .parse_custom_style

Built-in fill styles with empty and full characters

Examples:

Fill.progress(length: 10) do |bar|
  10.times { bar.advance; sleep 0.1 }
end
{
  blocks: { empty: '', full: '' },
  classic: { empty: '-', full: '=' },
  dots: { empty: '·', full: '' },
  squares: { empty: '', full: '' },
  circles: { empty: '', full: '' },
  ascii: { empty: '.', full: '#' },
  bars: { empty: '', full: '' },
  arrows: { empty: '', full: '' },
  stars: { empty: '', full: '' }
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ void

Initialize a progress bar instance.

Parameters:

  • options (Hash) (defaults to: {})

    configuration values

Options Hash (options):

  • :length (Integer)

    number of cells in the bar (default 20)

  • :style (Symbol, String, Hash)

    style name, symbol, or custom hash

  • :success (String)

    success message shown on completion

  • :error (String)

    error message shown on cancel/exception



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/ruby-progress/fill.rb', line 40

def initialize(options = {})
  @length = options[:length] || 20
  @style = parse_style(options[:style] || :blocks)
  @current_progress = 0
  @success_message = options[:success]
  @error_message = options[:error]
  @output_capture = options[:output_capture]

  # Parse --ends characters
  if options[:ends]
    @start_chars, @end_chars = RubyProgress::Utils.parse_ends(options[:ends])
  else
    @start_chars = ''
    @end_chars = ''
  end
end

Instance Attribute Details

#current_progressObject (readonly)

Returns the value of attribute current_progress.



29
30
31
# File 'lib/ruby-progress/fill.rb', line 29

def current_progress
  @current_progress
end

#end_charsObject (readonly)

Returns the value of attribute end_chars.



29
30
31
# File 'lib/ruby-progress/fill.rb', line 29

def end_chars
  @end_chars
end

#error_messageObject

Returns the value of attribute error_message.



30
31
32
# File 'lib/ruby-progress/fill.rb', line 30

def error_message
  @error_message
end

#lengthObject (readonly)

Returns the value of attribute length.



29
30
31
# File 'lib/ruby-progress/fill.rb', line 29

def length
  @length
end

#start_charsObject (readonly)

Returns the value of attribute start_chars.



29
30
31
# File 'lib/ruby-progress/fill.rb', line 29

def start_chars
  @start_chars
end

#styleObject (readonly)

Returns the value of attribute style.



29
30
31
# File 'lib/ruby-progress/fill.rb', line 29

def style
  @style
end

#success_messageObject

Returns the value of attribute success_message.



30
31
32
# File 'lib/ruby-progress/fill.rb', line 30

def success_message
  @success_message
end

Class Method Details

.hide_cursorObject

Hide or show the cursor (delegated to Utils)



176
177
178
# File 'lib/ruby-progress/fill.rb', line 176

def self.hide_cursor
  RubyProgress::Utils.hide_cursor
end

.parse_custom_style(style_string) ⇒ Object

Parse custom style string like “custom=.#”



238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/ruby-progress/fill.rb', line 238

def parse_custom_style(style_string)
  if style_string.start_with?('custom=')
    chars = style_string.sub('custom=', '')

    # Handle multi-byte characters properly
    char_array = chars.chars

    if char_array.length == 2
      { empty: char_array[0], full: char_array[1] }
    else
      # Invalid custom style, return default
      FILL_STYLES[:blocks]
    end
  else
    # Try to find built-in style
    style_name = style_string.to_sym
    FILL_STYLES[style_name] || FILL_STYLES[:blocks]
  end
end

.progress(options = {}, &block) ⇒ Object

Progress with block interface for library usage



185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/ruby-progress/fill.rb', line 185

def self.progress(options = {}, &block)
  return unless block_given?

  fill_bar = new(options)
  Fill.hide_cursor

  begin
    fill_bar.render # Show initial empty bar

    # Call the block with the fill bar instance
    result = block.call(fill_bar)

    # Handle completion based on block result or bar state
    if fill_bar.completed? || result == true || result.nil?
      fill_bar.complete
    elsif result == false
      fill_bar.cancel
    end

    result
  rescue StandardError => e
    fill_bar.cancel("Error: #{e.message}")
    raise
  ensure
    Fill.show_cursor
  end
end

.show_cursorObject



180
181
182
# File 'lib/ruby-progress/fill.rb', line 180

def self.show_cursor
  RubyProgress::Utils.show_cursor
end

Instance Method Details

#advance(increment: 1, percent: nil) ⇒ Boolean

Advance the progress bar by one step or specified increment.

Parameters:

  • increment (Integer) (defaults to: 1)

    amount to increase progress by (default 1)

  • percent (Numeric, nil) (defaults to: nil)

    optional percent to set the bar to (0-100)

Returns:

  • (Boolean)

    true if the bar is complete after advancing



62
63
64
65
66
67
68
69
70
71
# File 'lib/ruby-progress/fill.rb', line 62

def advance(increment: 1, percent: nil)
  @current_progress = if percent
                        [@length * percent / 100.0, @length].min.round
                      else
                        [@current_progress + increment, @length].min
                      end

  render
  completed?
end

#cancel(message = nil) ⇒ void

This method returns an undefined value.

Cancel the progress bar and show error message.

Parameters:

  • message (String, nil) (defaults to: nil)

    optional override message



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/ruby-progress/fill.rb', line 159

def cancel(message = nil)
  $stderr.print "\r\e[2K" # Clear the progress bar
  $stderr.flush

  error_msg = message || @error_message
  return unless error_msg

  RubyProgress::Utils.display_completion(
    error_msg,
    success: false,
    show_checkmark: true,
    output_stream: :warn,
    icons: {}
  )
end

#complete(message = nil, icons: {}) ⇒ void

This method returns an undefined value.

Complete the progress bar and show success message.

Parameters:

  • message (String, nil) (defaults to: nil)

    optional override message

  • icons (Hash) (defaults to: {})

    optional icons map passed to Utils.display_completion



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/ruby-progress/fill.rb', line 137

def complete(message = nil, icons: {})
  @current_progress = @length
  render

  completion_message = message || @success_message
  if completion_message
    RubyProgress::Utils.display_completion(
      completion_message,
      success: true,
      show_checkmark: true,
      output_stream: :warn,
      icons: icons
    )
  else
    $stderr.puts # Just add a newline if no message
  end
end

#completed?Boolean

Check if progress bar is complete.

Returns:

  • (Boolean)


87
88
89
# File 'lib/ruby-progress/fill.rb', line 87

def completed?
  @current_progress >= @length
end

#currentFloat

Get current progress as float (0.0-100.0) - for scripting.

Returns:

  • (Float)


101
102
103
# File 'lib/ruby-progress/fill.rb', line 101

def current
  (@current_progress.to_f / @length * 100).round(1)
end

#percentFloat

Get current progress as percentage.

Returns:

  • (Float)

    percentage (0.0-100.0) rounded to 1 decimal place



94
95
96
# File 'lib/ruby-progress/fill.rb', line 94

def percent
  (@current_progress.to_f / @length * 100).round(1)
end

#percent=(percent) ⇒ Boolean

Set progress to specific percentage (0-100).

Parameters:

  • percent (Numeric)

    percentage 0..100 to set the bar to

Returns:

  • (Boolean)

    true if the bar is complete after setting percent



77
78
79
80
81
82
# File 'lib/ruby-progress/fill.rb', line 77

def percent=(percent)
  percent = percent.clamp(0, 100) # Clamp between 0-100
  @current_progress = (@length * percent / 100.0).round
  render
  completed?
end

#rendervoid

This method returns an undefined value.

Render the current progress bar to stderr.



120
121
122
123
124
125
126
127
128
129
130
# File 'lib/ruby-progress/fill.rb', line 120

def render
  # First redraw captured output (if any) so it appears above/below the bar
  @output_capture&.redraw($stderr)

  filled = @style[:full] * @current_progress
  empty = @style[:empty] * (@length - @current_progress)
  bar = "#{@start_chars}#{filled}#{empty}#{@end_chars}"

  $stderr.print "\r\e[2K#{bar}"
  $stderr.flush
end

#reportHash

Get detailed progress status information.

Returns:

  • (Hash)

    structured status information about the bar



108
109
110
111
112
113
114
115
# File 'lib/ruby-progress/fill.rb', line 108

def report
  {
    progress: [@current_progress, @length],
    percent: current,
    completed: completed?,
    style: @style
  }
end