Golangで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とは関係のないプロセスを生成し、それを使用しているためだと思います。サイズを取得するために、コマンドを現在の端末に関連付けるにはどうすればよいですか?
子プロセスに親の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>
私は同様の問題で立ち往生していました。これが私が最終的に得たものです。
サブプロセスを使用しないため、状況によっては望ましい場合があります。
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)
}
最近この問題に遭遇したので、新しい答えを追加したかっただけです。公式のsshパッケージ内にあるターミナルパッケージがあります https://godoc.org/golang.org/x/crypto/ssh/terminal 。
このパッケージは、端末のサイズを簡単に取得する方法を提供します。
width, height, err := terminal.GetSize(0)
0は、サイズを指定する端末のファイル記述子になります。 fdまたは現在の端末を取得するには、いつでもint(os.Stdin.Fd())
を実行できます。
裏では、syscallを使用して、指定されたfdの端末サイズを取得します。
興味のある方は、これを簡単にするパッケージを作成しました。
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)
}