read.go 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. // License: GPLv3 Copyright: 2022, Kovid Goyal, <kovid at kovidgoyal.net>
  2. package loop
  3. import (
  4. "fmt"
  5. "io"
  6. "os"
  7. "golang.org/x/sys/unix"
  8. "kitty/tools/tty"
  9. "kitty/tools/utils"
  10. )
  11. var _ = fmt.Print
  12. func (self *Loop) dispatch_input_data(data []byte) error {
  13. if self.OnReceivedData != nil {
  14. err := self.OnReceivedData(data)
  15. if err != nil {
  16. return err
  17. }
  18. }
  19. err := self.escape_code_parser.Parse(data)
  20. if err != nil {
  21. return err
  22. }
  23. return nil
  24. }
  25. func read_ignoring_temporary_errors(f *tty.Term, buf []byte) (int, error) {
  26. n, err := f.Read(buf)
  27. if is_temporary_error(err) {
  28. return 0, nil
  29. }
  30. if n == 0 {
  31. return 0, io.EOF
  32. }
  33. return n, err
  34. }
  35. func read_from_tty(pipe_r *os.File, term *tty.Term, results_channel chan<- []byte, err_channel chan<- error, quit_channel <-chan byte) {
  36. keep_going := true
  37. pipe_fd := int(pipe_r.Fd())
  38. tty_fd := term.Fd()
  39. selector := utils.CreateSelect(2)
  40. selector.RegisterRead(pipe_fd)
  41. selector.RegisterRead(tty_fd)
  42. defer func() {
  43. close(results_channel)
  44. pipe_r.Close()
  45. }()
  46. const bufsize = 2 * utils.DEFAULT_IO_BUFFER_SIZE
  47. wait_for_read_available := func() {
  48. for {
  49. n, err := selector.WaitForever()
  50. if err != nil && err != unix.EINTR {
  51. err_channel <- err
  52. keep_going = false
  53. return
  54. }
  55. if n > 0 {
  56. break
  57. }
  58. }
  59. if selector.IsReadyToRead(pipe_fd) {
  60. keep_going = false
  61. }
  62. }
  63. buf := make([]byte, bufsize)
  64. for keep_going {
  65. if len(buf) < 64 {
  66. buf = make([]byte, bufsize)
  67. }
  68. if wait_for_read_available(); !keep_going {
  69. break
  70. }
  71. n, err := read_ignoring_temporary_errors(term, buf)
  72. if err != nil {
  73. err_channel <- err
  74. keep_going = false
  75. break
  76. }
  77. if n == 0 { // temporary error
  78. continue
  79. }
  80. send := buf[:n]
  81. buf = buf[n:]
  82. select {
  83. case results_channel <- send:
  84. case <-quit_channel:
  85. keep_going = false
  86. }
  87. }
  88. }