input_posix.go 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. // +build !windows
  2. package prompt
  3. import (
  4. "syscall"
  5. "github.com/c-bata/go-prompt/internal/term"
  6. "golang.org/x/sys/unix"
  7. )
  8. const maxReadBytes = 1024
  9. // PosixParser is a ConsoleParser implementation for POSIX environment.
  10. type PosixParser struct {
  11. fd int
  12. origTermios syscall.Termios
  13. }
  14. // Setup should be called before starting input
  15. func (t *PosixParser) Setup() error {
  16. // Set NonBlocking mode because if syscall.Read block this goroutine, it cannot receive data from stopCh.
  17. if err := syscall.SetNonblock(t.fd, true); err != nil {
  18. return err
  19. }
  20. if err := term.SetRaw(t.fd); err != nil {
  21. return err
  22. }
  23. return nil
  24. }
  25. // TearDown should be called after stopping input
  26. func (t *PosixParser) TearDown() error {
  27. if err := syscall.SetNonblock(t.fd, false); err != nil {
  28. return err
  29. }
  30. if err := term.Restore(); err != nil {
  31. return err
  32. }
  33. return nil
  34. }
  35. // Read returns byte array.
  36. func (t *PosixParser) Read() ([]byte, error) {
  37. buf := make([]byte, maxReadBytes)
  38. n, err := syscall.Read(t.fd, buf)
  39. if err != nil {
  40. return []byte{}, err
  41. }
  42. return buf[:n], nil
  43. }
  44. // GetWinSize returns WinSize object to represent width and height of terminal.
  45. func (t *PosixParser) GetWinSize() *WinSize {
  46. ws, err := unix.IoctlGetWinsize(t.fd, unix.TIOCGWINSZ)
  47. if err != nil {
  48. panic(err)
  49. }
  50. return &WinSize{
  51. Row: ws.Row,
  52. Col: ws.Col,
  53. }
  54. }
  55. var _ ConsoleParser = &PosixParser{}
  56. // NewStandardInputParser returns ConsoleParser object to read from stdin.
  57. func NewStandardInputParser() *PosixParser {
  58. in, err := syscall.Open("/dev/tty", syscall.O_RDONLY, 0)
  59. if err != nil {
  60. panic(err)
  61. }
  62. return &PosixParser{
  63. fd: in,
  64. }
  65. }