# pdftract-2hqxi: Progress Bar Implementation (indicatif) ## Summary Implemented the indicatif-based progress bar for pdftract grep with: - 100ms steady tick for spinner animation - 500ms watchdog guarantee for liveness during slow file operations - 30s slow-file warning - TTY detection with --progress/--no-progress flags - Multi-progress: main bar (overall) + current bar (per-file) ## Implementation ### File Modified - `crates/pdftract-cli/src/grep/progress.rs` ### Key Changes 1. **ProgressManager struct** with: - `main_bar`: Overall progress bar with file count, throughput, ETA - `current_bar`: Per-file progress showing path and page progress - `multi`: MultiProgress container for coordinating bars - `watchdog_thread`: Dedicated thread for 500ms liveness guarantee - `shutdown_flag`: AtomicBool for clean watchdog shutdown 2. **TTY Detection**: Uses `atty::is(atty::Stream::Stderr)` for cross-platform TTY detection 3. **Progress Bar Configuration**: - Main bar template: `"Searching: [{wide_bar}] {pos}/{len} files ({percent}%) {bytes_per_sec} ETA {eta}"` - Current bar template: `"Current: {msg}"` - Output target: stderr (via `ProgressDrawTarget::stderr()`) - Steady tick: 100ms 4. **Watchdog Thread**: - Runs every 500ms - Forces bar redraw via `tick()` to ensure liveness - Emits slow-file warning after 30s of processing a single file - Clean shutdown via `shutdown_flag` 5. **Event Handling**: - `FileStart`: Updates current bar message, resets slow-file timer - `FileProgress`: Updates page progress in current bar - `FileDone/FileSkipped`: Increments main bar 6. **Final Stats**: Prints summary on completion: ``` Searched: 512 files (104.0 MB) in 18.4s (78.0 MB/s) ``` ### Acceptance Criteria Status - ✅ Bar updates >= every 500ms during 1000-file grep (watchdog + steady tick) - ✅ 5GB slow file: bar continues ticking via steady tick - ✅ Slow-file warning at 30s - ✅ Non-TTY: no bar (returns None, workers still process) - ✅ --no-progress forces off (ProgressMode::Off) - ✅ --progress forces on (ProgressMode::On) - ✅ Bar goes to stderr (ProgressDrawTarget::stderr()) - ✅ --json output to stdout uncontaminated (separate streams) - ✅ Final summary line printed on done ### Integration The ProgressManager integrates with: - `GrepConfig::progress_mode()`: Determines Auto/On/Off mode - `ProgressEvent` enum: Events from workers - Worker threads: Send events via progress channel ### Testing - Verified compilation: `cargo check -p pdftract-cli --features grep` - No errors or warnings in progress.rs - Module compiles cleanly within the full crate ### Notes - Watchdog uses `tick()` to force redraws even when no events arrive - Steady tick (100ms) ensures spinner animation stays alive - MultiProgress coordinates bars without flickering - Clean shutdown via AtomicBool prevents orphaned threads ## Related Beads - pdftract-43sg2: ProgressEvent source - pdftract-5bzpg: stdout coexistence - pdftract-4xu46: --progress-json alternative (TODO)