Update updates the current progress and returns a formatted string In determinate mode: - TTY: Returns a visual progress bar with gradient and percentage - Non-TTY: Returns text percentage with human-readable sizes In indeterminate mode: - TTY: Returns a pulsing progress indicator - Non-TTY: Return
(current int64)
| 77 | // - TTY: Returns a pulsing progress indicator |
| 78 | // - Non-TTY: Returns processing indicator with current value |
| 79 | func (p *ProgressBar) Update(current int64) string { |
| 80 | p.current = current |
| 81 | p.updateCount++ // Increment counter for animation |
| 82 | |
| 83 | if progressLog.Enabled() && p.updateCount%100 == 0 { |
| 84 | // Log every 100 updates to avoid excessive logging |
| 85 | if p.indeterminate { |
| 86 | progressLog.Printf("Progress update: current=%d bytes, indeterminate mode", current) |
| 87 | } else { |
| 88 | percent := float64(current) / float64(p.total) * 100 |
| 89 | progressLog.Printf("Progress update: current=%d bytes, total=%d bytes, percent=%.1f%%", current, p.total, percent) |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | // Handle indeterminate mode |
| 94 | if p.indeterminate { |
| 95 | if !isTTY() { |
| 96 | // Fallback for non-TTY: "Processing... (512MB)" |
| 97 | if current == 0 { |
| 98 | return "Processing..." |
| 99 | } |
| 100 | return fmt.Sprintf("Processing... (%s)", formatBytes(current)) |
| 101 | } |
| 102 | // In TTY mode, show a pulsing indicator by cycling between 30% and 70% |
| 103 | // This creates a visual "breathing" effect that's more noticeable |
| 104 | // Using sine wave-like progression: 30% -> 50% -> 70% -> 50% -> 30% |
| 105 | pulseStep := p.updateCount % 8 // 8 steps for smoother animation |
| 106 | var pulsePercent float64 |
| 107 | if pulseStep < 4 { |
| 108 | // Rising: 30% -> 70% |
| 109 | pulsePercent = 0.3 + 0.4*float64(pulseStep)/3.0 |
| 110 | } else { |
| 111 | // Falling: 70% -> 30% |
| 112 | pulsePercent = 0.7 - 0.4*float64(pulseStep-4)/3.0 |
| 113 | } |
| 114 | return p.progress.ViewAs(pulsePercent) |
| 115 | } |
| 116 | |
| 117 | // Handle determinate mode with edge case: avoid division by zero |
| 118 | if p.total == 0 { |
| 119 | if isTTY() { |
| 120 | return p.progress.ViewAs(1.0) |
| 121 | } |
| 122 | return "100% (0B/0B)" |
| 123 | } |
| 124 | |
| 125 | percent := float64(current) / float64(p.total) |
| 126 | |
| 127 | if !isTTY() { |
| 128 | // Fallback for non-TTY: "50% (512MB/1024MB)" |
| 129 | return fmt.Sprintf("%d%% (%s/%s)", |
| 130 | int(percent*100), |
| 131 | formatBytes(current), |
| 132 | formatBytes(p.total)) |
| 133 | } |
| 134 | |
| 135 | return p.progress.ViewAs(percent) |
| 136 | } |