| package progress | |
| import ( | |
| "bytes" | |
| "fmt" | |
| "io" | |
| ) | |
| // Writer buffers writes until flush, at which time the last screen is cleared | |
| // and the current buffer contents are written. This is useful for | |
| // implementing progress displays, such as those implemented in docker and | |
| // git. | |
| type Writer struct { | |
| buf bytes.Buffer | |
| w io.Writer | |
| lines int | |
| } | |
| func NewWriter(w io.Writer) *Writer { | |
| return &Writer{ | |
| w: w, | |
| } | |
| } | |
| func (w *Writer) Write(p []byte) (n int, err error) { | |
| return w.buf.Write(p) | |
| } | |
| // Flush should be called when refreshing the current display. | |
| func (w *Writer) Flush() error { | |
| if w.buf.Len() == 0 { | |
| return nil | |
| } | |
| if err := w.clear(); err != nil { | |
| return err | |
| } | |
| w.lines = bytes.Count(w.buf.Bytes(), []byte("\n")) | |
| if _, err := w.w.Write(w.buf.Bytes()); err != nil { | |
| return err | |
| } | |
| w.buf.Reset() | |
| return nil | |
| } | |
| // TODO(stevvooe): The following are system specific. Break these out if we | |
| // decide to build this package further. | |
| func (w *Writer) clear() error { | |
| for i := 0; i < w.lines; i++ { | |
| if _, err := fmt.Fprintf(w.w, "\x1b[0A\x1b[2K\r"); err != nil { | |
| return err | |
| } | |
| } | |
| return nil | |
| } |