all repos — llm_aggregator @ 4b4b37a236f75a04bd530d0a4ffaa1fb26b89a27

A CLI tool to aggregate RSS feeds and summarise them with LLMs

internal/progress/progress.go (view raw)

  1package progress
  2
  3import (
  4	"fmt"
  5	"io"
  6
  7	"llm_aggregator/internal/style"
  8)
  9
 10// Logger is the minimal interface for progress and verbose logging implementations.
 11type Logger interface {
 12	Logf(format string, args ...any)
 13	Warningf(format string, args ...any)
 14	Debugf(format string, args ...any)
 15}
 16
 17// Progress extends Logger with stage/count/timing reporting.
 18// Implementations: NoopLogger (no output), SimpleLogger (stdout), TUIProgress (tea messages).
 19type Progress interface {
 20	Logger
 21	SetStage(stage string)
 22	SetSubStage(status string)
 23	SetArticleCount(total, processed int)
 24	SetTokenEstimate(total, used int)
 25	StartWaiting()
 26}
 27
 28// SimpleLogger writes formatted output to an io.Writer.
 29type SimpleLogger struct {
 30	writer io.Writer
 31	debug  bool
 32}
 33
 34// NewSimpleLogger creates a SimpleLogger; set debug=true to enable Debugf output.
 35func NewSimpleLogger(writer io.Writer, debug bool) *SimpleLogger {
 36	return &SimpleLogger{
 37		writer: writer,
 38		debug:  debug,
 39	}
 40}
 41
 42func (sl *SimpleLogger) Logf(format string, args ...any) {
 43	_, _ = fmt.Fprintf(sl.writer, format+"\n", args...)
 44}
 45
 46func (sl *SimpleLogger) Warningf(format string, args ...any) {
 47	// Use style.Warningf for orange bold WARNING prefix
 48	_, _ = fmt.Fprintf(sl.writer, "%s\n", style.Warningf(format, args...))
 49}
 50
 51func (sl *SimpleLogger) Debugf(format string, args ...any) {
 52	if sl.debug {
 53		// Use style.Debugf for styled debug output
 54		_, _ = fmt.Fprintf(sl.writer, "%s\n", style.Debugf(format, args...))
 55	}
 56}
 57
 58func (sl *SimpleLogger) SetStage(stage string)                      {}
 59func (sl *SimpleLogger) SetSubStage(stage string)                   {}
 60func (sl *SimpleLogger) SetArticleCount(total, processed int)       {}
 61func (sl *SimpleLogger) SetTokenEstimate(total, used int)           {}
 62func (sl *SimpleLogger) StartWaiting()                            {}
 63
 64// NoopLogger discards all output. Used as the default when no progress is desired.
 65type NoopLogger struct{}
 66
 67func (nl *NoopLogger) Logf(format string, args ...any)      {}
 68func (nl *NoopLogger) Warningf(format string, args ...any)  {}
 69func (nl *NoopLogger) Debugf(format string, args ...any)    {}
 70func (nl *NoopLogger) SetStage(stage string)                      {}
 71func (nl *NoopLogger) SetSubStage(status string)                  {}
 72func (nl *NoopLogger) SetArticleCount(total, processed int)        {}
 73func (nl *NoopLogger) SetTokenEstimate(total, used int)           {}
 74func (nl *NoopLogger) StartWaiting()                            {}
 75
 76// Context wraps a Logger and guards against nil receiver.
 77type Context struct {
 78	logger Logger
 79}
 80
 81// NewContext wraps a Logger. Passing nil produces a no-op context.
 82func NewContext(logger Logger) *Context {
 83	return &Context{
 84		logger: logger,
 85	}
 86}
 87
 88// Logf logs a message
 89func (c *Context) Logf(format string, args ...any) {
 90	if c.logger != nil {
 91		c.logger.Logf(format, args...)
 92	}
 93}
 94
 95// Warningf logs a warning
 96func (c *Context) Warningf(format string, args ...any) {
 97	if c.logger != nil {
 98		c.logger.Warningf(format, args...)
 99	}
100}
101
102// Debugf logs a debug message
103func (c *Context) Debugf(format string, args ...any) {
104	if c.logger != nil {
105		c.logger.Debugf(format, args...)
106	}
107}