github.com/pachyderm/pachyderm@v1.13.4/src/server/pkg/tabwriter/tabwriter.go (about)

     1  package tabwriter
     2  
     3  import (
     4  	"bytes"
     5  	"io"
     6  
     7  	"github.com/juju/ansiterm"
     8  )
     9  
    10  const (
    11  	// termHeight is the default height of a terminal.
    12  	termHeight = 50
    13  )
    14  
    15  // Writer is like tabwriter.Writer in the stdlib except that it's suitable for
    16  // large numbers of items because it periodically flushes its contents and
    17  // reprints a header when it does.
    18  type Writer struct {
    19  	w      *ansiterm.TabWriter
    20  	lines  int
    21  	header []byte
    22  }
    23  
    24  // NewWriter returns a new Writer, it will flush when
    25  // it gets termHeight many lines, including the header line.
    26  // The header line will be reprinted termHeight many lines have been written.
    27  // NewStreamingWriter will panic if it's given a header that doesn't end in \n.
    28  func NewWriter(w io.Writer, header string) *Writer {
    29  	if header[len(header)-1] != '\n' {
    30  		panic("header must end in a new line")
    31  	}
    32  	tabwriter := ansiterm.NewTabWriter(w, 0, 1, 1, ' ', 0)
    33  	tabwriter.Write([]byte(header))
    34  	return &Writer{
    35  		w:      tabwriter,
    36  		lines:  1, // 1 because we just printed the header
    37  		header: []byte(header),
    38  	}
    39  }
    40  
    41  // Write writes a line to the tabwriter.
    42  func (w *Writer) Write(buf []byte) (int, error) {
    43  	if w.lines >= termHeight {
    44  		if err := w.Flush(); err != nil {
    45  			return 0, err
    46  		}
    47  		if _, err := w.w.Write(w.header); err != nil {
    48  			return 0, err
    49  		}
    50  		w.lines++
    51  	}
    52  	w.lines += bytes.Count(buf, []byte{'\n'})
    53  	return w.w.Write(buf)
    54  }
    55  
    56  // Flush flushes the underlying tab writer.
    57  func (w *Writer) Flush() error {
    58  	w.lines = 0
    59  	return w.w.Flush()
    60  }