Cómo establecer el tamaño del terminal?
Pregunta
¿Cómo consigo el tamaño terminal en Ir. En C se vería así:
struct ttysize ts;
ioctl(0, TIOCGWINSZ, &ts);
Pero, ¿cómo puedo acceder a TIOCGWINSZ en Ir
Solución
El compilador CGO no puede manejar argumentos variables en función C y macros en archivos de cabecera de C en la actualidad, por lo que no se puede hacer un simple
// #include <sys/ioctl.h>
// typedef struct ttysize ttysize;
import "C"
func GetWinSz() {
var ts C.ttysize;
C.ioctl(0,C.TIOCGWINSZ,&ts)
}
Para conseguir alrededor de las macros utilizar una constante, por lo que
// #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)
}
Sin embargo CGO seguirá siendo vomitar en el ... en el prototipo de ioctl. Su mejor apuesta sería la de envolver ioctl con una función c teniendo un número específico de argumentos y vincular esa. Como un truco que puede hacer que en el comentario anterior de importación "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)
}
No he probado esto, pero algo similar debería funcionar.
Otros consejos
La mejor manera de hacer esto sería usar el paquete de llamada al sistema. El paquete de llamada al sistema no define una función ioctl, ya que sólo hace tantas cosas diferentes, pero todavía se puede llamar así:
syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), uintptr(TIOCGWINSZ), uintptr(unsafe.Pointer(&ts)))
Las dos cosas son dejadas para duplicar la estructura winsize y la constante que necesitan. La herramienta para esto es godefs, lo que generará un archivo de origen .go examinado estructuras y constantes en las cabeceras C. Crear un archivo termios.c que tiene este aspecto:
#include <termios.h>
enum {
$TIOCGWINSZ = TIOCGWINSZ
};
typedef winsize $winsize;
Ahora ejecute
godefs -gpackagename termios.c > termios.go
Ahora usted debería tener todo lo necesario para obtener el tamaño de terminal. Ajuste del tamaño es tan simple como la adición de otra constante a termios.c.
leer: 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
}
No parece mucho trabajo se ha hecho sobre esto todavía desde una mirada casual de la documentación -. De hecho, no puedo encontrar ioctl
en absoluto
Con un lenguaje tan temprano en su infancia, es seguro decir que usted está pisando suelo unwalked. TIOCGWINSZ
, en sí, es sólo un número entero constante (me encontré su valor en el código fuente Linux):
#define TIOCGWINSZ 0x5413
Buena suerte, sin embargo.