-
Notifications
You must be signed in to change notification settings - Fork 269
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #188 from cheggaaa/v3-pooling
multiple progress bars on v3
- Loading branch information
Showing
14 changed files
with
249 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
// +build linux darwin freebsd netbsd openbsd solaris dragonfly windows plan9 aix | ||
|
||
package pb | ||
|
||
import ( | ||
"io" | ||
"sync" | ||
"time" | ||
|
||
"github.com/cheggaaa/pb/v3/termutil" | ||
) | ||
|
||
// Create and start new pool with given bars | ||
// You need call pool.Stop() after work | ||
func StartPool(pbs ...*ProgressBar) (pool *Pool, err error) { | ||
pool = new(Pool) | ||
if err = pool.Start(); err != nil { | ||
return | ||
} | ||
pool.Add(pbs...) | ||
return | ||
} | ||
|
||
// NewPool initialises a pool with progress bars, but | ||
// doesn't start it. You need to call Start manually | ||
func NewPool(pbs ...*ProgressBar) (pool *Pool) { | ||
pool = new(Pool) | ||
pool.Add(pbs...) | ||
return | ||
} | ||
|
||
type Pool struct { | ||
Output io.Writer | ||
RefreshRate time.Duration | ||
bars []*ProgressBar | ||
lastBarsCount int | ||
shutdownCh chan struct{} | ||
workerCh chan struct{} | ||
m sync.Mutex | ||
finishOnce sync.Once | ||
} | ||
|
||
// Add progress bars. | ||
func (p *Pool) Add(pbs ...*ProgressBar) { | ||
p.m.Lock() | ||
defer p.m.Unlock() | ||
for _, bar := range pbs { | ||
bar.Set(Static, true) | ||
bar.Start() | ||
p.bars = append(p.bars, bar) | ||
} | ||
} | ||
|
||
func (p *Pool) Start() (err error) { | ||
p.RefreshRate = defaultRefreshRate | ||
p.shutdownCh, err = termutil.RawModeOn() | ||
if err != nil { | ||
return | ||
} | ||
p.workerCh = make(chan struct{}) | ||
go p.writer() | ||
return | ||
} | ||
|
||
func (p *Pool) writer() { | ||
var first = true | ||
defer func() { | ||
if first == false { | ||
p.print(false) | ||
} else { | ||
p.print(true) | ||
p.print(false) | ||
} | ||
close(p.workerCh) | ||
}() | ||
|
||
for { | ||
select { | ||
case <-time.After(p.RefreshRate): | ||
if p.print(first) { | ||
p.print(false) | ||
return | ||
} | ||
first = false | ||
case <-p.shutdownCh: | ||
return | ||
} | ||
} | ||
} | ||
|
||
// Restore terminal state and close pool | ||
func (p *Pool) Stop() error { | ||
p.finishOnce.Do(func() { | ||
if p.shutdownCh != nil { | ||
close(p.shutdownCh) | ||
} | ||
}) | ||
|
||
// Wait for the worker to complete | ||
select { | ||
case <-p.workerCh: | ||
} | ||
|
||
return termutil.RawModeOff() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
// +build windows | ||
|
||
package pb | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
|
||
"github.com/cheggaaa/pb/v3/termutil" | ||
) | ||
|
||
func (p *Pool) print(first bool) bool { | ||
p.m.Lock() | ||
defer p.m.Unlock() | ||
var out string | ||
if !first { | ||
coords, err := termutil.GetCursorPos() | ||
if err != nil { | ||
log.Panic(err) | ||
} | ||
coords.Y -= int16(p.lastBarsCount) | ||
if coords.Y < 0 { | ||
coords.Y = 0 | ||
} | ||
coords.X = 0 | ||
|
||
err = termutil.SetCursorPos(coords) | ||
if err != nil { | ||
log.Panic(err) | ||
} | ||
} | ||
isFinished := true | ||
for _, bar := range p.bars { | ||
if !bar.IsFinished() { | ||
isFinished = false | ||
} | ||
out += fmt.Sprintf("\r%s\n", bar.String()) | ||
} | ||
if p.Output != nil { | ||
fmt.Fprint(p.Output, out) | ||
} else { | ||
fmt.Print(out) | ||
} | ||
p.lastBarsCount = len(p.bars) | ||
return isFinished | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// +build linux darwin freebsd netbsd openbsd solaris dragonfly plan9 aix | ||
|
||
package pb | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
|
||
"github.com/cheggaaa/pb/v3/termutil" | ||
) | ||
|
||
func (p *Pool) print(first bool) bool { | ||
p.m.Lock() | ||
defer p.m.Unlock() | ||
var out string | ||
if !first { | ||
out = fmt.Sprintf("\033[%dA", p.lastBarsCount) | ||
} | ||
isFinished := true | ||
bars := p.bars | ||
rows, cols, err := termutil.TerminalSize() | ||
if err != nil { | ||
cols = defaultBarWidth | ||
} | ||
if rows > 0 && len(bars) > rows { | ||
// we need to hide bars that overflow terminal height | ||
bars = bars[len(bars)-rows:] | ||
} | ||
for _, bar := range bars { | ||
if !bar.IsFinished() { | ||
isFinished = false | ||
} | ||
bar.SetWidth(cols) | ||
out += fmt.Sprintf("\r%s\n", bar.String()) | ||
} | ||
if p.Output != nil { | ||
fmt.Fprint(p.Output, out) | ||
} else { | ||
fmt.Fprint(os.Stderr, out) | ||
} | ||
p.lastBarsCount = len(bars) | ||
return isFinished | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
//go:build appengine | ||
// +build appengine | ||
|
||
package termutil | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
// +build linux | ||
// +build !appengine | ||
//go:build linux && !appengine | ||
// +build linux,!appengine | ||
|
||
package termutil | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters