2013-05-15 59 views
12

Jak uzyskać rozmiar tty za pomocą polecenia Idź językiem? Próbuję to zrobić, wykonując polecenie stty size, ale nie mogę wykonać poprawnego kodu.Uzyskaj rozmiar terminala w Go

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) 
    } 
} 

wyjściowa:

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

Myślę, że to dlatego, że Go nie ikra proces związany z aktualnej konsoli, z którymi pracuje. Jak mogę powiązać polecenie z bieżącym terminalem, aby uzyskać jego rozmiar?

Odpowiedz

16

To działa, jeśli dać dostęp procesu dziecko do rodzica stdin:

package main 

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

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

Plony:

out: "36 118\n" 
err: <nil> 
+0

Możesz spróbować umieścić te linie w funkcji i ustawić test jednostkowy za pomocą modułu 'testing' w celu przetestowania funkcji, zobaczysz, że zawsze dostajesz pustą tablicę. – Kingname

14

utknąłem na podobnym problemem. Oto, w czym skończyłem.

Nie korzysta z podprocesu, więc może być pożądane w niektórych sytuacjach.

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) 
} 
+0

Pracowałem świetnie tutaj, dziękuję. – Alexander

5

Jeśli ktoś jest zainteresowany, zrobiłem paczkę, aby było to łatwiejsze.

https://github.com/wayneashleyberry/terminal-dimensions

package main 

import (
    "fmt" 

    terminal "github.com/wayneashleyberry/terminal-dimensions" 
) 

func main() { 
    x, _ := terminal.Width() 
    y, _ := terminal.Height() 
    fmt.Printf("Terminal is %d wide and %d high", x, y) 
} 
4

Chciałem tylko dodać nową odpowiedź ponieważ wpadłem na ten problem niedawno. Istnieje pakiet terminalowy, który znajduje się w oficjalnym pakiecie ssh https://godoc.org/golang.org/x/crypto/ssh/terminal.

Ten pakiet zapewnia metodę łatwego uzyskania rozmiaru terminala.

width, height, err := terminal.GetSize(0)

0 byłoby deskryptor terminalu chcesz rozmiar. Aby uzyskać FDA lub bieżący terminal, zawsze możesz wykonać: int(os.Stdin.Fd())

Pod pokrywami używa on systemu operacyjnego do pobrania rozmiaru terminala dla danego fd.