diff options
| author | 2023-04-28 01:36:44 +0800 | |
|---|---|---|
| committer | 2023-04-28 01:36:44 +0800 | |
| commit | dd84b9d64fb98746a230cd24233ff50a562c39c9 (patch) | |
| tree | b583261ef00b3afe72ec4d6dacb31e57779a6faf /cli/internal/spinner/spinner.go | |
| parent | 0b46fcd72ac34382387b2bcf9095233efbcc52f4 (diff) | |
| download | HydroRoll-dd84b9d64fb98746a230cd24233ff50a562c39c9.tar.gz HydroRoll-dd84b9d64fb98746a230cd24233ff50a562c39c9.zip | |
Diffstat (limited to 'cli/internal/spinner/spinner.go')
| -rw-r--r-- | cli/internal/spinner/spinner.go | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/cli/internal/spinner/spinner.go b/cli/internal/spinner/spinner.go new file mode 100644 index 0000000..8ce6b4a --- /dev/null +++ b/cli/internal/spinner/spinner.go @@ -0,0 +1,89 @@ +package spinner + +import ( + "context" + "fmt" + "io" + "time" + + "github.com/mitchellh/cli" + progressbar "github.com/schollz/progressbar/v3" + "github.com/vercel/turbo/cli/internal/ui" +) + +// getWriterAndColor unwraps cli.Ui instances until it gets to a BasicUi. +// If it happens to spot a ColoredUi along the way, it marks that color is +// enabled. +func getWriterAndColor(terminal cli.Ui, useColor bool) (io.Writer, bool) { + switch terminal := terminal.(type) { + case *cli.BasicUi: + return terminal.Writer, useColor + case *cli.ColoredUi: + return getWriterAndColor(terminal.Ui, true) + case *cli.ConcurrentUi: + return getWriterAndColor(terminal.Ui, useColor) + case *cli.PrefixedUi: + return getWriterAndColor(terminal.Ui, useColor) + case *cli.MockUi: + return terminal.OutputWriter, false + default: + panic(fmt.Sprintf("unknown Ui: %v", terminal)) + } +} + +// WaitFor runs fn, and prints msg to the terminal if it takes longer +// than initialDelay to complete. Depending on the terminal configuration, it may +// display a single instance of msg, or an infinite spinner, updated every 250ms. +func WaitFor(ctx context.Context, fn func(), terminal cli.Ui, msg string, initialDelay time.Duration) error { + doneCh := make(chan struct{}) + go func() { + fn() + close(doneCh) + }() + if ui.IsTTY { + select { + case <-ctx.Done(): + return nil + case <-time.After(initialDelay): + writer, useColor := getWriterAndColor(terminal, false) + bar := progressbar.NewOptions( + -1, + progressbar.OptionEnableColorCodes(useColor), + progressbar.OptionSetDescription(fmt.Sprintf("[yellow]%v[reset]", msg)), + progressbar.OptionSpinnerType(14), + progressbar.OptionSetWriter(writer), + ) + for { + select { + case <-doneCh: + err := bar.Finish() + terminal.Output("") + return err + case <-time.After(250 * time.Millisecond): + if err := bar.Add(1); err != nil { + return err + } + case <-ctx.Done(): + return nil + } + } + case <-doneCh: + return nil + } + } else { + // wait for the timeout before displaying a message, even with no tty + select { + case <-ctx.Done(): + return nil + case <-doneCh: + return nil + case <-time.After(initialDelay): + terminal.Output(msg) + } + select { + case <-ctx.Done(): + case <-doneCh: + } + return nil + } +} |
