From 9df5194c95e248055f7de4464d52fc4d662b7f13 Mon Sep 17 00:00:00 2001 From: c-bata Date: Sun, 24 Jun 2018 04:50:59 +0900 Subject: [PATCH] Separate signalHandler and InputProcessor from Prompt --- input_processor.go | 27 +++++++++++++++++++++++++++ prompt.go | 37 +++++++++++++------------------------ signal_posix.go | 5 ++--- signal_windows.go | 5 ++--- 4 files changed, 44 insertions(+), 30 deletions(-) create mode 100644 input_processor.go diff --git a/input_processor.go b/input_processor.go new file mode 100644 index 0000000..3f8e74a --- /dev/null +++ b/input_processor.go @@ -0,0 +1,27 @@ +package prompt + +import ( + "context" + "log" + "time" +) + +type InputProcessor struct { + in ConsoleParser +} + +func (ip *InputProcessor) Run(ctx context.Context, bufCh chan []byte) { + log.Printf("[INFO] Start running input processor") + for { + select { + case <-ctx.Done(): + log.Print("[INFO] Stop input processor") + return + default: + if b, err := ip.in.Read(); err == nil && !(len(b) == 1 && b[0] == 0) { + bufCh <- b + } + } + time.Sleep(10 * time.Millisecond) + } +} diff --git a/prompt.go b/prompt.go index ac86452..081d820 100644 --- a/prompt.go +++ b/prompt.go @@ -22,6 +22,7 @@ type Completer func(Document) []Suggest // Prompt is core struct of go-prompt. type Prompt struct { in ConsoleParser + inputProcessor *InputProcessor buf *Buffer renderer *Render executor Executor @@ -57,11 +58,11 @@ func (p *Prompt) Run() { p.renderer.Render(p.buf, p.completion) bufchan := make(chan []byte, 128) - go p.readBuffer(p.ctx, bufchan) + go p.inputProcessor.Run(p.ctx, bufchan) exitCh := make(chan int) - winchan := make(chan *WinSize) - go p.handleSignals(p.ctx, p.cancel, winchan) + winchan := make(chan struct{}) + go handleSignals(p.ctx, p.cancel, winchan) for { select { @@ -87,14 +88,15 @@ func (p *Prompt) Run() { ctx, cancel := context.WithCancel(context.Background()) p.ctx = ctx p.cancel = cancel - go p.readBuffer(p.ctx, bufchan) - go p.handleSignals(p.ctx, p.cancel, winchan) + go p.inputProcessor.Run(p.ctx, bufchan) + go handleSignals(p.ctx, p.cancel, winchan) } else { p.completion.Update(*p.buf.Document()) p.renderer.Render(p.buf, p.completion) } - case w := <-winchan: - p.renderer.UpdateWinSize(w) + case <-winchan: + ws := p.in.GetWinSize() + p.renderer.UpdateWinSize(ws) p.renderer.Render(p.buf, p.completion) case code := <-exitCh: p.renderer.BreakLine(p.buf) @@ -236,7 +238,7 @@ func (p *Prompt) Input() string { p.renderer.Render(p.buf, p.completion) bufchan := make(chan []byte, 128) - go p.readBuffer(p.ctx, bufchan) + go p.inputProcessor.Run(p.ctx, bufchan) for { select { @@ -257,26 +259,13 @@ func (p *Prompt) Input() string { } } -func (p *Prompt) readBuffer(ctx context.Context, bufCh chan []byte) { - log.Printf("[INFO] readBuffer start") - for { - select { - case <-ctx.Done(): - log.Print("[INFO] stop readBuffer") - return - default: - if b, err := p.in.Read(); err == nil && !(len(b) == 1 && b[0] == 0) { - bufCh <- b - } - } - time.Sleep(10 * time.Millisecond) - } -} - func (p *Prompt) setUp() { p.in.Setup() p.renderer.Setup() p.renderer.UpdateWinSize(p.in.GetWinSize()) + p.inputProcessor = &InputProcessor{ + in: p.in, + } ctx, cancel := context.WithCancel(context.Background()) p.ctx = ctx diff --git a/signal_posix.go b/signal_posix.go index 15020a5..edd877e 100644 --- a/signal_posix.go +++ b/signal_posix.go @@ -10,8 +10,7 @@ import ( "syscall" ) -func (p *Prompt) handleSignals(ctx context.Context, cancel context.CancelFunc, winSizeCh chan *WinSize) { - in := p.in +func handleSignals(ctx context.Context, cancel context.CancelFunc, sigwinchan chan struct{}) { sigchan := make(chan os.Signal, 1) signal.Notify( sigchan, @@ -42,7 +41,7 @@ func (p *Prompt) handleSignals(ctx context.Context, cancel context.CancelFunc, w case syscall.SIGWINCH: log.Println("[SIGNAL] Catch SIGWINCH") - winSizeCh <- in.GetWinSize() + sigwinchan <- struct{}{} } } } diff --git a/signal_windows.go b/signal_windows.go index c1d29ef..cad6db9 100644 --- a/signal_windows.go +++ b/signal_windows.go @@ -4,13 +4,12 @@ package prompt import ( "context" - "log" "os" "os/signal" "syscall" ) -func (p *Prompt) handleSignals(tx context.Context, cancel context.CancelFunc, winSizeCh chan *WinSize) { +func handleSignals(ctx context.Context, cancel context.CancelFunc, winsizechan chan struct{}) { sigCh := make(chan os.Signal, 1) signal.Notify( sigCh, @@ -29,7 +28,7 @@ func (p *Prompt) handleSignals(tx context.Context, cancel context.CancelFunc, wi cancel() case syscall.SIGTERM: // kill -SIGTERM XXXX - log.Println("[SIGNAL] Catch SIGTERM") + cancel() case syscall.SIGQUIT: // kill -SIGQUIT XXXX cancel()