Skip to content

Commit

Permalink
Allow to change the message for the spinner (#1973)
Browse files Browse the repository at this point in the history
  • Loading branch information
cardil authored Oct 28, 2024
1 parent b3b6b86 commit 117a365
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 6 deletions.
1 change: 1 addition & 0 deletions pkg/output/tui/progress_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
)

func TestProgress(t *testing.T) {
t.Parallel()
ctx := context.TestContext(t)
prt := output.NewTestPrinter()
ctx = output.WithContext(ctx, prt)
Expand Down
35 changes: 32 additions & 3 deletions pkg/output/tui/spinner.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import (
const spinnerColor = lipgloss.Color("205")

type Spinner interface {
Runnable[Spinner]
Runnable[SpinnerControl]
}

func (w *widgets) NewSpinner(message string) Spinner {
Expand All @@ -44,17 +44,27 @@ type BubbleSpinner struct {
output.InputOutput
Message

*updater
spin spinner.Model
tea *tea.Program
quitChan chan struct{}
teaErr error
}

func (b *BubbleSpinner) With(fn func(Spinner) error) error {
// SpinnerControl allows one to control the spinner, for example, to change the
// message.
type SpinnerControl interface {
UpdateMessage(message string)
}

// With will start the spinner and perform long operation within the
// provided fn. The spinner will be automatically shutdown when the provided
// function exits.
func (b *BubbleSpinner) With(fn func(SpinnerControl) error) error {
b.start()
err := func() error {
defer b.stop()
return fn(b)
return fn(b.updater)
}()
return multierr.Combine(err, b.teaErr)
}
Expand All @@ -70,10 +80,20 @@ func (b *BubbleSpinner) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}

func (b *BubbleSpinner) View() string {
select {
case m := <-b.updater.messages:
// nil on channel close
if m != nil {
b.Message.Text = *m
}
default:
// nothing
}
return fmt.Sprintf("%s %s", b.Message.Text, b.spin.View())
}

func (b *BubbleSpinner) start() {
b.updater = &updater{make(chan *string)}
b.spin = spinner.New(
spinner.WithSpinner(spinner.Meter),
spinner.WithStyle(spinnerStyle()),
Expand All @@ -94,6 +114,7 @@ func (b *BubbleSpinner) stop() {
return
}

close(b.updater.messages)
b.tea.Quit()
<-b.quitChan

Expand All @@ -111,3 +132,11 @@ func (b *BubbleSpinner) stop() {
func spinnerStyle() lipgloss.Style {
return lipgloss.NewStyle().Foreground(spinnerColor)
}

type updater struct {
messages chan *string
}

func (u updater) UpdateMessage(message string) {
u.messages <- &message
}
14 changes: 11 additions & 3 deletions pkg/output/tui/spinner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
)

func TestSpinner(t *testing.T) {
t.Parallel()
ctx := context.TestContext(t)
prt := output.NewTestPrinter()
ctx = output.WithContext(ctx, prt)
Expand All @@ -35,14 +36,21 @@ func TestSpinner(t *testing.T) {
if s == nil {
t.Errorf("want spinner, got nil")
}
if err := s.With(func(spinner tui.Spinner) error {
time.Sleep(20 * time.Millisecond)
if err := s.With(func(sc tui.SpinnerControl) error {
time.Sleep(3 * time.Millisecond)
sc.UpdateMessage("msg-1")
time.Sleep(3 * time.Millisecond)
sc.UpdateMessage("msg-2")
time.Sleep(3 * time.Millisecond)
return nil
}); err != nil {
t.Errorf("want nil, got %v", err)
}
got := prt.Outputs().Out.String()
want := "\x1b[?25lmessage ▰▱▱\x1b[0D\x1b[2K\x1b[?25h\x1b[?1002l\x1b[?1003l\x1b[?1006lmessage Done\n"
want := "\x1b[?25lmessage ▰▱▱\x1b[0D" +
"\x1b[0D\x1b[2Kmsg-1 ▰▰▱\x1b[0D" +
"\x1b[0D\x1b[2Kmsg-2 ▰▰▰\x1b[0D" +
"\x1b[2K\x1b[?25h\x1b[?1002l\x1b[?1003l\x1b[?1006lmsg-2 Done\n"
if got != want {
t.Errorf("text missmatch\nwant %q,\n got %q", want, got)
}
Expand Down
2 changes: 2 additions & 0 deletions pkg/output/tui/widgets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
)

func TestNewWidgets(t *testing.T) {
t.Parallel()
ctx := context.TestContext(t)
w := tui.NewWidgets(ctx)

Expand All @@ -33,6 +34,7 @@ func TestNewWidgets(t *testing.T) {
}

func TestNewInteractiveWidgets(t *testing.T) {
t.Parallel()
ctx := context.TestContext(t)
w, err := tui.NewInteractiveWidgets(ctx)

Expand Down

0 comments on commit 117a365

Please sign in to comment.