github.com/Racer159/jackal@v0.32.7-0.20240401174413-0bd2339e4f2e/src/pkg/message/progress.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // SPDX-FileCopyrightText: 2021-Present The Jackal Authors
     3  
     4  // Package message provides a rich set of functions for displaying messages to the user.
     5  package message
     6  
     7  import (
     8  	"os"
     9  
    10  	"github.com/pterm/pterm"
    11  )
    12  
    13  const padding = "    "
    14  
    15  // ProgressBar is a struct used to drive a pterm ProgressbarPrinter.
    16  type ProgressBar struct {
    17  	progress  *pterm.ProgressbarPrinter
    18  	startText string
    19  }
    20  
    21  // NewProgressBar creates a new ProgressBar instance from a total value and a format.
    22  func NewProgressBar(total int64, text string) *ProgressBar {
    23  	var progress *pterm.ProgressbarPrinter
    24  	if NoProgress {
    25  		Info(text)
    26  	} else {
    27  		progress, _ = pterm.DefaultProgressbar.
    28  			WithTotal(int(total)).
    29  			WithShowCount(false).
    30  			WithTitle(padding + text).
    31  			WithRemoveWhenDone(true).
    32  			WithMaxWidth(TermWidth).
    33  			WithWriter(os.Stderr).
    34  			Start()
    35  	}
    36  
    37  	return &ProgressBar{
    38  		progress:  progress,
    39  		startText: text,
    40  	}
    41  }
    42  
    43  // Update updates the ProgressBar with completed progress and new text.
    44  func (p *ProgressBar) Update(complete int64, text string) {
    45  	if NoProgress {
    46  		debugPrinter(2, text)
    47  		return
    48  	}
    49  	p.progress.UpdateTitle(padding + text)
    50  	chunk := int(complete) - p.progress.Current
    51  	p.Add(chunk)
    52  }
    53  
    54  // UpdateTitle updates the ProgressBar with new text.
    55  func (p *ProgressBar) UpdateTitle(text string) {
    56  	if NoProgress {
    57  		debugPrinter(2, text)
    58  		return
    59  	}
    60  	p.progress.UpdateTitle(padding + text)
    61  }
    62  
    63  // Add updates the ProgressBar with completed progress.
    64  func (p *ProgressBar) Add(n int) {
    65  	if p.progress != nil {
    66  		if p.progress.Current+n >= p.progress.Total {
    67  			// @RAZZLE TODO: This is a hack to prevent the progress bar from going over 100% and causing TUI ugliness.
    68  			overflow := p.progress.Current + n - p.progress.Total
    69  			p.progress.Total += overflow + 1
    70  		}
    71  		p.progress.Add(n)
    72  	}
    73  }
    74  
    75  // Write updates the ProgressBar with the number of bytes in a buffer as the completed progress.
    76  func (p *ProgressBar) Write(data []byte) (int, error) {
    77  	n := len(data)
    78  	if p.progress != nil {
    79  		p.Add(n)
    80  	}
    81  	return n, nil
    82  }
    83  
    84  // Successf marks the ProgressBar as successful in the CLI.
    85  func (p *ProgressBar) Successf(format string, a ...any) {
    86  	p.Stop()
    87  	pterm.Success.Printfln(format, a...)
    88  }
    89  
    90  // Stop stops the ProgressBar from continuing.
    91  func (p *ProgressBar) Stop() {
    92  	if p.progress != nil {
    93  		_, _ = p.progress.Stop()
    94  	}
    95  }
    96  
    97  // Errorf marks the ProgressBar as failed in the CLI.
    98  func (p *ProgressBar) Errorf(err error, format string, a ...any) {
    99  	p.Stop()
   100  	WarnErrf(err, format, a...)
   101  }
   102  
   103  // GetCurrent returns the current total
   104  func (p *ProgressBar) GetCurrent() int {
   105  	if p.progress != nil {
   106  		return p.progress.Current
   107  	}
   108  	return -1
   109  }