2013-05-15 48 views
12

Làm thế nào để có được kích thước tty với Go lang? Tôi đang cố gắng làm điều này với thực hiện lệnh stty size, nhưng tôi không thể viết mã đúng.Lấy kích thước thiết bị đầu cuối trong 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) 
    } 
} 

Output:

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

Tôi nghĩ rằng điều này là do Go spawns một quá trình không liên quan đến tty hiện tại, mà nó đang làm việc. Làm thế nào tôi có thể liên quan đến lệnh để thiết bị đầu cuối hiện tại để có được kích thước của nó?

Trả lời

16

Nó hoạt động nếu bạn cung cấp cho quá trình truy cập trẻ của stdin mẹ:

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

Sản lượng:

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

Bạn có thể thử đặt những dòng này vào một hàm và đặt một kiểm tra đơn vị bằng mô-đun 'testing' để kiểm tra hàm, bạn sẽ thấy rằng bạn luôn nhận được mảng trống. – Kingname

14

tôi đã bị mắc kẹt trên một vấn đề tương tự. Đây là những gì tôi đã kết thúc với.

Nó không sử dụng quy trình con, vì vậy có thể là mong muốn trong một số trường hợp.

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

Làm việc tuyệt vời ở đây, cảm ơn bạn. – Alexander

5

Nếu ai đó quan tâm đến tôi, tôi đã thực hiện một gói để làm việc này dễ dàng hơn.

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

Tôi chỉ muốn thêm một câu trả lời mới kể từ khi tôi chạy vào vấn đề này thời gian gần đây. Có một gói thiết bị đầu cuối nằm trong gói ssh chính thức https://godoc.org/golang.org/x/crypto/ssh/terminal.

Gói này cung cấp phương thức dễ dàng nhận được kích thước của thiết bị đầu cuối.

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

0 sẽ là mô tả tập tin của nhà ga mà bạn muốn kích thước của. Để có thiết bị đầu cuối fd hoặc bạn hiện tại, bạn luôn có thể làm int(os.Stdin.Fd())

Dưới nắp, nó sử dụng syscall để có kích thước đầu cuối cho fd đã cho.

Các vấn đề liên quan