Search code examples
terminalposixgoioctl

How do you get the terminal size in Go?


How do I get the terminal size in Go. In C it would look like this:

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

But how to i access TIOCGWINSZ in Go


Solution

  • The cgo compiler can't handle variable arguments in a c function and macros in c header files at present, so you can't do a simple

    // #include <sys/ioctl.h>
    // typedef struct ttysize ttysize;
    import "C"
    
    func GetWinSz() {
        var ts C.ttysize;
        C.ioctl(0,C.TIOCGWINSZ,&ts)
    }
    

    To get around the macros use a constant, so

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

    However cgo will still barf on the ... in ioctl's prototype. Your best bet would be to wrap ioctl with a c function taking a specific number of arguments and link that in. As a hack you can do that in the comment above import "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)
    }
    

    I've not tested this, but something similar should work.