Class: TTY::ProgressBar::Multi

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Enumerable, MonitorMixin
Defined in:
lib/tty/progressbar/multi.rb

Overview

Used for managing multiple terminal progress bars

Constant Summary collapse

DEFAULT_INSET =
{
  top:    Gem.win_platform? ? "+ "   : "\u250c ",
  middle: Gem.win_platform? ? "|-- " : "\u251c\u2500\u2500 ",
  bottom: Gem.win_platform? ? "|__ " : "\u2514\u2500\u2500 "
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ Multi

Create a multibar

Examples:

bars = TTY::ProgressBar::Multi.new
bars = TTY::ProgressBar::Multi.new("main [:bar]")

Parameters:

  • format (String)

    the formatting string to display this bar

  • options (Hash)


46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/tty/progressbar/multi.rb', line 46

def initialize(*args)
  super()
  @options = args.last.is_a?(::Hash) ? args.pop : {}
  format = args.empty? ? nil : args.pop
  @inset_opts = @options.delete(:style) { DEFAULT_INSET }
  @bars = []
  @rows = 0
  @top_bar = nil
  @top_bar = register(format, observable: false) if format

  @width = @options[:width]
  @top_bar.update(width: @width) if @top_bar && @width

  @callbacks = {
    progress: [],
    stopped: [],
    paused: [],
    done: []
  }
end

Instance Attribute Details

#rowsObject (readonly)

Number of currently occupied rows in terminal display



30
31
32
# File 'lib/tty/progressbar/multi.rb', line 30

def rows
  @rows
end

Instance Method Details

#complete?Boolean

Check if all progress bars are complete

Returns:

  • (Boolean)


165
166
167
168
169
# File 'lib/tty/progressbar/multi.rb', line 165

def complete?
  synchronize do
    (@bars - [@top_bar]).all?(&:complete?)
  end
end

#currentInteger

Calculate total current progress of all bars

Returns:

  • (Integer)


154
155
156
157
158
# File 'lib/tty/progressbar/multi.rb', line 154

def current
  synchronize do
    (@bars - [@top_bar]).map(&:current).reduce(&:+)
  end
end

#done?Boolean

Check if all bars are stopped or finished

Returns:

  • (Boolean)


187
188
189
190
191
# File 'lib/tty/progressbar/multi.rb', line 187

def done?
  synchronize do
    (@bars - [@top_bar]).all?(&:done?)
  end
end

#finishObject

Finish all progress bars



214
215
216
# File 'lib/tty/progressbar/multi.rb', line 214

def finish
  @bars.each(&:finish)
end

#line_inset(bar) ⇒ String

Find the number of characters to move into the line before printing the bar

Parameters:

  • bar (TTY::ProgressBar)

    the progress bar for which line inset is calculated

Returns:

  • (String)

    the inset



242
243
244
245
246
247
248
249
250
251
252
253
# File 'lib/tty/progressbar/multi.rb', line 242

def line_inset(bar)
  return "" if @top_bar.nil?

  case bar.row
  when @top_bar.row
    @inset_opts[:top]
  when rows
    @inset_opts[:bottom]
  else
    @inset_opts[:middle]
  end
end

#next_rowObject

Increase row count



94
95
96
97
98
# File 'lib/tty/progressbar/multi.rb', line 94

def next_row
  synchronize do
    @rows += 1
  end
end

#observe(bar) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Observe a bar for emitted events

Parameters:



106
107
108
109
110
111
# File 'lib/tty/progressbar/multi.rb', line 106

def observe(bar)
  bar.on(:progress, &progress_handler)
     .on(:done) { emit(:done) if complete? }
     .on(:stopped) { emit(:stopped) if stopped? }
     .on(:paused) { emit(:paused) if paused? }
end

#on(name, &callback) ⇒ Object

Listen on event

Parameters:

  • name (Symbol)

    the event name to listen on



261
262
263
264
265
266
267
268
269
# File 'lib/tty/progressbar/multi.rb', line 261

def on(name, &callback)
  unless @callbacks.key?(name)
    raise ArgumentError, "The event #{name} does not exist. " \
                         "Use :progress, :stopped, :paused or " \
                         ":done instead"
  end
  @callbacks[name] << callback
  self
end

#pauseObject

Pause all progress bars



221
222
223
# File 'lib/tty/progressbar/multi.rb', line 221

def pause
  @bars.each(&:pause)
end

#paused?Boolean

Check if all bars are paused

Returns:

  • (Boolean)


198
199
200
201
202
# File 'lib/tty/progressbar/multi.rb', line 198

def paused?
  synchronize do
    (@bars - [@top_bar]).all?(&:paused?)
  end
end

#progress_handlerObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Handle the progress event



116
117
118
119
120
121
# File 'lib/tty/progressbar/multi.rb', line 116

def progress_handler
  ->(progress) do
    @top_bar.advance(progress) if @top_bar
    emit(:progress, progress)
  end
end

#register(format, options = {}) ⇒ Object

Register a new progress bar

Parameters:

  • format (String)

    the formatting string to display the bar



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/tty/progressbar/multi.rb', line 73

def register(format, options = {})
  observable = options.delete(:observable) { true }
  bar = TTY::ProgressBar.new(format, @options.merge(options))

  synchronize do
    bar.attach_to(self)
    @bars << bar
    observe(bar) if observable
    if @top_bar
      @top_bar.update(total: total)
      @top_bar.resume if @top_bar.done?
      @top_bar.update(width: total) unless @width
    end
  end

  bar
end

#resumeObject

Resume all progress bars



228
229
230
# File 'lib/tty/progressbar/multi.rb', line 228

def resume
  @bars.each(&:resume)
end

#startObject



132
133
134
135
136
# File 'lib/tty/progressbar/multi.rb', line 132

def start
  raise "No top level progress bar" unless @top_bar

  @top_bar.start
end

#stopObject

Stop all progress bars



207
208
209
# File 'lib/tty/progressbar/multi.rb', line 207

def stop
  @bars.each(&:stop)
end

#stopped?Boolean

Check if all of the registered progress bars is stopped

Returns:

  • (Boolean)


176
177
178
179
180
# File 'lib/tty/progressbar/multi.rb', line 176

def stopped?
  synchronize do
    (@bars - [@top_bar]).all?(&:stopped?)
  end
end

#top_barObject

Get the top level bar if it exists



126
127
128
129
130
# File 'lib/tty/progressbar/multi.rb', line 126

def top_bar
  raise "No top level progress bar" unless @top_bar

  @top_bar
end

#totalInteger

Calculate total maximum progress of all bars

Returns:

  • (Integer)


143
144
145
146
147
# File 'lib/tty/progressbar/multi.rb', line 143

def total
  synchronize do
    (@bars - [@top_bar]).map(&:total).compact.reduce(&:+)
  end
end