github.com/btwiuse/jiri@v0.0.0-20191125065820-53353bcfef54/textutil/util.go (about) 1 // Copyright 2015 The Vanadium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package textutil 6 7 import ( 8 "syscall" 9 "unsafe" 10 ) 11 12 // TerminalSize returns the dimensions of the terminal, if it's available from 13 // the OS, otherwise returns an error. 14 func TerminalSize() (row, col int, _ error) { 15 // Try getting the terminal size from stdout, stderr and stdin respectively. 16 // We try each of these in turn because the mechanism we're using fails if any 17 // of the fds is redirected on the command line. E.g. "tool | less" redirects 18 // the stdout of tool to the stdin of less, and will mean tool cannot retrieve 19 // the terminal size from stdout. 20 // 21 // TODO(toddw): This probably only works on some linux / unix variants; add 22 // build tags and support different platforms. 23 if row, col, err := terminalSize(syscall.Stdout); err == nil { 24 return row, col, err 25 } 26 if row, col, err := terminalSize(syscall.Stderr); err == nil { 27 return row, col, err 28 } 29 return terminalSize(syscall.Stdin) 30 } 31 32 func terminalSize(fd int) (int, int, error) { 33 var ws winsize 34 if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&ws))); err != 0 { 35 return 0, 0, err 36 } 37 return int(ws.row), int(ws.col), nil 38 } 39 40 // winsize must correspond to the struct defined in "sys/ioctl.h". Do not 41 // export this struct; it's a platform-specific implementation detail. 42 type winsize struct { 43 row, col, xpixel, ypixel uint16 44 }