Get terminal size in Go

Ilia Sidorenko picture Ilia Sidorenko · May 15, 2013 · Viewed 11.9k times · Source

How to get tty size with Golang? I am trying do this with executing stty size command, but I can't craft code right.

package main

import (
  "os/exec"
  "fmt"
  "log"
)

func main() {
  out, err := exec.Command("stty", "size").Output()
  fmt.Printf("out: %#v\n", out)
  fmt.Printf("err: %#v\n", err)
  if err != nil {
    log.Fatal(err)
  }
}

Output:

out: []byte{}
err: &exec.ExitError{ProcessState:(*os.ProcessState)(0xc200066520)}
2013/05/16 02:35:57 exit status 1
exit status 1

I think this is because Go spawns a process not related to the current tty, with which it is working. How can I relate the command to current terminal in order to get its size?

Answer

deft_code picture deft_code · May 16, 2013

I was stuck on a similar problem. Here is what I ended up with.

It doesn't use a subprocess, so might be desirable in some situations.

import (
    "syscall"
    "unsafe"
)

type winsize struct {
    Row    uint16
    Col    uint16
    Xpixel uint16
    Ypixel uint16
}

func getWidth() uint {
    ws := &winsize{}
    retCode, _, errno := syscall.Syscall(syscall.SYS_IOCTL,
        uintptr(syscall.Stdin),
        uintptr(syscall.TIOCGWINSZ),
        uintptr(unsafe.Pointer(ws)))

    if int(retCode) == -1 {
        panic(errno)
    }
    return uint(ws.Col)
}