| 1 | 1 |
|
| 2 | 2 |
import (
|
| 3 | 3 |
"errors"
|
|
4 |
"fmt"
|
| 4 | 5 |
"io"
|
| 5 | 6 |
"log"
|
| 6 | 7 |
"os"
|
|
| 227 | 228 |
close(p.done)
|
| 228 | 229 |
}()
|
| 229 | 230 |
|
| 230 | |
var wg sync.WaitGroup
|
| 231 | |
recoverIfPanic := func() {
|
|
231 |
recoverFn := func(ch chan []byte) {
|
| 232 | 232 |
if p := recover(); p != nil {
|
| 233 | |
logger.Printf("unexpected panic: %+v\n", p)
|
| 234 | 233 |
var buf [4096]byte
|
| 235 | 234 |
n := runtime.Stack(buf[:], false)
|
| 236 | 235 |
os.Stderr.Write(buf[:n])
|
|
236 |
ch <- []byte(fmt.Sprintln(p))
|
| 237 | 237 |
}
|
| 238 | |
wg.Done()
|
|
238 |
close(ch)
|
| 239 | 239 |
}
|
| 240 | 240 |
|
| 241 | 241 |
var beforeRender BeforeRender
|
|
| 291 | 291 |
appendWs := newWidthSync(quitWidthSyncCh, numBars, b0.NumOfAppenders())
|
| 292 | 292 |
|
| 293 | 293 |
width, _, _ := cwriter.GetTermSize()
|
| 294 | |
ibars := iBarsGen(bars, width)
|
| 295 | |
ibbCh := make(chan indexedBarBuffer)
|
| 296 | |
wg.Add(numBars)
|
| 297 | |
for i := 0; i < numBars; i++ {
|
| 298 | |
go func() {
|
| 299 | |
defer recoverIfPanic()
|
| 300 | |
drawer(ibars, ibbCh, prependWs, appendWs)
|
| 301 | |
}()
|
| 302 | |
}
|
| 303 | |
go func() {
|
| 304 | |
wg.Wait()
|
| 305 | |
close(ibbCh)
|
| 306 | |
for _, ch := range prependWs.listen {
|
| 307 | |
close(ch)
|
| 308 | |
}
|
| 309 | |
for _, ch := range appendWs.listen {
|
| 310 | |
close(ch)
|
| 311 | |
}
|
| 312 | |
}()
|
| 313 | |
|
| 314 | |
m := make(map[int][]byte, len(bars))
|
| 315 | |
for ibb := range ibbCh {
|
| 316 | |
m[ibb.index] = ibb.buf
|
| 317 | |
}
|
| 318 | |
for i := 0; i < len(bars); i++ {
|
| 319 | |
cw.Write(m[i])
|
|
294 |
|
|
295 |
sequence := make([]<-chan []byte, numBars)
|
|
296 |
for i, b := range bars {
|
|
297 |
sequence[i] = b.render(recoverFn, width, prependWs, appendWs)
|
|
298 |
}
|
|
299 |
|
|
300 |
ch := fanIn(sequence...)
|
|
301 |
|
|
302 |
for buf := range ch {
|
|
303 |
cw.Write(buf)
|
| 320 | 304 |
}
|
| 321 | 305 |
|
| 322 | 306 |
cw.Flush()
|
|
| 370 | 354 |
return ws
|
| 371 | 355 |
}
|
| 372 | 356 |
|
| 373 | |
func drawer(ibars <-chan indexedBar, ibbCh chan<- indexedBarBuffer, prependWs, appendWs *widthSync) {
|
| 374 | |
for b := range ibars {
|
| 375 | |
buf := b.bar.bytes(b.termWidth, prependWs, appendWs)
|
| 376 | |
buf = append(buf, '\n')
|
| 377 | |
ibbCh <- indexedBarBuffer{b.index, buf}
|
| 378 | |
}
|
| 379 | |
}
|
| 380 | |
|
| 381 | |
func iBarsGen(bars []*Bar, width int) <-chan indexedBar {
|
| 382 | |
ibars := make(chan indexedBar)
|
|
357 |
func fanIn(inputs ...<-chan []byte) <-chan []byte {
|
|
358 |
ch := make(chan []byte)
|
|
359 |
|
| 383 | 360 |
go func() {
|
| 384 | |
defer close(ibars)
|
| 385 | |
for i, b := range bars {
|
| 386 | |
ibars <- indexedBar{i, width, b}
|
|
361 |
defer close(ch)
|
|
362 |
for _, input := range inputs {
|
|
363 |
ch <- <-input
|
| 387 | 364 |
}
|
| 388 | 365 |
}()
|
| 389 | |
return ibars
|
|
366 |
|
|
367 |
return ch
|
| 390 | 368 |
}
|
| 391 | 369 |
|
| 392 | 370 |
// isClosed check if ch closed
|