mirror of https://github.com/chzyer/readline.git
let stdin cancelable (#72)
This commit is contained in:
parent
27fdf0b285
commit
6cbc078c57
52
std.go
52
std.go
|
@ -7,7 +7,7 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
Stdin io.ReadCloser = os.Stdin
|
||||
Stdin io.ReadCloser = NewCancelableStdin()
|
||||
Stdout io.WriteCloser = os.Stdout
|
||||
Stderr io.WriteCloser = os.Stderr
|
||||
)
|
||||
|
@ -64,3 +64,53 @@ func Line(prompt string) (string, error) {
|
|||
ins.SetPrompt(prompt)
|
||||
return ins.Readline()
|
||||
}
|
||||
|
||||
type CancelableStdin struct {
|
||||
mutex sync.Mutex
|
||||
stop chan struct{}
|
||||
notify chan struct{}
|
||||
data []byte
|
||||
read int
|
||||
err error
|
||||
}
|
||||
|
||||
func NewCancelableStdin() *CancelableStdin {
|
||||
c := &CancelableStdin{
|
||||
notify: make(chan struct{}),
|
||||
stop: make(chan struct{}),
|
||||
}
|
||||
go c.ioloop()
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *CancelableStdin) ioloop() {
|
||||
loop:
|
||||
for {
|
||||
select {
|
||||
case <-c.notify:
|
||||
c.read, c.err = os.Stdin.Read(c.data)
|
||||
<-c.notify
|
||||
case <-c.stop:
|
||||
break loop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CancelableStdin) Read(b []byte) (n int, err error) {
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
|
||||
c.data = b
|
||||
c.notify <- struct{}{}
|
||||
select {
|
||||
case <-c.notify:
|
||||
return c.read, c.err
|
||||
case <-c.stop:
|
||||
return 0, io.EOF
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CancelableStdin) Close() error {
|
||||
close(c.stop)
|
||||
return nil
|
||||
}
|
||||
|
|
14
terminal.go
14
terminal.go
|
@ -3,6 +3,7 @@ package readline
|
|||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
@ -109,7 +110,11 @@ func (t *Terminal) KickRead() {
|
|||
|
||||
func (t *Terminal) ioloop() {
|
||||
t.wg.Add(1)
|
||||
defer t.wg.Done()
|
||||
defer func() {
|
||||
t.wg.Done()
|
||||
close(t.outchan)
|
||||
}()
|
||||
|
||||
var (
|
||||
isEscape bool
|
||||
isEscapeEx bool
|
||||
|
@ -182,7 +187,7 @@ func (t *Terminal) ioloop() {
|
|||
t.outchan <- r
|
||||
}
|
||||
}
|
||||
close(t.outchan)
|
||||
|
||||
}
|
||||
|
||||
func (t *Terminal) Bell() {
|
||||
|
@ -193,7 +198,10 @@ func (t *Terminal) Close() error {
|
|||
if atomic.SwapInt32(&t.closed, 1) != 0 {
|
||||
return nil
|
||||
}
|
||||
t.stopChan <- struct{}{}
|
||||
if closer, ok := t.cfg.Stdin.(io.Closer); ok {
|
||||
closer.Close()
|
||||
}
|
||||
close(t.stopChan)
|
||||
t.wg.Wait()
|
||||
return t.ExitRawMode()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue