2022-04-18 15:41:19 +03:00
|
|
|
// +build aix darwin dragonfly freebsd linux,!appengine netbsd openbsd os400 solaris
|
2015-09-27 06:41:05 +03:00
|
|
|
|
|
|
|
package readline
|
|
|
|
|
|
|
|
import (
|
2016-05-16 12:59:35 +03:00
|
|
|
"io"
|
2016-03-13 13:32:48 +03:00
|
|
|
"os"
|
|
|
|
"os/signal"
|
|
|
|
"sync"
|
2015-09-27 06:41:05 +03:00
|
|
|
"syscall"
|
|
|
|
)
|
|
|
|
|
|
|
|
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 {
|
2017-03-13 02:57:45 +03:00
|
|
|
cols, _, err := GetSize(stdoutFd)
|
|
|
|
if err != nil {
|
2016-02-18 06:25:41 +03:00
|
|
|
return -1
|
2015-09-27 06:41:05 +03:00
|
|
|
}
|
2017-03-13 02:57:45 +03:00
|
|
|
return cols
|
2015-09-27 06:41:05 +03:00
|
|
|
}
|
2016-03-13 13:32:48 +03:00
|
|
|
|
|
|
|
func GetScreenWidth() int {
|
2016-06-21 12:47:31 +03:00
|
|
|
w := getWidth(syscall.Stdout)
|
|
|
|
if w < 0 {
|
|
|
|
w = getWidth(syscall.Stderr)
|
|
|
|
}
|
|
|
|
return w
|
2016-03-13 13:32:48 +03:00
|
|
|
}
|
|
|
|
|
2022-06-28 08:49:19 +03:00
|
|
|
// getWidthHeight of the terminal using given file descriptor
|
|
|
|
func getWidthHeight(stdoutFd int) (width int, height int) {
|
|
|
|
width, height, err := GetSize(stdoutFd)
|
|
|
|
if err != nil {
|
|
|
|
return -1, -1
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetScreenSize returns the width/height of the terminal or -1,-1 or error
|
|
|
|
func GetScreenSize() (width int, height int) {
|
|
|
|
width, height = getWidthHeight(syscall.Stdout)
|
|
|
|
if width < 0 {
|
|
|
|
width, height = getWidthHeight(syscall.Stderr)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-05-16 04:56:06 +03:00
|
|
|
// Ask the terminal for the current cursor position. The terminal will then
|
|
|
|
// write the position back to us via termainal stdin asynchronously.
|
|
|
|
func SendCursorPosition(t *Terminal) {
|
|
|
|
t.Write([]byte("\033[6n"))
|
|
|
|
}
|
|
|
|
|
2016-05-16 12:59:35 +03:00
|
|
|
// ClearScreen clears the console screen
|
|
|
|
func ClearScreen(w io.Writer) (int, error) {
|
|
|
|
return w.Write([]byte("\033[H"))
|
|
|
|
}
|
|
|
|
|
2016-03-13 13:32:48 +03:00
|
|
|
func DefaultIsTerminal() bool {
|
2016-06-21 12:47:31 +03:00
|
|
|
return IsTerminal(syscall.Stdin) && (IsTerminal(syscall.Stdout) || IsTerminal(syscall.Stderr))
|
2016-03-13 13:32:48 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
func GetStdin() int {
|
|
|
|
return syscall.Stdin
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
var (
|
2022-06-28 08:49:19 +03:00
|
|
|
sizeChange sync.Once
|
|
|
|
sizeChangeCallback func()
|
2016-03-13 13:32:48 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
func DefaultOnWidthChanged(f func()) {
|
2022-06-28 08:49:19 +03:00
|
|
|
DefaultOnSizeChanged(f)
|
|
|
|
}
|
|
|
|
|
|
|
|
func DefaultOnSizeChanged(f func()) {
|
|
|
|
sizeChangeCallback = f
|
|
|
|
sizeChange.Do(func() {
|
2016-03-13 13:32:48 +03:00
|
|
|
ch := make(chan os.Signal, 1)
|
|
|
|
signal.Notify(ch, syscall.SIGWINCH)
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
for {
|
|
|
|
_, ok := <-ch
|
|
|
|
if !ok {
|
|
|
|
break
|
|
|
|
}
|
2022-06-28 08:49:19 +03:00
|
|
|
sizeChangeCallback()
|
2016-03-13 13:32:48 +03:00
|
|
|
}
|
|
|
|
}()
|
|
|
|
})
|
|
|
|
}
|