Ver código fonte

update progress rendering to be closer to `v0.1.10`

Jeffrey Morgan 1 ano atrás
pai
commit
c06b9b7304
4 arquivos alterados com 46 adições e 70 exclusões
  1. 18 19
      cmd/cmd.go
  2. 2 1
      progress/bar.go
  3. 18 13
      progress/progress.go
  4. 8 37
      progress/spinner.go

+ 18 - 19
cmd/cmd.go

@@ -53,10 +53,6 @@ func CreateHandler(cmd *cobra.Command, args []string) error {
 
 	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)
 	if err != nil {
 		return err
@@ -72,10 +68,8 @@ func CreateHandler(cmd *cobra.Command, args []string) error {
 		return err
 	}
 
-	spinner.Stop()
-
-	status = "transferring model data"
-	spinner = progress.NewSpinner(status)
+	status := "transferring model data"
+	spinner := progress.NewSpinner(status)
 	p.Add(status, spinner)
 
 	for _, c := range commands {
@@ -179,14 +173,14 @@ func PushHandler(cmd *cobra.Command, args []string) error {
 	defer p.Stop()
 
 	bars := make(map[string]*progress.Bar)
-
-	status := fmt.Sprintf("pushing %s", args[0])
-	spinner := progress.NewSpinner(status)
-	p.Add(status, spinner)
+	var status string
+	var spinner *progress.Spinner
 
 	fn := func(resp api.ProgressResponse) error {
 		if resp.Digest != "" {
-			spinner.Stop()
+			if spinner != nil {
+				spinner.Stop()
+			}
 
 			bar, ok := bars[resp.Digest]
 			if !ok {
@@ -197,7 +191,9 @@ func PushHandler(cmd *cobra.Command, args []string) error {
 
 			bar.Set(resp.Completed)
 		} else if status != resp.Status {
-			spinner.Stop()
+			if spinner != nil {
+				spinner.Stop()
+			}
 
 			status = resp.Status
 			spinner = progress.NewSpinner(status)
@@ -373,13 +369,14 @@ func PullHandler(cmd *cobra.Command, args []string) error {
 
 	bars := make(map[string]*progress.Bar)
 
-	status := fmt.Sprintf("pulling %s", args[0])
-	spinner := progress.NewSpinner(status)
-	p.Add(status, spinner)
+	var status string
+	var spinner *progress.Spinner
 
 	fn := func(resp api.ProgressResponse) error {
 		if resp.Digest != "" {
-			spinner.Stop()
+			if spinner != nil {
+				spinner.Stop()
+			}
 
 			bar, ok := bars[resp.Digest]
 			if !ok {
@@ -390,7 +387,9 @@ func PullHandler(cmd *cobra.Command, args []string) error {
 
 			bar.Set(resp.Completed)
 		} else if status != resp.Status {
-			spinner.Stop()
+			if spinner != nil {
+				spinner.Stop()
+			}
 
 			status = resp.Status
 			spinner = progress.NewSpinner(status)

+ 2 - 1
progress/bar.go

@@ -66,7 +66,8 @@ func (b *Bar) String() string {
 
 	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)
 
 	if n > 0 {

+ 18 - 13
progress/progress.go

@@ -12,9 +12,10 @@ type State interface {
 }
 
 type Progress struct {
-	mu  sync.Mutex
+	mu sync.Mutex
+	w  io.Writer
+
 	pos int
-	w   io.Writer
 
 	ticker *time.Ticker
 	states []State
@@ -37,6 +38,7 @@ func (p *Progress) Stop() bool {
 		p.ticker.Stop()
 		p.ticker = nil
 		p.render()
+		fmt.Fprint(p.w, "\n")
 		return true
 	}
 
@@ -50,11 +52,8 @@ func (p *Progress) StopAndClear() bool {
 	stopped := p.Stop()
 	if stopped {
 		// 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++ {
-			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")
 	defer fmt.Fprint(p.w, "\033[?25h")
 
-	if p.pos > 0 {
-		fmt.Fprintf(p.w, "\033[%dA", p.pos)
+	// clear already rendered progress lines
+	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 {
-		fmt.Fprintln(p.w, state.String())
+	// render progress lines
+	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
 }

+ 8 - 37
progress/spinner.go

@@ -2,11 +2,8 @@ package progress
 
 import (
 	"fmt"
-	"os"
 	"strings"
 	"time"
-
-	"golang.org/x/term"
 )
 
 type Spinner struct {
@@ -35,45 +32,28 @@ func NewSpinner(message string) *Spinner {
 }
 
 func (s *Spinner) String() string {
-	termWidth, _, err := term.GetSize(int(os.Stderr.Fd()))
-	if err != nil {
-		panic(err)
-	}
-
-	var pre strings.Builder
+	var sb strings.Builder
 	if len(s.message) > 0 {
 		message := strings.TrimSpace(s.message)
 		if s.messageWidth > 0 && len(message) > s.messageWidth {
 			message = message[:s.messageWidth]
 		}
 
-		fmt.Fprintf(&pre, "%s", message)
-		if s.messageWidth-pre.Len() >= 0 {
-			pre.WriteString(strings.Repeat(" ", s.messageWidth-pre.Len()))
+		fmt.Fprintf(&sb, "%s", message)
+		if s.messageWidth-sb.Len() >= 0 {
+			sb.WriteString(strings.Repeat(" ", s.messageWidth-sb.Len()))
 		}
 
-		pre.WriteString(" ")
+		sb.WriteString(" ")
 	}
 
-	var pad int
 	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]
-		pre.WriteString(spinner)
-		pad = len(spinner) - len([]rune(spinner))
-	}
-
-	var suf strings.Builder
-	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))
+		sb.WriteString(spinner)
+		sb.WriteString(" ")
 	}
 
-	return pre.String() + mid.String() + suf.String()
+	return sb.String()
 }
 
 func (s *Spinner) start() {
@@ -91,12 +71,3 @@ func (s *Spinner) Stop() {
 		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)
-}