package terminal import ( "fmt" "golang.org/x/term" "os" ) type Screen struct { Rows int Cols int } // Get the size of the terminal in rows and columns func Size() *Screen { cols := 80 rows := 24 // Try the syscall first cols, rows, err := term.GetSize(int(os.Stdin.Fd())) if err == nil { return &Screen{rows, cols} } // Figure out the size the hard way if term.IsTerminal(int(os.Stdin.Fd())) { rows, cols = sizeTrick() } return &Screen{rows, cols} } func sizeTrick() (rows int, cols int) { // Move cursor to location further than likely screen size // The cursor will move to maximum available position fmt.Print(Code("999C") + Code("999B")) // Ask the terminal where the cursor is fmt.Print(LocateCursor) // Read stdin looking for the reported location buffer := "" for char, _ := ReadKey(); char != 'R'; char, _ = ReadKey() { if char == '\x1b' || char == '[' { continue } if char == 'R' || char == '\x00' { break } buffer += string(char) } _, err := fmt.Sscanf(buffer, "%d;%d", &rows, &cols) if err != nil { panic(err) } return rows, cols }