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 }