Как установить размер терминала? - PullRequest
4 голосов
/ 14 ноября 2009

Как узнать размер терминала в Go. В Си это будет выглядеть так:

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

Но как мне получить доступ к TIOCGWINSZ в Go

Ответы [ 4 ]

3 голосов
/ 14 ноября 2009

В настоящее время компилятор 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)
}

Тем не менее, cgo все равно прекратит ... в прототипе ioctl. Лучше всего было бы заключить ioctl в функцию c, принимающую определенное количество аргументов, и связать ее с ней. В качестве хака вы можете сделать это в приведенном выше комментарии 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)
}

Я не проверял это, но что-то подобное должно работать.

1 голос
/ 03 апреля 2013

читать: 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
}
1 голос
/ 09 февраля 2011

Лучший способ сделать это - использовать пакет syscall. Пакет syscall не определяет функцию ioctl, потому что он просто делает так много разных вещей, но вы все равно можете вызвать ее так:

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

Осталось две вещи: дублировать структуру winsize и необходимую вам константу. Инструментом для этого является godefs, который сгенерирует исходный файл .go, просматривая структуры и константы в заголовках языка C. Создайте файл termios.c, который выглядит следующим образом:

#include <termios.h>

enum {
    $TIOCGWINSZ = TIOCGWINSZ
};

typedef winsize $winsize;

Теперь запустите

godefs -gpackagename termios.c > termios.go

Теперь у вас должно быть все необходимое для получения размера терминала. Установить размер так же просто, как добавить еще одну константу в termios.c.

0 голосов
/ 14 ноября 2009

Похоже, что с этой точки зрения не было проделано большой работы над этим документом - фактически, я не могу найти ioctl вообще.

С языком, который находится на раннем этапе своего зарождения, можно с уверенностью сказать, что вы шагаете по непрогулявшейся земле. TIOCGWINSZ само по себе является просто постоянным целым числом (я нашел его значение в исходном коде Linux):

#define TIOCGWINSZ  0x5413

Удачи, хотя.

...