2015-09-27 06:41:05 +03:00
|
|
|
// +build darwin dragonfly freebsd linux,!appengine netbsd openbsd
|
|
|
|
|
|
|
|
package readline
|
|
|
|
|
|
|
|
import (
|
2016-03-13 13:32:48 +03:00
|
|
|
"os"
|
|
|
|
"os/signal"
|
|
|
|
"sync"
|
2015-09-27 06:41:05 +03:00
|
|
|
"syscall"
|
|
|
|
"unsafe"
|
|
|
|
)
|
|
|
|
|
|
|
|
type winsize struct {
|
|
|
|
Row uint16
|
|
|
|
Col uint16
|
|
|
|
Xpixel uint16
|
|
|
|
Ypixel uint16
|
|
|
|
}
|
|
|
|
|
2016-04-17 16:05:00 +03:00
|
|
|
// SuspendMe use to send suspend signal to myself, when we in the raw mode.
|
|
|
|
// For OSX it need to send to parent's pid
|
|
|
|
// For Linux it need to send to myself
|
|
|
|
func SuspendMe() {
|
|
|
|
p, _ := os.FindProcess(os.Getppid())
|
|
|
|
p.Signal(syscall.SIGTSTP)
|
|
|
|
p, _ = os.FindProcess(os.Getpid())
|
|
|
|
p.Signal(syscall.SIGTSTP)
|
|
|
|
}
|
|
|
|
|
2015-09-27 06:41:05 +03:00
|
|
|
// get width of the terminal
|
2016-02-18 06:25:41 +03:00
|
|
|
func getWidth(stdoutFd int) int {
|
2015-09-27 06:41:05 +03:00
|
|
|
ws := &winsize{}
|
|
|
|
retCode, _, errno := syscall.Syscall(syscall.SYS_IOCTL,
|
2016-02-18 06:25:41 +03:00
|
|
|
uintptr(stdoutFd),
|
2015-09-27 06:41:05 +03:00
|
|
|
uintptr(syscall.TIOCGWINSZ),
|
|
|
|
uintptr(unsafe.Pointer(ws)))
|
|
|
|
|
|
|
|
if int(retCode) == -1 {
|
2016-02-18 06:25:41 +03:00
|
|
|
_ = errno
|
|
|
|
return -1
|
2015-09-27 06:41:05 +03:00
|
|
|
}
|
|
|
|
return int(ws.Col)
|
|
|
|
}
|
2016-03-13 13:32:48 +03:00
|
|
|
|
|
|
|
func GetScreenWidth() int {
|
|
|
|
return getWidth(syscall.Stdout)
|
|
|
|
}
|
|
|
|
|
|
|
|
func DefaultIsTerminal() bool {
|
|
|
|
return IsTerminal(syscall.Stdin) && IsTerminal(syscall.Stdout)
|
|
|
|
}
|
|
|
|
|
|
|
|
func GetStdin() int {
|
|
|
|
return syscall.Stdin
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
var (
|
|
|
|
widthChange sync.Once
|
|
|
|
widthChangeCallback func()
|
|
|
|
)
|
|
|
|
|
|
|
|
func DefaultOnWidthChanged(f func()) {
|
|
|
|
widthChangeCallback = f
|
|
|
|
widthChange.Do(func() {
|
|
|
|
ch := make(chan os.Signal, 1)
|
|
|
|
signal.Notify(ch, syscall.SIGWINCH)
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
for {
|
|
|
|
_, ok := <-ch
|
|
|
|
if !ok {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
widthChangeCallback()
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
})
|
|
|
|
}
|