diff --git a/window/manager.go b/window/manager.go index 7902904..8fd1a00 100644 --- a/window/manager.go +++ b/window/manager.go @@ -159,11 +159,27 @@ func expandBacktick(filename string) (string, error) { } func (m *Manager) read(r io.Reader) error { + bs, err := func() ([]byte, error) { + r, stop := newReader(r) + defer stop() + return io.ReadAll(r) + }() + window, err := newWindow(bytes.NewReader(bs), "", "", m.eventCh, m.redrawCh) + if err != nil { + return err + } + return m.init(window) +} + +type reader struct { + io.Reader + abort chan os.Signal +} + +func newReader(r io.Reader) (*reader, func()) { done := make(chan struct{}) - defer close(done) abort := make(chan os.Signal, 1) signal.Notify(abort, os.Interrupt) - defer signal.Stop(abort) go func() { select { case <-time.After(time.Second): @@ -171,36 +187,20 @@ func (m *Manager) read(r io.Reader) error { case <-done: } }() - bs, err := func() ([]byte, error) { - // ref: io.ReadAll - bs := make([]byte, 0, 1024) - for { - n, err := r.Read(bs[len(bs):cap(bs)]) - bs = bs[:len(bs)+n] - if err != nil { - if err == io.EOF { - err = nil - } - return bs, err - } - select { - case <-time.After(10 * time.Millisecond): - case <-abort: - return bs, nil - } - if len(bs) == cap(bs) { - bs = append(bs, 0)[:len(bs)] - } - } - }() - if err != nil { - return err + return &reader{r, abort}, func() { + signal.Stop(abort) + close(abort) + close(done) } - window, err := newWindow(bytes.NewReader(bs), "", "", m.eventCh, m.redrawCh) - if err != nil { - return err +} + +func (r *reader) Read(p []byte) (int, error) { + select { + case <-r.abort: + return 0, io.EOF + default: } - return m.init(window) + return r.Reader.Read(p) } // SetSize sets the size of the screen.