Class: CLI::UI::Spinner::SpinGroup

Inherits:
Object
  • Object
show all
Defined in:
lib/cli/ui/spinner/spin_group.rb

Defined Under Namespace

Classes: Task

Instance Method Summary collapse

Constructor Details

#initialize(auto_debrief: true) ⇒ SpinGroup

Initializes a new spin group This lets you add Task objects to the group to multi-thread work

Options

  • :auto_debrief - Automatically debrief exceptions? Default to true

Example Usage

spin_group = CLI::UI::SpinGroup.new
spin_group.add('Title')   { |spinner| sleep 3.0 }
spin_group.add('Title 2') { |spinner| sleep 3.0; spinner.update_title('New Title'); sleep 3.0 }
spin_group.wait

Output:


23
24
25
26
27
28
29
# File 'lib/cli/ui/spinner/spin_group.rb', line 23

def initialize(auto_debrief: true)
  @m = Mutex.new
  @consumed_lines = 0
  @tasks = []
  @auto_debrief = auto_debrief
  @start = Time.new
end

Instance Method Details

#add(title, &block) ⇒ Object

Add a new task

Attributes

  • title - Title of the task

  • block - Block for the task, will be provided with an instance of the spinner

Example Usage:

spin_group = CLI::UI::SpinGroup.new
spin_group.add('Title') { |spinner| sleep 1.0 }
spin_group.wait

173
174
175
176
177
# File 'lib/cli/ui/spinner/spin_group.rb', line 173

def add(title, &block)
  @m.synchronize do
    @tasks << Task.new(title, &block)
  end
end

#debriefObject

Debriefs failed tasks is auto_debrief is true


233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
# File 'lib/cli/ui/spinner/spin_group.rb', line 233

def debrief
  @m.synchronize do
    @tasks.each do |task|
      next if task.success

      e = task.exception
      out = task.stdout
      err = task.stderr

      CLI::UI::Frame.open('Task Failed: ' + task.title, color: :red, timing: Time.new - @start) do
        if e
          puts "#{e.class}: #{e.message}"
          puts "\tfrom #{e.backtrace.join("\n\tfrom ")}"
        end

        CLI::UI::Frame.divider('STDOUT')
        out = "(empty)" if out.nil? || out.strip.empty?
        puts out

        CLI::UI::Frame.divider('STDERR')
        err = "(empty)" if err.nil? || err.strip.empty?
        puts err
      end
    end
    @tasks.all?(&:success)
  end
end

#waitObject

Tells the group you're done adding tasks and to wait for all of them to finish

Example Usage:

spin_group = CLI::UI::SpinGroup.new
spin_group.add('Title') { |spinner| sleep 1.0 }
spin_group.wait

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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# File 'lib/cli/ui/spinner/spin_group.rb', line 186

def wait
  idx = 0

  loop do
    all_done = true

    width = CLI::UI::Terminal.width

    @m.synchronize do
      CLI::UI.raw do
        @tasks.each.with_index do |task, int_index|
          nat_index = int_index + 1
          task_done = task.check
          all_done = false unless task_done

          if nat_index > @consumed_lines
            print(task.render(idx, true, width: width) + "\n")
            @consumed_lines += 1
          else
            offset = @consumed_lines - int_index
            move_to = CLI::UI::ANSI.cursor_up(offset) + "\r"
            move_from = "\r" + CLI::UI::ANSI.cursor_down(offset)

            print(move_to + task.render(idx, idx.zero?, width: width) + move_from)
          end
        end
      end
    end

    break if all_done

    idx = (idx + 1) % GLYPHS.size
    Spinner.index = idx
    sleep(PERIOD)
  end

  if @auto_debrief
    debrief
  else
    @m.synchronize do
      @tasks.all?(&:success)
    end
  end
end