[windows] fix ansi parse by remove channel

This commit is contained in:
chzyer 2016-07-24 00:39:44 +08:00
parent 4f0ff8f850
commit f83f3269ca
1 changed files with 36 additions and 51 deletions

View File

@ -51,89 +51,73 @@ var ColorTableBg = []word{
type ANSIWriter struct { type ANSIWriter struct {
target io.Writer target io.Writer
ch chan rune
wg sync.WaitGroup wg sync.WaitGroup
ctx *ANSIWriterCtx
sync.Mutex sync.Mutex
} }
func NewANSIWriter(w io.Writer) *ANSIWriter { func NewANSIWriter(w io.Writer) *ANSIWriter {
a := &ANSIWriter{ a := &ANSIWriter{
target: w, target: w,
ch: make(chan rune), ctx: NewANSIWriterCtx(w),
} }
go a.ioloop()
return a return a
} }
func (a *ANSIWriter) Close() error { func (a *ANSIWriter) Close() error {
close(a.ch)
a.wg.Wait() a.wg.Wait()
return nil return nil
} }
func (a *ANSIWriter) ioloop() { type ANSIWriterCtx struct {
a.wg.Add(1) isEsc bool
defer a.wg.Done() isEscSeq bool
arg []string
target *bufio.Writer
wantFlush bool
}
var ( func NewANSIWriterCtx(target io.Writer) *ANSIWriterCtx {
ok bool return &ANSIWriterCtx{
isEsc bool target: bufio.NewWriter(target),
isEscSeq bool }
}
char rune func (a *ANSIWriterCtx) Flush() {
arg []string a.target.Flush()
}
target = bufio.NewWriter(a.target) func (a *ANSIWriterCtx) process(r rune) bool {
) if a.wantFlush {
if r == 0 || r == CharEsc {
peek := func() rune { a.wantFlush = false
select { a.target.Flush()
case ch := <-a.ch:
return ch
default:
return 0
} }
} }
if a.isEscSeq {
read: a.isEscSeq = a.ioloopEscSeq(a.target, r, &a.arg)
r := char return true
if char == 0 {
r, ok = <-a.ch
if !ok {
target.Flush()
return
}
} else {
char = 0
}
if isEscSeq {
isEscSeq = a.ioloopEscSeq(target, r, &arg)
goto read
} }
switch r { switch r {
case CharEsc: case CharEsc:
isEsc = true a.isEsc = true
case '[': case '[':
if isEsc { if a.isEsc {
arg = nil a.arg = nil
isEscSeq = true a.isEscSeq = true
isEsc = false a.isEsc = false
break break
} }
fallthrough fallthrough
default: default:
target.WriteRune(r) a.target.WriteRune(r)
char = peek() a.wantFlush = true
if char == 0 || char == CharEsc {
target.Flush()
}
} }
goto read return true
} }
func (a *ANSIWriter) ioloopEscSeq(w *bufio.Writer, r rune, argptr *[]string) bool { func (a *ANSIWriterCtx) ioloopEscSeq(w *bufio.Writer, r rune, argptr *[]string) bool {
arg := *argptr arg := *argptr
var err error var err error
@ -217,8 +201,9 @@ func (a *ANSIWriter) Write(b []byte) (int, error) {
return off, io.ErrShortWrite return off, io.ErrShortWrite
} }
off += size off += size
a.ch <- r a.ctx.process(r)
} }
a.ctx.Flush()
return off, nil return off, nil
} }