diff --git a/cwriter/writer_posix.go b/cwriter/writer_posix.go index 2a7995a..fd8aea0 100644 --- a/cwriter/writer_posix.go +++ b/cwriter/writer_posix.go @@ -4,20 +4,9 @@ import ( "fmt" - "os" "syscall" "unsafe" ) - -var tty *os.File - -func init() { - var err error - tty, err = os.Open("/dev/tty") - if err != nil { - tty = os.Stdin - } -} func (w *Writer) clearLines() { for i := 0; i < w.lineCount; i++ { @@ -26,24 +15,13 @@ } } -// TerminalWidth returns width of the terminal. -func TerminalWidth() (int, error) { - w := new(window) - tio := syscall.TIOCGWINSZ - _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, - tty.Fd(), - uintptr(tio), - uintptr(unsafe.Pointer(w)), - ) - if errno != 0 { - return 0, errno +// GetTermSize returns the dimensions of the given terminal. +// the code is stolen from "golang.org/x/crypto/ssh/terminal" +func GetTermSize() (width, height int, err error) { + var dimensions [4]uint16 + + if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(syscall.Stdout), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&dimensions)), 0, 0, 0); err != 0 { + return -1, -1, err } - return int(w.Col), nil + return int(dimensions[1]), int(dimensions[0]), nil } - -type window struct { - Row uint16 - Col uint16 - Xpixel uint16 - Ypixel uint16 -} diff --git a/cwriter/writer_windows.go b/cwriter/writer_windows.go index fcd0131..64a68f6 100644 --- a/cwriter/writer_windows.go +++ b/cwriter/writer_windows.go @@ -20,29 +20,29 @@ procFillConsoleOutputAttribute = kernel32.NewProc("FillConsoleOutputAttribute") ) -type short int16 -type dword uint32 -type word uint16 +type ( + short int16 + word uint16 + dword uint32 -type coord struct { - x short - y short -} - -type smallRect struct { - left short - top short - right short - bottom short -} - -type consoleScreenBufferInfo struct { - size coord - cursorPosition coord - attributes word - window smallRect - maximumWindowSize coord -} + 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 { @@ -54,36 +54,37 @@ f, ok := w.out.(FdWriter) if ok && !isatty.IsTerminal(f.Fd()) { for i := 0; i < w.lineCount; i++ { - fmt.Fprintf(w.out, "%c[%dA", ESC, 0) // move the cursor up + fmt.Fprintf(w.out, "%c[%dA", ESC, 1) // move the cursor up fmt.Fprintf(w.out, "%c[2K\r", ESC) // clear the line } return } fd := f.Fd() - var csbi consoleScreenBufferInfo - procGetConsoleScreenBufferInfo.Call(fd, uintptr(unsafe.Pointer(&csbi))) + var info consoleScreenBufferInfo + procGetConsoleScreenBufferInfo.Call(fd, uintptr(unsafe.Pointer(&info))) for i := 0; i < w.lineCount; i++ { // move the cursor up - csbi.cursorPosition.y-- - procSetConsoleCursorPosition.Call(fd, uintptr(*(*int32)(unsafe.Pointer(&csbi.cursorPosition)))) + info.cursorPosition.y-- + procSetConsoleCursorPosition.Call(fd, uintptr(*(*int32)(unsafe.Pointer(&info.cursorPosition)))) // clear the line cursor := coord{ - x: csbi.window.left, - y: csbi.window.top + csbi.cursorPosition.y, + x: info.window.left, + y: info.window.top + info.cursorPosition.y, } var count, w dword - count = dword(csbi.size.x) + count = dword(info.size.x) procFillConsoleOutputCharacter.Call(fd, uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&w))) } } -// TerminalWidth returns width of the terminal. -func TerminalWidth() (int, error) { +// GetTermSize returns the dimensions of the given terminal. +// the code is stolen from "golang.org/x/crypto/ssh/terminal" +func GetTermSize() (width, height int, err error) { var info consoleScreenBufferInfo - _, _, errno := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(syscall.Stdout), uintptr(unsafe.Pointer(&info)), 0) - if errno != 0 { - return 0, errno + _, _, e := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(syscall.Stdout), uintptr(unsafe.Pointer(&info)), 0) + if e != 0 { + return 0, 0, error(e) } - return int(info.size.x) - 1, nil + return int(info.size.x), int(info.size.y), nil } diff --git a/progress.go b/progress.go index 788a5ca..4e3e06a 100644 --- a/progress.go +++ b/progress.go @@ -229,7 +229,7 @@ sort.Sort(SortableBarSlice(bars)) } - width, _ := cwriter.TerminalWidth() + width, _, _ := cwriter.GetTermSize() ibars := iBarsGen(bars, width) c := make(chan indexedBarBuffer) wg.Add(numDrawers)