如何设置终端的大小?

时间:2009-11-14 03:38:32

标签: terminal posix go ioctl

如何在Go中获取终端大小。在C中它看起来像这样:

struct ttysize ts; 
ioctl(0, TIOCGWINSZ, &ts);

但是如何在Go

中访问TIOCGWINSZ

4 个答案:

答案 0 :(得分:3)

目前cgo编译器无法处理c函数中的变量参数和c头文件中的宏,所以你不能做一个简单的

// #include <sys/ioctl.h>
// typedef struct ttysize ttysize;
import "C"

func GetWinSz() {
    var ts C.ttysize;
    C.ioctl(0,C.TIOCGWINSZ,&ts)
}

绕过宏使用常量,所以

// #include <sys/ioctl.h>
// typedef struct ttysize ttysize;
import "C"

const TIOCGWINSZ C.ulong = 0x5413; // Value from Jed Smith's answer

func GetWinSz() {
    var ts C.ttysize;
    C.ioctl(0,TIOCGWINSZ,&ts)
}

然而,在ioctl的原型中,cgo仍然会在...上bar。你最好的选择是用一个带有特定数量参数的c函数来包装ioctl并将其链接起来。作为一个hack,你可以在导入“C”上面的注释中做到这一点

// #include <sys/ioctl.h>
// typedef struct ttysize ttysize;
// void myioctl(int i, unsigned long l, ttysize * t){ioctl(i,l,t);}
import "C"

const TIOCGWINSZ C.ulong = 0x5413; // Value from Jed Smith's answer

func GetWinSz() {
    var ts C.ttysize;
    C.myioctl(0,TIOCGWINSZ,&ts)
}

我没有对此进行过测试,但类似的东西应该有用。

答案 1 :(得分:1)

执行此操作的最佳方法是使用syscall包。系统调用包没有定义ioctl函数,因为它只是做了很多不同的事情,但你仍然可以像这样调用它:

syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), uintptr(TIOCGWINSZ), uintptr(unsafe.Pointer(&ts)))

剩下的两件事就是复制winsize结构和你需要的常量。用于此的工具是godefs,它将通过查看C头中的结构和常量来生成.go源文件。创建一个如下所示的termios.c文件:

#include <termios.h>

enum {
    $TIOCGWINSZ = TIOCGWINSZ
};

typedef winsize $winsize;

现在运行

godefs -gpackagename termios.c > termios.go

现在你应该拥有获得终端尺寸所需的一切。设置大小就像在termios.c中添加另一个常量一样简单。

答案 2 :(得分:1)

阅读:http://www.darkcoding.net/software/pretty-command-line-console-output-on-unix-in-python-and-go-lang/

const (
    TIOCGWINSZ     = 0x5413
    TIOCGWINSZ_OSX = 1074295912
)

type window struct {
    Row    uint16
    Col    uint16
    Xpixel uint16
    Ypixel uint16
}

func terminalWidth() (int, error) {
    w := new(window)
    tio := syscall.TIOCGWINSZ
    if runtime.GOOS == "darwin" {
        tio = TIOCGWINSZ_OSX
    }
    res, _, err := syscall.Syscall(syscall.SYS_IOCTL,
        uintptr(syscall.Stdin),
        uintptr(tio),
        uintptr(unsafe.Pointer(w)),
    )
    if int(res) == -1 {
        return 0, err
    }
    return int(w.Col), nil
}

答案 3 :(得分:0)

从文档的随意浏览中看起来似乎没有做太多工作 - 实际上,我根本找不到ioctl

这种语言早在婴儿时期,就可以肯定地说你正在踩着不受约束的地面。 TIOCGWINSZ本身只是一个常量整数(我在Linux源代码中找到了它的值):

#define TIOCGWINSZ  0x5413

祝你好运。