132 lines
2.5 KiB
Go
132 lines
2.5 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"slices"
|
||
|
"sync"
|
||
|
|
||
|
"github.com/gosuri/uiprogress"
|
||
|
"src.lwithers.me.uk/go/htpack/cmd/htpacker/packer"
|
||
|
)
|
||
|
|
||
|
type uiProgress struct {
|
||
|
p *uiprogress.Progress
|
||
|
uncompressed, gzip, brotli *uiProgressBar
|
||
|
}
|
||
|
|
||
|
func newUiProgress(ftp packer.FilesToPack) *uiProgress {
|
||
|
up := &uiProgress{
|
||
|
p: uiprogress.New(),
|
||
|
}
|
||
|
|
||
|
up.uncompressed = newUiProgressBar(up.p, len(ftp), "uncompressed")
|
||
|
var nGzip, nBrotli int
|
||
|
for _, f := range ftp {
|
||
|
if !f.DisableCompression && !f.DisableGzip {
|
||
|
nGzip++
|
||
|
}
|
||
|
if !f.DisableCompression && !f.DisableBrotli {
|
||
|
nBrotli++
|
||
|
}
|
||
|
}
|
||
|
if nGzip > 0 {
|
||
|
up.gzip = newUiProgressBar(up.p, nGzip, "gzip")
|
||
|
}
|
||
|
if nBrotli > 0 {
|
||
|
up.brotli = newUiProgressBar(up.p, nGzip, "brotli")
|
||
|
}
|
||
|
|
||
|
up.p.Start()
|
||
|
return up
|
||
|
}
|
||
|
|
||
|
func (up *uiProgress) Count(_ int) {
|
||
|
}
|
||
|
|
||
|
func (up *uiProgress) Begin(filename, compression string) {
|
||
|
up.bar(compression).begin(filename)
|
||
|
}
|
||
|
|
||
|
func (up *uiProgress) End(filename, compression string) {
|
||
|
up.bar(compression).end(filename)
|
||
|
}
|
||
|
|
||
|
func (up *uiProgress) bar(compression string) *uiProgressBar {
|
||
|
switch compression {
|
||
|
case "uncompressed":
|
||
|
return up.uncompressed
|
||
|
case "gzip":
|
||
|
return up.gzip
|
||
|
case "brotli":
|
||
|
return up.brotli
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (up *uiProgress) Complete() {
|
||
|
up.p.Stop()
|
||
|
}
|
||
|
|
||
|
type uiProgressBar struct {
|
||
|
bar *uiprogress.Bar
|
||
|
lock sync.Mutex
|
||
|
inflight []string
|
||
|
}
|
||
|
|
||
|
func newUiProgressBar(p *uiprogress.Progress, total int, compression string) *uiProgressBar {
|
||
|
bar := &uiProgressBar{
|
||
|
bar: p.AddBar(total).AppendCompleted(),
|
||
|
}
|
||
|
|
||
|
var buf bytes.Buffer
|
||
|
bar.bar.PrependFunc(func(*uiprogress.Bar) string {
|
||
|
bar.lock.Lock()
|
||
|
defer bar.lock.Unlock()
|
||
|
buf.Reset()
|
||
|
buf.WriteString(compression)
|
||
|
if len(bar.inflight) > 0 {
|
||
|
buf.WriteString(" (")
|
||
|
for i, f := range bar.inflight {
|
||
|
if i > 0 {
|
||
|
buf.WriteString(", ")
|
||
|
}
|
||
|
buf.WriteString(f)
|
||
|
}
|
||
|
buf.WriteRune(')')
|
||
|
}
|
||
|
if buf.Len() < 40 {
|
||
|
buf.WriteString(" ")
|
||
|
buf.Truncate(40)
|
||
|
} else if buf.Len() > 40 {
|
||
|
buf.Truncate(39)
|
||
|
buf.WriteString("…")
|
||
|
}
|
||
|
return buf.String()
|
||
|
})
|
||
|
|
||
|
return bar
|
||
|
}
|
||
|
|
||
|
func (bar *uiProgressBar) begin(filename string) {
|
||
|
if bar == nil {
|
||
|
return
|
||
|
}
|
||
|
bar.lock.Lock()
|
||
|
defer bar.lock.Unlock()
|
||
|
|
||
|
bar.inflight = append(bar.inflight, filename)
|
||
|
}
|
||
|
|
||
|
func (bar *uiProgressBar) end(filename string) {
|
||
|
if bar == nil {
|
||
|
return
|
||
|
}
|
||
|
bar.lock.Lock()
|
||
|
defer bar.lock.Unlock()
|
||
|
|
||
|
bar.bar.Incr()
|
||
|
if idx := slices.Index(bar.inflight, filename); idx != -1 {
|
||
|
bar.inflight = slices.Delete(bar.inflight, idx, idx+1)
|
||
|
}
|
||
|
}
|