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  }