feat: Timeout for Spin Command (#385)

* feat: Timeout for Spin Command

* fix: spin timeout

---------

Co-authored-by: Maas Lalani <maas@lalani.dev>
This commit is contained in:
Dieter Eickstaedt 2023-06-30 15:17:09 +02:00 committed by GitHub
parent 0c1cc8e669
commit f8caeef195
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 10 deletions

View file

@ -26,7 +26,8 @@ func (o Options) Run() error {
title: o.TitleStyle.ToLipgloss().Render(o.Title),
command: o.Command,
align: o.Align,
showOutput: o.ShowOutput && isTTY,
timeout: o.Timeout,
hasTimeout: o.Timeout > 0,
}
p := tea.NewProgram(m, tea.WithOutput(os.Stderr))
mm, err := p.Run()

View file

@ -1,15 +1,20 @@
package spin
import "github.com/charmbracelet/gum/style"
import (
"time"
"github.com/charmbracelet/gum/style"
)
// Options is the customization options for the spin command.
type Options struct {
Command []string `arg:"" help:"Command to run"`
ShowOutput bool `help:"Show or pipe output of command during execution" default:"false" env:"GUM_SPIN_SHOW_OUTPUT"`
Spinner string `help:"Spinner type" short:"s" type:"spinner" enum:"line,dot,minidot,jump,pulse,points,globe,moon,monkey,meter,hamburger" default:"dot" env:"GUM_SPIN_SPINNER"`
SpinnerStyle style.Styles `embed:"" prefix:"spinner." set:"defaultForeground=212" envprefix:"GUM_SPIN_SPINNER_"`
Title string `help:"Text to display to user while spinning" default:"Loading..." env:"GUM_SPIN_TITLE"`
TitleStyle style.Styles `embed:"" prefix:"title." envprefix:"GUM_SPIN_TITLE_"`
Align string `help:"Alignment of spinner with regard to the title" short:"a" type:"align" enum:"left,right" default:"left" env:"GUM_SPIN_ALIGN"`
ShowOutput bool `help:"Show or pipe output of command during execution" default:"false" env:"GUM_SPIN_SHOW_OUTPUT"`
Spinner string `help:"Spinner type" short:"s" type:"spinner" enum:"line,dot,minidot,jump,pulse,points,globe,moon,monkey,meter,hamburger" default:"dot" env:"GUM_SPIN_SPINNER"`
SpinnerStyle style.Styles `embed:"" prefix:"spinner." set:"defaultForeground=212" envprefix:"GUM_SPIN_SPINNER_"`
Title string `help:"Text to display to user while spinning" default:"Loading..." env:"GUM_SPIN_TITLE"`
TitleStyle style.Styles `embed:"" prefix:"title." envprefix:"GUM_SPIN_TITLE_"`
Align string `help:"Alignment of spinner with regard to the title" short:"a" type:"align" enum:"left,right" default:"left" env:"GUM_SPIN_ALIGN"`
Timeout time.Duration `help:"Timeout until spin command aborts" default:"0" env:"GUM_SPIN_TIMEOUT"`
}

View file

@ -17,6 +17,10 @@ package spin
import (
"os/exec"
"strings"
"time"
"github.com/charmbracelet/gum/internal/exit"
"github.com/charmbracelet/gum/timeout"
"github.com/charmbracelet/bubbles/spinner"
tea "github.com/charmbracelet/bubbletea"
@ -31,6 +35,8 @@ type model struct {
status int
stdout string
showOutput bool
timeout time.Duration
hasTimeout bool
}
var outbuf strings.Builder
@ -71,14 +77,19 @@ func (m model) Init() tea.Cmd {
return tea.Batch(
m.spinner.Tick,
commandStart(m.command),
timeout.Init(m.timeout, nil),
)
}
func (m model) View() string {
var str string
if m.hasTimeout {
str = timeout.Str(m.timeout)
}
var header string
if m.align == "left" {
header = m.spinner.View() + " " + m.title
header = m.spinner.View() + str + " " + m.title
} else {
header = m.title + " " + m.spinner.View()
header = str + " " + m.title + " " + m.spinner.View()
}
if !m.showOutput {
return header
@ -89,6 +100,13 @@ func (m model) View() string {
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var cmd tea.Cmd
switch msg := msg.(type) {
case timeout.TickTimeoutMsg:
if msg.TimeoutValue <= 0 {
m.status = exit.StatusAborted
return m, tea.Quit
}
m.timeout = msg.TimeoutValue
return m, timeout.Tick(msg.TimeoutValue, msg.Data)
case finishCommandMsg:
m.stdout = msg.stdout
m.status = msg.status