Allow to change the message for the spinner (#1973)

This commit is contained in:
Chris Suszynski 2024-10-28 12:12:48 +01:00 committed by GitHub
parent b3b6b86030
commit 117a365d93
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 46 additions and 6 deletions

View File

@ -33,6 +33,7 @@ import (
)
func TestProgress(t *testing.T) {
t.Parallel()
ctx := context.TestContext(t)
prt := output.NewTestPrinter()
ctx = output.WithContext(ctx, prt)

View File

@ -30,7 +30,7 @@ import (
const spinnerColor = lipgloss.Color("205")
type Spinner interface {
Runnable[Spinner]
Runnable[SpinnerControl]
}
func (w *widgets) NewSpinner(message string) Spinner {
@ -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)
}
@ -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()),
@ -94,6 +114,7 @@ func (b *BubbleSpinner) stop() {
return
}
close(b.updater.messages)
b.tea.Quit()
<-b.quitChan
@ -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
}

View File

@ -26,6 +26,7 @@ import (
)
func TestSpinner(t *testing.T) {
t.Parallel()
ctx := context.TestContext(t)
prt := output.NewTestPrinter()
ctx = output.WithContext(ctx, prt)
@ -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)
}

View File

@ -24,6 +24,7 @@ import (
)
func TestNewWidgets(t *testing.T) {
t.Parallel()
ctx := context.TestContext(t)
w := tui.NewWidgets(ctx)
@ -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)