Получите размер терминала в Go
Как получить размер tty с Голангом? Я пытаюсь сделать это с помощью команды stty size
, но я не могу правильно написать код.
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)
}
}
Выход:
out: []byte{}
err: &exec.ExitError{ProcessState:(*os.ProcessState)(0xc200066520)}
2013/05/16 02:35:57 exit status 1
exit status 1
Я думаю, это потому, что Go порождает процесс, не связанный с текущим tty, с которым он работает. Как я могу связать команду с текущим терминалом, чтобы получить его размер?
Ответы
Ответ 1
Он работает, если вы предоставите дочернему процессу доступ к родительскому 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)
}
}
Урожайность:
out: "36 118\n"
err: <nil>
Ответ 2
Я столкнулся с подобной проблемой. Вот что я закончил.
Он не использует подпроцесс, поэтому может быть желательно в некоторых ситуациях.
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)
}
Ответ 3
Я просто хотел добавить новый ответ, так как недавно столкнулся с этой проблемой. Существует пакет терминала, который находится внутри официального пакета ssh https://godoc.org/golang.org/x/crypto/ssh/terminal.
Этот пакет предоставляет метод, позволяющий легко получить размер терминала.
width, height, err := terminal.GetSize(0)
0 будет файловым дескриптором терминала, размер которого вы хотите. Чтобы получить fd или ваш текущий терминал, вы всегда можете сделать int(os.Stdin.Fd())
Под прикрытием он использует системный вызов для получения размера терминала для данного файла.
Ответ 4
Если кому-то интересно, я сделал пакет, чтобы сделать это проще.
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)
}