83 lines
1.5 KiB
Go
83 lines
1.5 KiB
Go
package main
|
||
|
||
import (
|
||
"fmt"
|
||
"os"
|
||
"strings"
|
||
"unicode"
|
||
|
||
"golang.org/x/term"
|
||
|
||
"zipveil/internal/zipveil"
|
||
)
|
||
|
||
type progressDisplay struct {
|
||
label string
|
||
last int
|
||
lastName string
|
||
shown bool
|
||
closed bool
|
||
}
|
||
|
||
func newProgressDisplay(label string) *progressDisplay {
|
||
if !term.IsTerminal(int(os.Stderr.Fd())) {
|
||
return nil
|
||
}
|
||
return &progressDisplay{label: label, last: -1}
|
||
}
|
||
|
||
func (display *progressDisplay) callback() zipveil.ProgressFunc {
|
||
if display == nil {
|
||
return nil
|
||
}
|
||
return display.update
|
||
}
|
||
|
||
func (display *progressDisplay) update(done, total uint64, current string, finished bool) {
|
||
if display == nil || display.closed {
|
||
return
|
||
}
|
||
percent := 0
|
||
if finished {
|
||
percent = 100
|
||
} else if total > 0 {
|
||
percent = int(float64(done) / float64(total) * 100)
|
||
if percent > 99 {
|
||
percent = 99
|
||
}
|
||
}
|
||
current = cleanProgressName(current)
|
||
if percent != display.last || current != display.lastName {
|
||
_, _ = fmt.Fprintf(os.Stderr, "\r[%3d/100%%]正在%s:%s\033[K", percent, display.label, current)
|
||
display.last = percent
|
||
display.lastName = current
|
||
display.shown = true
|
||
}
|
||
if finished {
|
||
display.closeLine()
|
||
}
|
||
}
|
||
|
||
func cleanProgressName(name string) string {
|
||
return strings.Map(func(r rune) rune {
|
||
if unicode.IsControl(r) {
|
||
return '�'
|
||
}
|
||
return r
|
||
}, name)
|
||
}
|
||
|
||
func (display *progressDisplay) closeLine() {
|
||
if display == nil || display.closed {
|
||
return
|
||
}
|
||
if display.shown {
|
||
_, _ = fmt.Fprintln(os.Stderr)
|
||
}
|
||
display.closed = true
|
||
}
|
||
|
||
func (display *progressDisplay) Close() {
|
||
display.closeLine()
|
||
}
|