KEMBAR78
Golangにおける端末制御 リッチなターミナルUIの実現方法 | PDF
CA.go #2
Golang
UI
AbemaTV
Masashi SHIBATA
c-bata c_bata_! "
https://github.com/c-bata/go-prompt
python-prompt-toolkit Go
Topic 1
termios
canonical mode / non-canonical mode
raw mode / cbreak mode
termios structure
KEYWORDS
Ctrl-C Enter
https://github.com/c-bata/go-prompt/blob/master/_tools/vt100_debug.go
Non-Cannonical Mode
( )
https://golang.org/pkg/syscall/#Termios
type Termios struct {
Iflag uint32
Oflag uint32
Cflag uint32
Lflag uint32
Line uint8
Cc [32]uint8
Pad_cgo_0 [3]byte
Ispeed uint32
Ospeed uint32
}
termios tcgetattr / tcsetattr
https://golang.org/pkg/syscall/#Termios
type Termios struct {
Iflag uint32
Oflag uint32
Cflag uint32
Lflag uint32
Line uint8
Cc [32]uint8
Pad_cgo_0 [3]byte
Ispeed uint32
Ospeed uint32
}
termios tcgetattr / tcsetattr
ICANON(2bit )
https://golang.org/pkg/syscall/#Termios
type Termios struct {
Iflag uint32
Oflag uint32
Cflag uint32
Lflag uint32
Line uint8
Cc [32]uint8
Pad_cgo_0 [3]byte
Ispeed uint32
Ospeed uint32
}
termios tcgetattr / tcsetattr
VMIN / VTIME
raw
raw mode




VMIN=1 / VTIME=0
github.com/pkg/term
// Cfmakeraw modifies attr for raw mode.
func Cfmakeraw(attr *syscall.Termios) {
attr.Iflag &^= syscall.BRKINT | syscall.ICRNL |
syscall.INPCK | syscall.ISTRIP | syscall.IXON
attr.Oflag &^= syscall.OPOST
attr.Cflag &^= syscall.CSIZE | syscall.PARENB
attr.Cflag |= syscall.CS8
attr.Lflag &^= syscall.ECHO | syscall.ICANON |
syscall.IEXTEN | syscall.ISIG
attr.Cc[syscall.VMIN] = 1
attr.Cc[syscall.VTIME] = 0
}
https://github.com/pkg/term/blob/master/termios/termios.go
https://github.com/c-bata/go-prompt/blob/master/vt100_input.go
Byte
var asciiSequences []*ASCIICode = []*ASCIICode{
{Key: Escape, ASCIICode: []byte{0x1b}},
{Key: ControlSpace, ASCIICode: []byte{0x00}},
{Key: ControlA, ASCIICode: []byte{0x1}},
{Key: ControlB, ASCIICode: []byte{0x2}},
{Key: ControlC, ASCIICode: []byte{0x3}},
{Key: ControlD, ASCIICode: []byte{0x4}},
{Key: ControlE, ASCIICode: []byte{0x5}},
{Key: ControlF, ASCIICode: []byte{0x6}},
{Key: ControlG, ASCIICode: []byte{0x7}},
{Key: ControlH, ASCIICode: []byte{0x8}},
:
}
https://github.com/c-bata/go-prompt/blob/master/_tools/vt100_debug.go
🎉
KeyBinding
) ab←c acb
Topic 2
VT100 digital terminal device
Escape sequences
KEYWORDS
UI
https://ja.wikipedia.org/wiki/VT100https://ja.wikipedia.org/wiki/ASR-33
https://ja.wikipedia.org/wiki/VT100https://ja.wikipedia.org/wiki/ASR-33
1960-1970
https://ja.wikipedia.org/wiki/VT100https://ja.wikipedia.org/wiki/ASR-33
( )
→
VT100 Escape Sequences
VT100
ANSI
VT100
syscall.Write(syscall.Stdin, []byte("x1b[4;30;46m"))
syscall.Write(syscall.Stdin, []byte("Hello Worldn"))
syscall.Write(syscall.Stdin, []byte("x1b[0m"))
http://vt100.net/docs/vt100-ug/chapter3.html
VT100
syscall.Write(syscall.Stdin, []byte("x1b[4;30;46m"))
syscall.Write(syscall.Stdin, []byte("Hello Worldn"))
syscall.Write(syscall.Stdin, []byte("x1b[0m"))
http://vt100.net/docs/vt100-ug/chapter3.html
x1b[ 4;30;46 m
Control Sequence Introducer (CSI)
VT100
syscall.Write(syscall.Stdin, []byte("x1b[4;30;46m"))
syscall.Write(syscall.Stdin, []byte("Hello Worldn"))
syscall.Write(syscall.Stdin, []byte("x1b[0m"))
http://vt100.net/docs/vt100-ug/chapter3.html
x1b[ 4;30;46 m
: :
VT100
syscall.Write(syscall.Stdin, []byte("x1b[4;30;46m"))
syscall.Write(syscall.Stdin, []byte("Hello Worldn"))
syscall.Write(syscall.Stdin, []byte("x1b[0m"))
http://vt100.net/docs/vt100-ug/chapter3.html
x1b[ 4;30;46 m
Final Character
Topic 3
ioctl system call and TIOCGWINSZ
SIGWINCH
KEYWORDS
kube-prompt
Window
https://github.com/c-bata/go-prompt/blob/master/_tools/window_size.go
func GetWinSize(fd int) (row, col uint16, err error) {
var ws *winsize
retCode, _, errno := syscall.Syscall(syscall.SYS_IOCTL,
uintptr(syscall.Stdin), uintptr(syscall.TIOCGWINSZ),
uintptr(unsafe.Pointer(ws)))
if int(retCode) == -1 {
return 0, 0, fmt.Errorf(“failed with %d”, retCode)
}
return ws.Row, ws.Col, nil
}
ioctl TIOCGWINSZ
SIGWINCH
Window
https://github.com/c-bata/go-prompt/blob/master/_tools/window_size.go
Golangにおける端末制御 リッチなターミナルUIの実現方法

Golangにおける端末制御 リッチなターミナルUIの実現方法