From ab72a5521f039958c32198913b92fa54c3dc4f1c Mon Sep 17 00:00:00 2001 From: Daisuke Maki Date: Fri, 3 Mar 2017 23:23:07 +0900 Subject: [PATCH] Tweak timing for when to initialize the screen and other components We should wait to initialize the screen until we have something coming in from the source: otherwise multiple peograms chained via pipes would compete for the same terminal resource, and things may go southward. But then there are components that rely on the screen being intialized, so we let them wait as well. --- peco.go | 39 ++++++++++++++++++++------------------- screen.go | 5 ++++- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/peco.go b/peco.go index 6486dd1..d8a7cd0 100644 --- a/peco.go +++ b/peco.go @@ -301,11 +301,6 @@ func (p *Peco) Run(ctx context.Context) (err error) { if err := p.Setup(); err != nil { return errors.Wrap(err, "failed to setup peco") } - // screen.Init must be called within Run() because we - // want to make sure to call screen.Close() after getting - // out of Run() - p.screen.Init() - defer p.screen.Close() var _cancelOnce sync.Once var _cancel func() @@ -325,20 +320,11 @@ func (p *Peco) Run(ctx context.Context) (err error) { // remember this cancel func so p.Exit works (XXX requires locking?) p.cancelFunc = cancel - loopers := []interface { - Loop(ctx context.Context, cancel func()) error - }{ - NewInput(p, p.Keymap(), p.screen.PollEvent(ctx)), - NewView(p), - NewFilter(p), - sig.New(sig.SigReceivedHandlerFunc(func(sig os.Signal) { - p.Exit(errors.New("received signal: " + sig.String())) - })), - } + sigH := sig.New(sig.SigReceivedHandlerFunc(func(sig os.Signal) { + p.Exit(errors.New("received signal: " + sig.String())) + })) - for _, l := range loopers { - go l.Loop(ctx, cancel) - } + go sigH.Loop(ctx, cancel) // SetupSource is done AFTER other components are ready, otherwise // we can't draw onto the screen while we are reading a really big @@ -350,6 +336,18 @@ func (p *Peco) Run(ctx context.Context) (err error) { } p.source = src + go func() { + <-p.source.Ready() + // screen.Init must be called within Run() because we + // want to make sure to call screen.Close() after getting + // out of Run() + p.screen.Init() + go NewInput(p, p.Keymap(), p.screen.PollEvent(ctx)).Loop(ctx, cancel) + go NewView(p).Loop(ctx, cancel) + go NewFilter(p).Loop(ctx, cancel) + }() + defer p.screen.Close() + if p.Query().Len() <= 0 { // Re-set the source only if there are no queries p.ResetCurrentLineBuffer() @@ -391,7 +389,10 @@ func (p *Peco) Run(ctx context.Context) (err error) { } if p.Query().Len() > 0 { - p.ExecQuery() + go func() { + <-p.source.Ready() + p.ExecQuery() + }() } // Alright, done everything we need to do automatically. We'll let diff --git a/screen.go b/screen.go index 8d237ad..edbce87 100644 --- a/screen.go +++ b/screen.go @@ -26,6 +26,10 @@ func NewTermbox() *Termbox { } func (t *Termbox) Close() error { + if pdebug.Enabled { + pdebug.Printf("Termbox: Close") + } + termbox.Interrupt() termbox.Close() return nil } @@ -69,7 +73,6 @@ func (t *Termbox) PollEvent(ctx context.Context) chan termbox.Event { if pdebug.Enabled { pdebug.Printf("poll event suspended!") } - termbox.Interrupt() t.Close() } }