github.com/kopoli/go-terminal-size@v0.0.0-20170219200355-5c97524c8b54/size_unix.go (about)

     1  // +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
     2  
     3  package tsize
     4  
     5  import (
     6  	"os"
     7  	"os/signal"
     8  	"unsafe"
     9  
    10  	"golang.org/x/sys/unix"
    11  )
    12  
    13  type winsize struct {
    14  	rows uint16
    15  	cols uint16
    16  	x    uint16
    17  	y    uint16
    18  }
    19  
    20  var unixSyscall = unix.Syscall
    21  
    22  func getTerminalSize(fp *os.File) (s Size, err error) {
    23  	ws := winsize{}
    24  
    25  	_, _, errno := unixSyscall(
    26  		unix.SYS_IOCTL,
    27  		fp.Fd(),
    28  		uintptr(unix.TIOCGWINSZ),
    29  		uintptr(unsafe.Pointer(&ws)))
    30  
    31  	if errno != 0 {
    32  		err = errno
    33  		return
    34  	}
    35  
    36  	s = Size{
    37  		Width:  int(ws.cols),
    38  		Height: int(ws.rows),
    39  	}
    40  
    41  	return
    42  }
    43  
    44  func getTerminalSizeChanges(sc chan Size, done chan struct{}) error {
    45  	ch := make(chan os.Signal, 1)
    46  
    47  	sig := unix.SIGWINCH
    48  
    49  	signal.Notify(ch, sig)
    50  	go func() {
    51  		for {
    52  			select {
    53  			case <-ch:
    54  				var err error
    55  				s, err := getTerminalSize(os.Stdout)
    56  				if err == nil {
    57  					sc <- s
    58  				}
    59  			case <-done:
    60  				signal.Reset(sig)
    61  				close(ch)
    62  				return
    63  			}
    64  		}
    65  	}()
    66  
    67  	return nil
    68  }