update progress rendering to be closer to v0.1.10
This commit is contained in:
parent
95b9acd324
commit
c06b9b7304
4 changed files with 46 additions and 70 deletions
29
cmd/cmd.go
29
cmd/cmd.go
|
@ -53,10 +53,6 @@ func CreateHandler(cmd *cobra.Command, args []string) error {
|
||||||
|
|
||||||
bars := make(map[string]*progress.Bar)
|
bars := make(map[string]*progress.Bar)
|
||||||
|
|
||||||
status := fmt.Sprintf("creating %s", args[0])
|
|
||||||
spinner := progress.NewSpinner(status)
|
|
||||||
p.Add(status, spinner)
|
|
||||||
|
|
||||||
modelfile, err := os.ReadFile(filename)
|
modelfile, err := os.ReadFile(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -72,10 +68,8 @@ func CreateHandler(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
spinner.Stop()
|
status := "transferring model data"
|
||||||
|
spinner := progress.NewSpinner(status)
|
||||||
status = "transferring model data"
|
|
||||||
spinner = progress.NewSpinner(status)
|
|
||||||
p.Add(status, spinner)
|
p.Add(status, spinner)
|
||||||
|
|
||||||
for _, c := range commands {
|
for _, c := range commands {
|
||||||
|
@ -179,14 +173,14 @@ func PushHandler(cmd *cobra.Command, args []string) error {
|
||||||
defer p.Stop()
|
defer p.Stop()
|
||||||
|
|
||||||
bars := make(map[string]*progress.Bar)
|
bars := make(map[string]*progress.Bar)
|
||||||
|
var status string
|
||||||
status := fmt.Sprintf("pushing %s", args[0])
|
var spinner *progress.Spinner
|
||||||
spinner := progress.NewSpinner(status)
|
|
||||||
p.Add(status, spinner)
|
|
||||||
|
|
||||||
fn := func(resp api.ProgressResponse) error {
|
fn := func(resp api.ProgressResponse) error {
|
||||||
if resp.Digest != "" {
|
if resp.Digest != "" {
|
||||||
|
if spinner != nil {
|
||||||
spinner.Stop()
|
spinner.Stop()
|
||||||
|
}
|
||||||
|
|
||||||
bar, ok := bars[resp.Digest]
|
bar, ok := bars[resp.Digest]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -197,7 +191,9 @@ func PushHandler(cmd *cobra.Command, args []string) error {
|
||||||
|
|
||||||
bar.Set(resp.Completed)
|
bar.Set(resp.Completed)
|
||||||
} else if status != resp.Status {
|
} else if status != resp.Status {
|
||||||
|
if spinner != nil {
|
||||||
spinner.Stop()
|
spinner.Stop()
|
||||||
|
}
|
||||||
|
|
||||||
status = resp.Status
|
status = resp.Status
|
||||||
spinner = progress.NewSpinner(status)
|
spinner = progress.NewSpinner(status)
|
||||||
|
@ -373,13 +369,14 @@ func PullHandler(cmd *cobra.Command, args []string) error {
|
||||||
|
|
||||||
bars := make(map[string]*progress.Bar)
|
bars := make(map[string]*progress.Bar)
|
||||||
|
|
||||||
status := fmt.Sprintf("pulling %s", args[0])
|
var status string
|
||||||
spinner := progress.NewSpinner(status)
|
var spinner *progress.Spinner
|
||||||
p.Add(status, spinner)
|
|
||||||
|
|
||||||
fn := func(resp api.ProgressResponse) error {
|
fn := func(resp api.ProgressResponse) error {
|
||||||
if resp.Digest != "" {
|
if resp.Digest != "" {
|
||||||
|
if spinner != nil {
|
||||||
spinner.Stop()
|
spinner.Stop()
|
||||||
|
}
|
||||||
|
|
||||||
bar, ok := bars[resp.Digest]
|
bar, ok := bars[resp.Digest]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -390,7 +387,9 @@ func PullHandler(cmd *cobra.Command, args []string) error {
|
||||||
|
|
||||||
bar.Set(resp.Completed)
|
bar.Set(resp.Completed)
|
||||||
} else if status != resp.Status {
|
} else if status != resp.Status {
|
||||||
|
if spinner != nil {
|
||||||
spinner.Stop()
|
spinner.Stop()
|
||||||
|
}
|
||||||
|
|
||||||
status = resp.Status
|
status = resp.Status
|
||||||
spinner = progress.NewSpinner(status)
|
spinner = progress.NewSpinner(status)
|
||||||
|
|
|
@ -66,7 +66,8 @@ func (b *Bar) String() string {
|
||||||
|
|
||||||
mid.WriteString("▕")
|
mid.WriteString("▕")
|
||||||
|
|
||||||
f := termWidth - pre.Len() - suf.Len() - 2
|
// add 3 extra spaces: 2 boundary characters and 1 space at the end
|
||||||
|
f := termWidth - pre.Len() - suf.Len() - 3
|
||||||
n := int(float64(f) * b.percent() / 100)
|
n := int(float64(f) * b.percent() / 100)
|
||||||
|
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
|
|
|
@ -13,9 +13,10 @@ type State interface {
|
||||||
|
|
||||||
type Progress struct {
|
type Progress struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
pos int
|
|
||||||
w io.Writer
|
w io.Writer
|
||||||
|
|
||||||
|
pos int
|
||||||
|
|
||||||
ticker *time.Ticker
|
ticker *time.Ticker
|
||||||
states []State
|
states []State
|
||||||
}
|
}
|
||||||
|
@ -37,6 +38,7 @@ func (p *Progress) Stop() bool {
|
||||||
p.ticker.Stop()
|
p.ticker.Stop()
|
||||||
p.ticker = nil
|
p.ticker = nil
|
||||||
p.render()
|
p.render()
|
||||||
|
fmt.Fprint(p.w, "\n")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,11 +52,8 @@ func (p *Progress) StopAndClear() bool {
|
||||||
stopped := p.Stop()
|
stopped := p.Stop()
|
||||||
if stopped {
|
if stopped {
|
||||||
// clear the progress bar by:
|
// clear the progress bar by:
|
||||||
// 1. for each line in the progress:
|
|
||||||
// a. move the cursor up one line
|
|
||||||
// b. clear the line
|
|
||||||
for i := 0; i < p.pos; i++ {
|
for i := 0; i < p.pos; i++ {
|
||||||
fmt.Fprint(p.w, "\033[A\033[2K")
|
fmt.Fprint(p.w, "\033[A\033[2K\033[1G")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,17 +74,23 @@ func (p *Progress) render() error {
|
||||||
fmt.Fprint(p.w, "\033[?25l")
|
fmt.Fprint(p.w, "\033[?25l")
|
||||||
defer fmt.Fprint(p.w, "\033[?25h")
|
defer fmt.Fprint(p.w, "\033[?25h")
|
||||||
|
|
||||||
if p.pos > 0 {
|
// clear already rendered progress lines
|
||||||
fmt.Fprintf(p.w, "\033[%dA", p.pos)
|
for i := 0; i < p.pos; i++ {
|
||||||
|
if i > 0 {
|
||||||
|
fmt.Fprint(p.w, "\033[A")
|
||||||
|
}
|
||||||
|
fmt.Fprint(p.w, "\033[2K\033[1G")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, state := range p.states {
|
// render progress lines
|
||||||
fmt.Fprintln(p.w, state.String())
|
for i, state := range p.states {
|
||||||
|
fmt.Fprint(p.w, state.String())
|
||||||
|
if i < len(p.states)-1 {
|
||||||
|
fmt.Fprint(p.w, "\n")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(p.states) > 0 {
|
|
||||||
p.pos = len(p.states)
|
p.pos = len(p.states)
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,8 @@ package progress
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/term"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Spinner struct {
|
type Spinner struct {
|
||||||
|
@ -35,45 +32,28 @@ func NewSpinner(message string) *Spinner {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Spinner) String() string {
|
func (s *Spinner) String() string {
|
||||||
termWidth, _, err := term.GetSize(int(os.Stderr.Fd()))
|
var sb strings.Builder
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var pre strings.Builder
|
|
||||||
if len(s.message) > 0 {
|
if len(s.message) > 0 {
|
||||||
message := strings.TrimSpace(s.message)
|
message := strings.TrimSpace(s.message)
|
||||||
if s.messageWidth > 0 && len(message) > s.messageWidth {
|
if s.messageWidth > 0 && len(message) > s.messageWidth {
|
||||||
message = message[:s.messageWidth]
|
message = message[:s.messageWidth]
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(&pre, "%s", message)
|
fmt.Fprintf(&sb, "%s", message)
|
||||||
if s.messageWidth-pre.Len() >= 0 {
|
if s.messageWidth-sb.Len() >= 0 {
|
||||||
pre.WriteString(strings.Repeat(" ", s.messageWidth-pre.Len()))
|
sb.WriteString(strings.Repeat(" ", s.messageWidth-sb.Len()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pre.WriteString(" ")
|
sb.WriteString(" ")
|
||||||
}
|
}
|
||||||
|
|
||||||
var pad int
|
|
||||||
if s.stopped.IsZero() {
|
if s.stopped.IsZero() {
|
||||||
// spinner has a string length of 3 but a rune length of 1
|
|
||||||
// in order to align correctly, we need to pad with (3 - 1) = 2 spaces
|
|
||||||
spinner := s.parts[s.value]
|
spinner := s.parts[s.value]
|
||||||
pre.WriteString(spinner)
|
sb.WriteString(spinner)
|
||||||
pad = len(spinner) - len([]rune(spinner))
|
sb.WriteString(" ")
|
||||||
}
|
}
|
||||||
|
|
||||||
var suf strings.Builder
|
return sb.String()
|
||||||
fmt.Fprintf(&suf, "(%s)", s.elapsed())
|
|
||||||
|
|
||||||
var mid strings.Builder
|
|
||||||
f := termWidth - pre.Len() - mid.Len() - suf.Len() + pad
|
|
||||||
if f > 0 {
|
|
||||||
mid.WriteString(strings.Repeat(" ", f))
|
|
||||||
}
|
|
||||||
|
|
||||||
return pre.String() + mid.String() + suf.String()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Spinner) start() {
|
func (s *Spinner) start() {
|
||||||
|
@ -91,12 +71,3 @@ func (s *Spinner) Stop() {
|
||||||
s.stopped = time.Now()
|
s.stopped = time.Now()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Spinner) elapsed() time.Duration {
|
|
||||||
stopped := s.stopped
|
|
||||||
if stopped.IsZero() {
|
|
||||||
stopped = time.Now()
|
|
||||||
}
|
|
||||||
|
|
||||||
return stopped.Sub(s.started).Round(time.Second)
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue