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 =

Built-in fill styles with empty and full characters

{
  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 = {}) ⇒ Fill

Returns a new instance of Fill.



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/ruby-progress/fill.rb', line 22

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.



19
20
21
# File 'lib/ruby-progress/fill.rb', line 19

def current_progress
  @current_progress
end

#end_charsObject (readonly)

Returns the value of attribute end_chars.



19
20
21
# File 'lib/ruby-progress/fill.rb', line 19

def end_chars
  @end_chars
end

#error_messageObject

Returns the value of attribute error_message.



20
21
22
# File 'lib/ruby-progress/fill.rb', line 20

def error_message
  @error_message
end

#lengthObject (readonly)

Returns the value of attribute length.



19
20
21
# File 'lib/ruby-progress/fill.rb', line 19

def length
  @length
end

#start_charsObject (readonly)

Returns the value of attribute start_chars.



19
20
21
# File 'lib/ruby-progress/fill.rb', line 19

def start_chars
  @start_chars
end

#styleObject (readonly)

Returns the value of attribute style.



19
20
21
# File 'lib/ruby-progress/fill.rb', line 19

def style
  @style
end

#success_messageObject

Returns the value of attribute success_message.



20
21
22
# File 'lib/ruby-progress/fill.rb', line 20

def success_message
  @success_message
end

Class Method Details

.hide_cursorObject

Hide or show the cursor (delegated to Utils)



134
135
136
# File 'lib/ruby-progress/fill.rb', line 134

def self.hide_cursor
  RubyProgress::Utils.hide_cursor
end

.parse_custom_style(style_string) ⇒ Object

Parse custom style string like “custom=.#”



196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/ruby-progress/fill.rb', line 196

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



143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/ruby-progress/fill.rb', line 143

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



138
139
140
# File 'lib/ruby-progress/fill.rb', line 138

def self.show_cursor
  RubyProgress::Utils.show_cursor
end

Instance Method Details

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

Advance the progress bar by one step or specified increment



40
41
42
43
44
45
46
47
48
49
# File 'lib/ruby-progress/fill.rb', line 40

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) ⇒ Object

Cancel the progress bar and show error message



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

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: {}) ⇒ Object

Complete the progress bar and show success message



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/ruby-progress/fill.rb', line 98

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)


60
61
62
# File 'lib/ruby-progress/fill.rb', line 60

def completed?
  @current_progress >= @length
end

#currentObject

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



70
71
72
# File 'lib/ruby-progress/fill.rb', line 70

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

#percentObject

Get current progress as percentage



65
66
67
# File 'lib/ruby-progress/fill.rb', line 65

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

#percent=(percent) ⇒ Object

Set progress to specific percentage (0-100)



52
53
54
55
56
57
# File 'lib/ruby-progress/fill.rb', line 52

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

#renderObject

Render the current progress bar to stderr



85
86
87
88
89
90
91
92
93
94
95
# File 'lib/ruby-progress/fill.rb', line 85

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

#reportObject

Get detailed progress status information



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

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