progress' output is changable any time
Vladimir Bauer
9 years ago
| 34 | 34 | sort SortType |
| 35 | 35 | stopped bool |
| 36 | 36 | |
| 37 | op chan *operation | |
| 38 | rrChangeReqCh chan time.Duration | |
| 37 | op chan *operation | |
| 38 | rrChangeReqCh chan time.Duration | |
| 39 | outChangeReqCh chan io.Writer | |
| 39 | 40 | |
| 40 | 41 | wg *sync.WaitGroup |
| 41 | 42 | } |
| 49 | 50 | // New returns a new progress bar with defaults |
| 50 | 51 | func New() *Progress { |
| 51 | 52 | p := &Progress{ |
| 52 | out: os.Stdout, | |
| 53 | width: 70, | |
| 54 | op: make(chan *operation), | |
| 55 | rrChangeReqCh: make(chan time.Duration), | |
| 56 | wg: new(sync.WaitGroup), | |
| 53 | width: 70, | |
| 54 | op: make(chan *operation), | |
| 55 | rrChangeReqCh: make(chan time.Duration), | |
| 56 | outChangeReqCh: make(chan io.Writer), | |
| 57 | wg: new(sync.WaitGroup), | |
| 57 | 58 | } |
| 58 | go p.server() | |
| 59 | go p.server(cwriter.New(os.Stdout)) | |
| 59 | 60 | return p |
| 60 | 61 | } |
| 61 | 62 | |
| 73 | 74 | if w == nil { |
| 74 | 75 | return p |
| 75 | 76 | } |
| 76 | p.out = w | |
| 77 | p.outChangeReqCh <- w | |
| 77 | 78 | return p |
| 78 | 79 | } |
| 79 | 80 | |
| 113 | 114 | } |
| 114 | 115 | |
| 115 | 116 | // server monitors underlying channels and renders any progress bars |
| 116 | func (p *Progress) server() { | |
| 117 | func (p *Progress) server(cw *cwriter.Writer) { | |
| 117 | 118 | t := time.NewTicker(refreshRate * time.Millisecond) |
| 118 | 119 | bars := make([]*Bar, 0, 4) |
| 119 | lw := cwriter.New(p.out) | |
| 120 | 120 | for { |
| 121 | 121 | select { |
| 122 | case w := <-p.outChangeReqCh: | |
| 123 | cw.Flush() | |
| 124 | cw = cwriter.New(w) | |
| 122 | 125 | case op, ok := <-p.op: |
| 123 | 126 | if !ok { |
| 124 | 127 | // fmt.Fprintln(os.Stderr, "Sopping bars") |
| 152 | 155 | } |
| 153 | 156 | for _, b := range bars { |
| 154 | 157 | // cannot parallel this, because order matters |
| 155 | fmt.Fprintln(lw, b) | |
| 158 | fmt.Fprintln(cw, b) | |
| 156 | 159 | } |
| 157 | lw.Flush() | |
| 160 | cw.Flush() | |
| 158 | 161 | for _, b := range bars { |
| 159 | 162 | go func(b *Bar) { |
| 160 | 163 | b.flushedCh <- struct{}{} |