You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

83 lines
1.5 KiB

  1. // +build darwin dragonfly freebsd linux,!appengine netbsd openbsd solaris
  2. package readline
  3. import (
  4. "io"
  5. "os"
  6. "os/signal"
  7. "sync"
  8. "syscall"
  9. )
  10. type winsize struct {
  11. Row uint16
  12. Col uint16
  13. Xpixel uint16
  14. Ypixel uint16
  15. }
  16. // SuspendMe use to send suspend signal to myself, when we in the raw mode.
  17. // For OSX it need to send to parent's pid
  18. // For Linux it need to send to myself
  19. func SuspendMe() {
  20. p, _ := os.FindProcess(os.Getppid())
  21. p.Signal(syscall.SIGTSTP)
  22. p, _ = os.FindProcess(os.Getpid())
  23. p.Signal(syscall.SIGTSTP)
  24. }
  25. // get width of the terminal
  26. func getWidth(stdoutFd int) int {
  27. cols, _, err := GetSize(stdoutFd)
  28. if err != nil {
  29. return -1
  30. }
  31. return cols
  32. }
  33. func GetScreenWidth() int {
  34. w := getWidth(syscall.Stdout)
  35. if w < 0 {
  36. w = getWidth(syscall.Stderr)
  37. }
  38. return w
  39. }
  40. // ClearScreen clears the console screen
  41. func ClearScreen(w io.Writer) (int, error) {
  42. return w.Write([]byte("\033[H"))
  43. }
  44. func DefaultIsTerminal() bool {
  45. return IsTerminal(syscall.Stdin) && (IsTerminal(syscall.Stdout) || IsTerminal(syscall.Stderr))
  46. }
  47. func GetStdin() int {
  48. return syscall.Stdin
  49. }
  50. // -----------------------------------------------------------------------------
  51. var (
  52. widthChange sync.Once
  53. widthChangeCallback func()
  54. )
  55. func DefaultOnWidthChanged(f func()) {
  56. widthChangeCallback = f
  57. widthChange.Do(func() {
  58. ch := make(chan os.Signal, 1)
  59. signal.Notify(ch, syscall.SIGWINCH)
  60. go func() {
  61. for {
  62. _, ok := <-ch
  63. if !ok {
  64. break
  65. }
  66. widthChangeCallback()
  67. }
  68. }()
  69. })
  70. }