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