Codebase list golang-github-vbauerster-mpb / da4b012
utilize bytes.Buffer.ReadFrom Vladimir Bauer 8 years ago
5 changed file(s) with 46 addition(s) and 55 deletion(s). Raw diff Collapse all Expand all
33 "bytes"
44 "fmt"
55 "io"
6 "strings"
67 "sync"
78 "time"
89 "unicode/utf8"
6768 char rune
6869 till int64
6970 }
70 writeBuf struct {
71 buf []byte
72 completeAfterFlush bool
71 bufReader struct {
72 io.Reader
73 complete bool
7374 }
7475 )
7576
285286 }
286287 }
287288
288 func (b *Bar) render(tw int, prependWs, appendWs *widthSync) <-chan *writeBuf {
289 ch := make(chan *writeBuf, 1)
289 func (b *Bar) render(tw int, prependWs, appendWs *widthSync) <-chan *bufReader {
290 ch := make(chan *bufReader, 1)
290291
291292 go func() {
292293 select {
298299 s.prependFuncs = nil
299300 s.appendFuncs = nil
300301
301 ch <- &writeBuf{[]byte(s.panic), true}
302 ch <- &bufReader{strings.NewReader(s.panic), true}
302303 }
303304 close(ch)
304305 }()
305306 s.draw(tw, prependWs, appendWs)
306 ch <- &writeBuf{s.toBytes(), s.completed}
307 ch <- &bufReader{io.MultiReader(s.bufP, s.bufB, s.bufA), s.completed}
307308 }:
308309 case <-b.done:
309310 s := b.cacheState
310 var buf []byte
311 var r io.Reader
311312 if s.panic != "" {
312 buf = []byte(s.panic)
313 r = strings.NewReader(s.panic)
313314 } else {
314315 s.draw(tw, prependWs, appendWs)
315 buf = s.toBytes()
316 r = io.MultiReader(s.bufP, s.bufB, s.bufA)
316317 }
317 ch <- &writeBuf{buf, false}
318 ch <- &bufReader{r, false}
318319 close(ch)
319320 }
320321 }()
321322
322323 return ch
323 }
324
325 func (s *state) toBytes() []byte {
326 buf := make([]byte, 0, s.bufP.Len()+s.bufB.Len()+s.bufA.Len())
327 buf = concatenateBlocks(buf, s.bufP.Bytes(), s.bufB.Bytes(), s.bufA.Bytes())
328 return buf
329324 }
330325
331326 func (s *state) updateTimePerItemEstimate(amount int, now, next time.Time) {
432427 }
433428 }
434429
435 func concatenateBlocks(buf []byte, blocks ...[]byte) []byte {
436 for _, block := range blocks {
437 buf = append(buf, block...)
438 }
439 return buf
440 }
441
442430 func (s *state) updateFormat(format string) {
443431 for i, n := 0, 0; len(format) > 0; i++ {
444432 s.format[i], n = utf8.DecodeRuneInString(format)
1717 // Writer is a buffered the writer that updates the terminal.
1818 // The contents of writer will be flushed when Flush is called.
1919 type Writer struct {
20 out io.Writer
21
20 out io.Writer
2221 buf bytes.Buffer
2322 lineCount int
2423 }
2524
2625 // New returns a new Writer with defaults
2726 func New(w io.Writer) *Writer {
28 return &Writer{
29 out: w,
30 }
27 return &Writer{out: w}
3128 }
3229
3330 // Flush flushes the underlying buffer
3431 func (w *Writer) Flush() error {
35 // Do nothing if buffer is empty
36 if w.buf.Len() == 0 {
37 return nil
32 err := w.clearLines()
33 w.lineCount = bytes.Count(w.buf.Bytes(), []byte("\n"))
34 // WriteTo takes care of w.buf.Reset
35 if _, e := w.buf.WriteTo(w.out); err == nil {
36 err = e
3837 }
39 w.clearLines()
40 w.lineCount = bytes.Count(w.buf.Bytes(), []byte("\n"))
41 _, err := w.out.Write(w.buf.Bytes())
42 w.buf.Reset()
4338 return err
4439 }
4540
46 // Write save the contents of b to its buffers. The only errors returned are ones encountered while writing to the underlying buffer.
47 func (w *Writer) Write(b []byte) (n int, err error) {
48 return w.buf.Write(b)
41 // Write appends the contents of p to the underlying buffer
42 func (w *Writer) Write(p []byte) (n int, err error) {
43 return w.buf.Write(p)
4944 }
5045
46 // WriteString writes string to the underlying buffer
5147 func (w *Writer) WriteString(s string) (n int, err error) {
5248 return w.buf.WriteString(s)
5349 }
50
51 // ReadFrom reads from the provided io.Reader and writes to the underlying buffer.
52 func (w *Writer) ReadFrom(r io.Reader) (n int64, err error) {
53 return w.buf.ReadFrom(r)
54 }
22 package cwriter
33
44 import (
5 "fmt"
5 "io"
66 "strings"
77 "syscall"
88 "unsafe"
99 )
1010
11 func (w *Writer) clearLines() {
12 fmt.Fprint(w.out, strings.Repeat(clearCursorAndLine, w.lineCount))
11 func (w *Writer) clearLines() error {
12 _, err := io.WriteString(w.out, strings.Repeat(clearCursorAndLine, w.lineCount))
13 return err
1314 }
1415
1516 // TermSize returns the dimensions of the given terminal.
22 package cwriter
33
44 import (
5 "fmt"
65 "io"
6 "strings"
77 "syscall"
88 "unsafe"
9 "strings"
9
1010 "github.com/mattn/go-isatty"
1111 )
1212
4949 Fd() uintptr
5050 }
5151
52 func (w *Writer) clearLines() {
52 func (w *Writer) clearLines() error {
5353 f, ok := w.out.(FdWriter)
5454 if ok && !isatty.IsTerminal(f.Fd()) {
55 fmt.Fprint(w.out, strings.Repeat(clearCursorAndLine, w.lineCount))
56 return
55 _, err := io.WriteString(w.out, strings.Repeat(clearCursorAndLine, w.lineCount))
56 return err
5757 }
5858 fd := f.Fd()
5959 var info consoleScreenBufferInfo
7272 count = dword(info.size.x)
7373 procFillConsoleOutputCharacter.Call(fd, uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&w)))
7474 }
75 return nil
7576 }
7677
77 // GetTermSize returns the dimensions of the given terminal.
78 // TermSize returns the dimensions of the given terminal.
7879 // the code is stolen from "golang.org/x/crypto/ssh/terminal"
79 func GetTermSize() (width, height int, err error) {
80 func TermSize() (width, height int, err error) {
8081 var info consoleScreenBufferInfo
8182 _, _, e := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(syscall.Stdout), uintptr(unsafe.Pointer(&info)), 0)
8283 if e != 0 {
294294 prependWs := newWidthSync(wSyncTimeout, len(p.bars), numP)
295295 appendWs := newWidthSync(wSyncTimeout, len(p.bars), numA)
296296
297 sequence := make([]<-chan *writeBuf, len(p.bars))
297 sequence := make([]<-chan *bufReader, len(p.bars))
298298 for i, b := range p.bars {
299299 sequence[i] = b.render(tw, prependWs, appendWs)
300300 }
301301
302302 var i int
303 for b := range fanIn(sequence...) {
304 _, err = p.cw.Write(b.buf)
303 for r := range fanIn(sequence...) {
304 _, err = p.cw.ReadFrom(r)
305305 defer func(bar *Bar, complete bool) {
306306 if complete {
307307 bar.Complete()
308308 }
309 }(p.bars[i], b.completeAfterFlush)
309 }(p.bars[i], r.complete)
310310 i++
311311 }
312312
320320 return
321321 }
322322
323 func fanIn(inputs ...<-chan *writeBuf) <-chan *writeBuf {
324 ch := make(chan *writeBuf)
323 func fanIn(inputs ...<-chan *bufReader) <-chan *bufReader {
324 ch := make(chan *bufReader)
325325
326326 go func() {
327327 defer close(ch)