Codebase list golang-github-vbauerster-mpb / 4bef1e5
GetTermSize Vladimir Bauer 9 years ago
3 changed file(s) with 46 addition(s) and 67 deletion(s). Raw diff Collapse all Expand all
33
44 import (
55 "fmt"
6 "os"
76 "syscall"
87 "unsafe"
98 )
10
11 var tty *os.File
12
13 func init() {
14 var err error
15 tty, err = os.Open("/dev/tty")
16 if err != nil {
17 tty = os.Stdin
18 }
19 }
209
2110 func (w *Writer) clearLines() {
2211 for i := 0; i < w.lineCount; i++ {
2514 }
2615 }
2716
28 // TerminalWidth returns width of the terminal.
29 func TerminalWidth() (int, error) {
30 w := new(window)
31 tio := syscall.TIOCGWINSZ
32 _, _, errno := syscall.Syscall(syscall.SYS_IOCTL,
33 tty.Fd(),
34 uintptr(tio),
35 uintptr(unsafe.Pointer(w)),
36 )
37 if errno != 0 {
38 return 0, errno
17 // GetTermSize returns the dimensions of the given terminal.
18 // the code is stolen from "golang.org/x/crypto/ssh/terminal"
19 func GetTermSize() (width, height int, err error) {
20 var dimensions [4]uint16
21
22 if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(syscall.Stdout), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&dimensions)), 0, 0, 0); err != 0 {
23 return -1, -1, err
3924 }
40 return int(w.Col), nil
25 return int(dimensions[1]), int(dimensions[0]), nil
4126 }
42
43 type window struct {
44 Row uint16
45 Col uint16
46 Xpixel uint16
47 Ypixel uint16
48 }
1919 procFillConsoleOutputAttribute = kernel32.NewProc("FillConsoleOutputAttribute")
2020 )
2121
22 type short int16
23 type dword uint32
24 type word uint16
22 type (
23 short int16
24 word uint16
25 dword uint32
2526
26 type coord struct {
27 x short
28 y short
29 }
30
31 type smallRect struct {
32 left short
33 top short
34 right short
35 bottom short
36 }
37
38 type consoleScreenBufferInfo struct {
39 size coord
40 cursorPosition coord
41 attributes word
42 window smallRect
43 maximumWindowSize coord
44 }
27 coord struct {
28 x short
29 y short
30 }
31 smallRect struct {
32 left short
33 top short
34 right short
35 bottom short
36 }
37 consoleScreenBufferInfo struct {
38 size coord
39 cursorPosition coord
40 attributes word
41 window smallRect
42 maximumWindowSize coord
43 }
44 )
4545
4646 // FdWriter is a writer with a file descriptor.
4747 type FdWriter interface {
5353 f, ok := w.out.(FdWriter)
5454 if ok && !isatty.IsTerminal(f.Fd()) {
5555 for i := 0; i < w.lineCount; i++ {
56 fmt.Fprintf(w.out, "%c[%dA", ESC, 0) // move the cursor up
56 fmt.Fprintf(w.out, "%c[%dA", ESC, 1) // move the cursor up
5757 fmt.Fprintf(w.out, "%c[2K\r", ESC) // clear the line
5858 }
5959 return
6060 }
6161 fd := f.Fd()
62 var csbi consoleScreenBufferInfo
63 procGetConsoleScreenBufferInfo.Call(fd, uintptr(unsafe.Pointer(&csbi)))
62 var info consoleScreenBufferInfo
63 procGetConsoleScreenBufferInfo.Call(fd, uintptr(unsafe.Pointer(&info)))
6464
6565 for i := 0; i < w.lineCount; i++ {
6666 // move the cursor up
67 csbi.cursorPosition.y--
68 procSetConsoleCursorPosition.Call(fd, uintptr(*(*int32)(unsafe.Pointer(&csbi.cursorPosition))))
67 info.cursorPosition.y--
68 procSetConsoleCursorPosition.Call(fd, uintptr(*(*int32)(unsafe.Pointer(&info.cursorPosition))))
6969 // clear the line
7070 cursor := coord{
71 x: csbi.window.left,
72 y: csbi.window.top + csbi.cursorPosition.y,
71 x: info.window.left,
72 y: info.window.top + info.cursorPosition.y,
7373 }
7474 var count, w dword
75 count = dword(csbi.size.x)
75 count = dword(info.size.x)
7676 procFillConsoleOutputCharacter.Call(fd, uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&w)))
7777 }
7878 }
7979
80 // TerminalWidth returns width of the terminal.
81 func TerminalWidth() (int, error) {
80 // GetTermSize returns the dimensions of the given terminal.
81 // the code is stolen from "golang.org/x/crypto/ssh/terminal"
82 func GetTermSize() (width, height int, err error) {
8283 var info consoleScreenBufferInfo
83 _, _, errno := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(syscall.Stdout), uintptr(unsafe.Pointer(&info)), 0)
84 if errno != 0 {
85 return 0, errno
84 _, _, e := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(syscall.Stdout), uintptr(unsafe.Pointer(&info)), 0)
85 if e != 0 {
86 return 0, 0, error(e)
8687 }
87 return int(info.size.x) - 1, nil
88 return int(info.size.x), int(info.size.y), nil
8889 }
228228 sort.Sort(SortableBarSlice(bars))
229229 }
230230
231 width, _ := cwriter.TerminalWidth()
231 width, _, _ := cwriter.GetTermSize()
232232 ibars := iBarsGen(bars, width)
233233 c := make(chan indexedBarBuffer)
234234 wg.Add(numDrawers)