Class: CLI::UI::ProgressReporter::Reporter

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

Overview

Progress reporter instance that manages the lifecycle of progress reporting

Constant Summary collapse

OSC =

OSC (Operating System Command) escape sequences

"\e]"
ST =

String Terminator (BEL)

"\a"
REMOVE =

Progress states

0
SET_PROGRESS =
1
ERROR =
2
INDETERMINATE =
3
PAUSED =
4

Instance Method Summary collapse

Constructor Details

#initialize(mode, to = $stdout, parent: nil, delay_start: false) ⇒ Reporter

: (Symbol mode, ?io_like to, ?parent: Reporter?, ?delay_start: bool) -> void



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/cli/ui/progress_reporter.rb', line 27

def initialize(mode, to = $stdout, parent: nil, delay_start: false)
  @mode = mode
  @to = to
  @parent = parent
  @children = []
  @active = ProgressReporter.supports_progress? && @parent.nil?

  # Register with parent if nested
  @parent&.add_child(self)

  return unless @active
  return if delay_start # Don't emit initial OSC if delayed

  case mode
  when :indeterminate
    set_indeterminate
  when :progress
    set_progress(0)
  else
    raise ArgumentError, "Unknown progress mode: #{mode}"
  end
end

Instance Method Details

#add_child(child) ⇒ Object

: (Reporter child) -> void



51
52
53
# File 'lib/cli/ui/progress_reporter.rb', line 51

def add_child(child)
  @children << child
end

#cleanupObject

: -> void



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/cli/ui/progress_reporter.rb', line 137

def cleanup
  # Remove self from parent's children list
  @parent&.remove_child(self)

  # If parent exists and has no more children, restore its progress state
  if @parent && !@parent.has_active_children?
    case @parent.instance_variable_get(:@mode)
    when :indeterminate
      @parent.set_indeterminate
    when :progress
      # Parent progress bar should maintain its last state
      # The parent will handle re-emitting its progress on next tick
    end
  elsif !@parent
    # We're the root, clear progress
    clear
  end
end

#clearObject

: -> void



128
129
130
131
132
133
134
# File 'lib/cli/ui/progress_reporter.rb', line 128

def clear
  # Only clear if we're the root reporter and have no active children
  return unless @active
  return if has_active_children?

  @to.print("#{OSC}9;4;#{REMOVE};#{ST}")
end

#force_set_indeterminateObject

Force indeterminate mode even if there are children : -> void



99
100
101
102
103
104
# File 'lib/cli/ui/progress_reporter.rb', line 99

def force_set_indeterminate
  return unless @active

  @mode = :indeterminate
  @to.print("#{OSC}9;4;#{INDETERMINATE};#{ST}")
end

#force_set_progress(percentage) ⇒ Object

Force progress mode even if there are children - used by SpinGroup when a task needs to show deterministic progress : (Integer percentage) -> void



89
90
91
92
93
94
95
# File 'lib/cli/ui/progress_reporter.rb', line 89

def force_set_progress(percentage)
  return unless @active

  @mode = :progress
  percentage = percentage.clamp(0, 100)
  @to.print("#{OSC}9;4;#{SET_PROGRESS};#{percentage}#{ST}")
end

#has_active_children?Boolean

: -> bool

Returns:

  • (Boolean)


61
62
63
# File 'lib/cli/ui/progress_reporter.rb', line 61

def has_active_children?
  @children.any?
end

#remove_child(child) ⇒ Object

: (Reporter child) -> void



56
57
58
# File 'lib/cli/ui/progress_reporter.rb', line 56

def remove_child(child)
  @children.delete(child)
end

#set_errorObject

: -> void



107
108
109
110
111
112
# File 'lib/cli/ui/progress_reporter.rb', line 107

def set_error
  # Error state can be set even with children
  return unless @active

  @to.print("#{OSC}9;4;#{ERROR};#{ST}")
end

#set_indeterminateObject

: -> void



77
78
79
80
81
82
83
84
# File 'lib/cli/ui/progress_reporter.rb', line 77

def set_indeterminate
  # Don't emit progress if we have active children
  return if has_active_children?
  return unless @active

  @mode = :indeterminate # Update mode when switching to indeterminate
  @to.print("#{OSC}9;4;#{INDETERMINATE};#{ST}")
end

#set_paused(percentage = nil) ⇒ Object

: (?Integer? percentage) -> void



115
116
117
118
119
120
121
122
123
124
125
# File 'lib/cli/ui/progress_reporter.rb', line 115

def set_paused(percentage = nil)
  return if has_active_children?
  return unless @active

  if percentage
    percentage = percentage.clamp(0, 100)
    @to.print("#{OSC}9;4;#{PAUSED};#{percentage}#{ST}")
  else
    @to.print("#{OSC}9;4;#{PAUSED};#{ST}")
  end
end

#set_progress(percentage) ⇒ Object

: (Integer percentage) -> void



66
67
68
69
70
71
72
73
74
# File 'lib/cli/ui/progress_reporter.rb', line 66

def set_progress(percentage) # rubocop:disable Naming/AccessorMethodName
  # Don't emit progress if we have active children (they own the progress)
  return if has_active_children?
  return unless @active

  @mode = :progress # Update mode when switching to progress
  percentage = percentage.clamp(0, 100)
  @to.print("#{OSC}9;4;#{SET_PROGRESS};#{percentage}#{ST}")
end