summaryrefslogtreecommitdiff
path: root/vendor/github.com/vbauerster/mpb/cwriter
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/vbauerster/mpb/cwriter')
-rw-r--r--vendor/github.com/vbauerster/mpb/cwriter/writer.go78
-rw-r--r--vendor/github.com/vbauerster/mpb/cwriter/writer_posix.go13
-rw-r--r--vendor/github.com/vbauerster/mpb/cwriter/writer_windows.go77
3 files changed, 168 insertions, 0 deletions
diff --git a/vendor/github.com/vbauerster/mpb/cwriter/writer.go b/vendor/github.com/vbauerster/mpb/cwriter/writer.go
new file mode 100644
index 000000000..0b1470d4c
--- /dev/null
+++ b/vendor/github.com/vbauerster/mpb/cwriter/writer.go
@@ -0,0 +1,78 @@
+package cwriter
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+ "os"
+
+ isatty "github.com/mattn/go-isatty"
+ "golang.org/x/crypto/ssh/terminal"
+)
+
+// ESC is the ASCII code for escape character
+const ESC = 27
+
+var NotATTY = errors.New("not a terminal")
+
+var (
+ cursorUp = fmt.Sprintf("%c[%dA", ESC, 1)
+ clearLine = fmt.Sprintf("%c[2K\r", ESC)
+ clearCursorAndLine = cursorUp + clearLine
+)
+
+// Writer is a buffered the writer that updates the terminal.
+// The contents of writer will be flushed when Flush is called.
+type Writer struct {
+ out io.Writer
+ buf bytes.Buffer
+ isTerminal bool
+ fd int
+ lineCount int
+}
+
+// New returns a new Writer with defaults
+func New(out io.Writer) *Writer {
+ w := &Writer{out: out}
+ if f, ok := out.(*os.File); ok {
+ fd := f.Fd()
+ w.isTerminal = isatty.IsTerminal(fd)
+ w.fd = int(fd)
+ }
+ return w
+}
+
+// Flush flushes the underlying buffer
+func (w *Writer) Flush(lineCount int) error {
+ err := w.clearLines()
+ w.lineCount = lineCount
+ // WriteTo takes care of w.buf.Reset
+ if _, e := w.buf.WriteTo(w.out); err == nil {
+ err = e
+ }
+ return err
+}
+
+// Write appends the contents of p to the underlying buffer
+func (w *Writer) Write(p []byte) (n int, err error) {
+ return w.buf.Write(p)
+}
+
+// WriteString writes string to the underlying buffer
+func (w *Writer) WriteString(s string) (n int, err error) {
+ return w.buf.WriteString(s)
+}
+
+// ReadFrom reads from the provided io.Reader and writes to the underlying buffer.
+func (w *Writer) ReadFrom(r io.Reader) (n int64, err error) {
+ return w.buf.ReadFrom(r)
+}
+
+func (w *Writer) GetWidth() (int, error) {
+ if w.isTerminal {
+ tw, _, err := terminal.GetSize(w.fd)
+ return tw, err
+ }
+ return -1, NotATTY
+}
diff --git a/vendor/github.com/vbauerster/mpb/cwriter/writer_posix.go b/vendor/github.com/vbauerster/mpb/cwriter/writer_posix.go
new file mode 100644
index 000000000..05e31c480
--- /dev/null
+++ b/vendor/github.com/vbauerster/mpb/cwriter/writer_posix.go
@@ -0,0 +1,13 @@
+// +build !windows
+
+package cwriter
+
+import (
+ "io"
+ "strings"
+)
+
+func (w *Writer) clearLines() error {
+ _, err := io.WriteString(w.out, strings.Repeat(clearCursorAndLine, w.lineCount))
+ return err
+}
diff --git a/vendor/github.com/vbauerster/mpb/cwriter/writer_windows.go b/vendor/github.com/vbauerster/mpb/cwriter/writer_windows.go
new file mode 100644
index 000000000..dad7f50b2
--- /dev/null
+++ b/vendor/github.com/vbauerster/mpb/cwriter/writer_windows.go
@@ -0,0 +1,77 @@
+// +build windows
+
+package cwriter
+
+import (
+ "io"
+ "strings"
+ "syscall"
+ "unsafe"
+
+ "github.com/mattn/go-isatty"
+)
+
+var kernel32 = syscall.NewLazyDLL("kernel32.dll")
+
+var (
+ procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
+ procSetConsoleCursorPosition = kernel32.NewProc("SetConsoleCursorPosition")
+ procFillConsoleOutputCharacter = kernel32.NewProc("FillConsoleOutputCharacterW")
+ procFillConsoleOutputAttribute = kernel32.NewProc("FillConsoleOutputAttribute")
+)
+
+type (
+ short int16
+ word uint16
+ dword uint32
+
+ coord struct {
+ x short
+ y short
+ }
+ smallRect struct {
+ left short
+ top short
+ right short
+ bottom short
+ }
+ consoleScreenBufferInfo struct {
+ size coord
+ cursorPosition coord
+ attributes word
+ window smallRect
+ maximumWindowSize coord
+ }
+)
+
+// FdWriter is a writer with a file descriptor.
+type FdWriter interface {
+ io.Writer
+ Fd() uintptr
+}
+
+func (w *Writer) clearLines() error {
+ f, ok := w.out.(FdWriter)
+ if ok && !isatty.IsTerminal(f.Fd()) {
+ _, err := io.WriteString(w.out, strings.Repeat(clearCursorAndLine, w.lineCount))
+ return err
+ }
+ fd := f.Fd()
+ var info consoleScreenBufferInfo
+ procGetConsoleScreenBufferInfo.Call(fd, uintptr(unsafe.Pointer(&info)))
+
+ for i := 0; i < w.lineCount; i++ {
+ // move the cursor up
+ info.cursorPosition.y--
+ procSetConsoleCursorPosition.Call(fd, uintptr(*(*int32)(unsafe.Pointer(&info.cursorPosition))))
+ // clear the line
+ cursor := coord{
+ x: info.window.left,
+ y: info.window.top + info.cursorPosition.y,
+ }
+ var count, w dword
+ count = dword(info.size.x)
+ procFillConsoleOutputCharacter.Call(fd, uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&w)))
+ }
+ return nil
+}