Implements the 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) - Output to stderr (separate from --json stdout) Key changes: - Replaced tokio::sync::Mutex with std::sync::Mutex for sync context - Added shutdown_flag for clean watchdog thread shutdown - Added main_bar_for_watchdog reference for forced redraws - Changed TTY detection to use atty crate (cross-platform) - Set ProgressDrawTarget::stderr() explicitly Acceptance criteria: - Bar updates >= every 500ms during 1000-file grep - 5GB slow file: bar continues ticking via steady tick - Slow-file warning at 30s - Non-TTY: no bar (workers still process) - --no-progress forces off even on TTY - Bar goes to stderr; --json output to stdout uncontaminated - Final summary line printed on done Related: pdftract-43sg2 (ProgressEvent source) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
86 lines
3 KiB
Markdown
86 lines
3 KiB
Markdown
# 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)
|