cli-progress-bar-ansi
~/
├── go.mod — Module definition
├── ansi.go — ANSI escape code constants & helpers
├── bar.go — ProgressBar type (thread-safe, format, ETA, throughput)
├── manager.go — Manager (multiple bars, SIGWINCH, render loop)
├── bar_test.go — Unit tests for ProgressBar
├── manager_test.go — Unit tests for Manager & SIGWINCH
└── example_test.go — Integration example tests
ansi.go — Terminal control primitives using ANSI escape codes:
const (
ansiSave = "\033[s"
ansiRestore = "\033[u"
ansiHide = "\033[?25l"
ansiShow = "\033[?25h"
ansiErase = "\033[K"
ansiReset = "\033[0m"
ansiCyan = "\033[36m"
ansiGreen = "\033[32m"
ansiYellow = "\033[33m"
ansiBold = "\033[1m"
)
bar.go — Thread-safe ProgressBar with sync.Mutex protecting all state. Key methods:
New(total int64) / NewNamed(name string, total int64) — constructorsAdd(n int64) — atomically increment, auto-closes done channel on completionSet(n int64) — jump to specific value, clamps to totalDone() — mark finished immediatelyformat(width int) — renders a single bar line with: [name] [███████░░░░░] 45% | 1.2 MB/s | ETA 5sThe bar intelligently allocates space: name → bar → percentage → throughput → ETA. Bar color changes: cyan (<40%), yellow (40–99%), green (100%).
manager.go — Multi-bar manager with goroutine-based render loop:
NewManager() — detects terminal width, registers SIGWINCH handlerAddBar(pb) — thread-safe bar registrationStart() — launches background render goroutine (100ms ticker)Stop() — restores cursor, clears bars, stops signal handlerWait() — blocks on all bars' done channels, then calls Stop()render() — uses \033[nA/\033[nB cursor movement to update bars in-placeupdateTermSize() — called on SIGWINCH to re-measure terminal widthm := progress.NewManager()
defer m.Stop()
pb := progress.NewNamed("download", 100)
m.AddBar(pb)
m.Start()
for i := int64(0); i <= 100; i++ {
pb.Set(i)
time.Sleep(50 * time.Millisecond)
}
m.Wait()
All **32 unit tests pass** covering: | Category | Tests | What's verified | |---|---|---| | **Basic ops** | `TestNewProgressBar`, `TestNewNamed`, `TestAdd`, `TestSet`, `TestDone`, `TestSetName` | Constructor, increment, set, finish | | **Edge cases** | `TestAddOverflow`, `TestSetOverflow`, `TestAddAfterFinished`, `TestFormatZeroTotal`, `TestFormatComplete` | Clamping, no-ops after done, 0 total, 100% | | **Formatting** | `TestFormatPartial`, `TestFormatNarrowWidth`, `TestFormatBytes`, `TestFormatDuration` | Name, bar chars, percentage, narrow terminals, byte units (B/KB/MB/GB), duration (s/m/h) | | **Timing** | `TestFormatThroughput`, `TestFormatETA` | Rate calculation, ETA display | | **Concurrency** | `TestConcurrentAdd`, `TestIsFinishedConcurrent` | 10 goroutines adding 100 each; concurrent reads | | **Manager** | `TestNewManager`, `TestManagerAddBar`, `TestManagerStop`, `TestManagerWait`, `TestManagerMultipleBars`, `TestManagerRenderEmpty` | Lifecycle, multi-bar, double-stop safety | | **SIGWINCH** | `TestSIGWINCH` | Signal delivery, no crash, manager still functional | | **Terminal** | `TestTermWidthFallback`, `TestManagerSetOutput` | Width detection, output redirection | The ANSI rendering was observed in test output showing real bar characters (`█`, `░`), color codes (`\033[36m` cyan, `\033[33m` yellow, `\033[32m` green), cursor movement (`\033[nA`/`\033[nB`), and hide/show cursor (`\033[?25l`/`\033[?25h`). ---
{"model": "claude-sonnet-4-20250514", "problem_class": "cli-progress-bar-ansi", "result": "passed", "tests": 32}~/
├── go.mod — Module definition
├── ansi.go — ANSI escape code constants & helpers
├── bar.go — ProgressBar type (thread-safe, format, ETA, throughput)
├── manager.go — Manager (multiple bars, SIGWINCH, render loop)
├── bar_test.go — Unit tests for ProgressBar
├── manager_test.go — Unit tests for Manager & SIGWINCH
└── example_test.go — Integration example tests
ansi.go — Terminal control primitives using ANSI escape codes:
const (
ansiSave = "\033[s"
ansiRestore = "\033[u"
ansiHide = "\033[?25l"
ansiShow = "\033[?25h"
ansiErase = "\033[K"
ansiReset = "\033[0m"
ansiCyan = "\033[36m"
ansiGreen = "\033[32m"
ansiYellow = "\033[33m"
ansiBold = "\033[1m"
)
bar.go — Thread-safe ProgressBar with sync.Mutex protecting all state. Key methods:
New(total int64) / NewNamed(name string, total int64) — constructorsAdd(n int64) — atomically increment, auto-closes done channel on completionSet(n int64) — jump to specific value, clamps to totalDone() — mark finished immediatelyformat(width int) — renders a single bar line with: [name] [███████░░░░░] 45% | 1.2 MB/s | ETA 5sThe bar intelligently allocates space: name → bar → percentage → throughput → ETA. Bar color changes: cyan (<40%), yellow (40–99%), green (100%).
manager.go — Multi-bar manager with goroutine-based render loop:
NewManager() — detects terminal width, registers SIGWINCH handlerAddBar(pb) — thread-safe bar registrationStart() — launches background render goroutine (100ms ticker)Stop() — restores cursor, clears bars, stops signal handlerWait() — blocks on all bars' done channels, then calls Stop()render() — uses \033[nA/\033[nB cursor movement to update bars in-placeupdateTermSize() — called on SIGWINCH to re-measure terminal widthm := progress.NewManager()
defer m.Stop()
pb := progress.NewNamed("download", 100)
m.AddBar(pb)
m.Start()
for i := int64(0); i <= 100; i++ {
pb.Set(i)
time.Sleep(50 * time.Millisecond)
}
m.Wait()
All **32 unit tests pass** covering: | Category | Tests | What's verified | |---|---|---| | **Basic ops** | `TestNewProgressBar`, `TestNewNamed`, `TestAdd`, `TestSet`, `TestDone`, `TestSetName` | Constructor, increment, set, finish | | **Edge cases** | `TestAddOverflow`, `TestSetOverflow`, `TestAddAfterFinished`, `TestFormatZeroTotal`, `TestFormatComplete` | Clamping, no-ops after done, 0 total, 100% | | **Formatting** | `TestFormatPartial`, `TestFormatNarrowWidth`, `TestFormatBytes`, `TestFormatDuration` | Name, bar chars, percentage, narrow terminals, byte units (B/KB/MB/GB), duration (s/m/h) | | **Timing** | `TestFormatThroughput`, `TestFormatETA` | Rate calculation, ETA display | | **Concurrency** | `TestConcurrentAdd`, `TestIsFinishedConcurrent` | 10 goroutines adding 100 each; concurrent reads | | **Manager** | `TestNewManager`, `TestManagerAddBar`, `TestManagerStop`, `TestManagerWait`, `TestManagerMultipleBars`, `TestManagerRenderEmpty` | Lifecycle, multi-bar, double-stop safety | | **SIGWINCH** | `TestSIGWINCH` | Signal delivery, no crash, manager still functional | | **Terminal** | `TestTermWidthFallback`, `TestManagerSetOutput` | Width detection, output redirection | The ANSI rendering was observed in test output showing real bar characters (`█`, `░`), color codes (`\033[36m` cyan, `\033[33m` yellow, `\033[32m` green), cursor movement (`\033[nA`/`\033[nB`), and hide/show cursor (`\033[?25l`/`\033[?25h`). ---
{"model": "claude-sonnet-4-20250514", "problem_class": "cli-progress-bar-ansi", "result": "passed", "tests": 32}