如何使用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无关的进程,它正在使用它。如何将命令与当前终端关联以获得其大小?
答案 0 :(得分:20)
我遇到了类似的问题。这就是我最终的目标。
它不使用子进程,因此在某些情况下可能是理想的。
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)
}
答案 1 :(得分:16)
如果您允许子进程访问父级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 :(得分:12)
我刚才想添加一个新答案,因为我最近遇到了这个问题。终端软件包位于官方ssh包https://godoc.org/golang.org/x/crypto/ssh/terminal内。
此软件包提供了一种轻松获取终端大小的方法。
width, height, err := terminal.GetSize(0)
0将是您想要大小的终端的文件描述符。要获得fd或您当前的终端,您始终可以int(os.Stdin.Fd())
在封面下,它使用系统调用来获取给定fd的终端大小。
答案 3 :(得分:5)
如果有兴趣的话,我提出了一个方案来使这更容易。
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 :(得分:2)
您可以使用 golang.org/x/term
包 (https://pkg.go.dev/golang.org/x/term)
示例
package main
import "golang.org/x/term"
func main() {
if term.IsTerminal(0) {
println("in a term")
} else {
println("not in a term")
}
width, height, err := term.GetSize(0)
if err != nil {
return
}
println("width:", width, "height:", height)
}
输出
in a term
width: 228 height: 27
答案 5 :(得分:1)
由于这里还没有人提出可以在 Windows 和 Unix 上运行的跨平台解决方案,因此我继续整理了一个库,该库支持两者。
https://github.com/nathan-fiscaletti/consolesize-go
package main
import (
"fmt"
"github.com/nathan-fiscaletti/consolesize-go"
)
func main() {
cols, rows := consolesize.GetConsoleSize()
fmt.Printf("Rows: %v, Cols: %v\n", rows, cols)
}
答案 6 :(得分:0)
我有一个使用tcell
模块的实现,实际上,它仍将使用基于调用本地dlls
的方法,但是如果您要搜索终端尺寸,则很有可能您仍然需要该软件包:
package main
import (
"fmt"
"github.com/gdamore/tcell"
)
func main() {
screen, _ := tcell.NewScreen()
screen.Init()
w, h := screen.Size()
fmt.Println(w, h)
}