github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/internal/hud/printer.go (about)

     1  package hud
     2  
     3  import (
     4  	"io"
     5  	"time"
     6  
     7  	"github.com/tilt-dev/tilt/pkg/model/logstore"
     8  )
     9  
    10  var backoffInit = 5 * time.Second
    11  var backoffMultiplier = time.Duration(2)
    12  
    13  type Stdout io.Writer
    14  
    15  type IncrementalPrinter struct {
    16  	progress map[progressKey]progressStatus
    17  	stdout   Stdout
    18  }
    19  
    20  func NewIncrementalPrinter(stdout Stdout) *IncrementalPrinter {
    21  	return &IncrementalPrinter{
    22  		progress: make(map[progressKey]progressStatus),
    23  		stdout:   stdout,
    24  	}
    25  }
    26  
    27  func (p *IncrementalPrinter) PrintNewline() {
    28  	_, _ = io.WriteString(p.stdout, "\n")
    29  }
    30  
    31  func (p *IncrementalPrinter) Print(lines []logstore.LogLine) {
    32  	for _, line := range lines {
    33  		// Naive progress implementation: skip lines that have already been printed
    34  		// recently. This works with any output stream.
    35  		//
    36  		// TODO(nick): Use ANSI codes to overwrite previous lines. It requires
    37  		// a little extra bookkeeping about where to find the progress line,
    38  		// and only works on terminals.
    39  		progressID := line.ProgressID
    40  		key := progressKey{spanID: line.SpanID, progressID: progressID}
    41  		if progressID != "" {
    42  			status, hasBeenPrinted := p.progress[key]
    43  			shouldPrint := line.ProgressMustPrint ||
    44  				!hasBeenPrinted ||
    45  				line.Time.Sub(status.lastPrinted) > status.printWait
    46  			if !shouldPrint {
    47  				continue
    48  			}
    49  		}
    50  		_, _ = io.WriteString(p.stdout, line.Text)
    51  
    52  		if progressID != "" {
    53  			status := p.progress[key]
    54  			newWait := backoffInit
    55  			if status.printWait > 0 {
    56  				newWait = backoffMultiplier * status.printWait
    57  			}
    58  			p.progress[key] = progressStatus{
    59  				lastPrinted: line.Time,
    60  				printWait:   newWait,
    61  			}
    62  		}
    63  	}
    64  }
    65  
    66  type progressKey struct {
    67  	spanID     logstore.SpanID
    68  	progressID string
    69  }
    70  
    71  type progressStatus struct {
    72  	lastPrinted time.Time
    73  	printWait   time.Duration
    74  }