mirror of
https://github.com/charmbracelet/gum
synced 2024-06-10 09:42:16 +02:00
feat: Add gum spin
command
Spin provides a shell script interface for the spinner bubble. It is useful for displaying that some task is running in the background while consuming it's output so that it is not shown to the user. For example, let's do a long running task: ``` sleep 5 ``` We can simply prepend a spinner to this task to show it to the user, while performing the task / command in the background. ``` gum spin -t "Taking a nap..." -- sleep 5 ``` The spinner will automatically exit when the task is complete.
This commit is contained in:
parent
c906d1904d
commit
454040cf4d
22
spin/command.go
Normal file
22
spin/command.go
Normal file
|
@ -0,0 +1,22 @@
|
|||
package spin
|
||||
|
||||
import (
|
||||
"github.com/charmbracelet/bubbles/spinner"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
)
|
||||
|
||||
// Run provides a shell script interface for the spinner bubble.
|
||||
// https://github.com/charmbracelet/bubbles/spinner
|
||||
func (o Options) Run() {
|
||||
s := spinner.New()
|
||||
s.Style = lipgloss.NewStyle().Foreground(lipgloss.Color(o.Color))
|
||||
s.Spinner = spinnerMap[o.Spinner]
|
||||
m := model{
|
||||
spinner: s,
|
||||
title: o.Title,
|
||||
command: o.Command,
|
||||
}
|
||||
p := tea.NewProgram(m)
|
||||
_ = p.Start()
|
||||
}
|
10
spin/options.go
Normal file
10
spin/options.go
Normal file
|
@ -0,0 +1,10 @@
|
|||
package spin
|
||||
|
||||
// Options is the customization options for the spin command.
|
||||
type Options struct {
|
||||
Command []string `arg:"" help:"Command to run"`
|
||||
|
||||
Color string `help:"Spinner color" default:"#FF06B7"`
|
||||
Title string `help:"Text to display to user while spinning" default:"Loading..."`
|
||||
Spinner string `help:"Spinner type" type:"spinner" enum:"line,dot,minidot,jump,pulse,points,globe,moon,monkey,meter,hamburger" default:"dot"`
|
||||
}
|
51
spin/spin.go
Normal file
51
spin/spin.go
Normal file
|
@ -0,0 +1,51 @@
|
|||
package spin
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
|
||||
"github.com/charmbracelet/bubbles/spinner"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
)
|
||||
|
||||
type model struct {
|
||||
spinner spinner.Model
|
||||
title string
|
||||
command []string
|
||||
}
|
||||
|
||||
type finishCommandMsg struct{ output string }
|
||||
|
||||
func commandStart(command []string) tea.Cmd {
|
||||
return func() tea.Msg {
|
||||
var args []string
|
||||
if len(command) > 1 {
|
||||
args = command[1:]
|
||||
}
|
||||
out, _ := exec.Command(command[0], args...).Output()
|
||||
return finishCommandMsg{output: string(out)}
|
||||
}
|
||||
}
|
||||
|
||||
func (m model) Init() tea.Cmd {
|
||||
return tea.Batch(
|
||||
m.spinner.Tick,
|
||||
commandStart(m.command),
|
||||
)
|
||||
}
|
||||
func (m model) View() string { return m.spinner.View() + " " + m.title }
|
||||
|
||||
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
var cmd tea.Cmd
|
||||
switch msg := msg.(type) {
|
||||
case finishCommandMsg:
|
||||
return m, tea.Quit
|
||||
case tea.KeyMsg:
|
||||
switch msg.String() {
|
||||
case "ctrl+c":
|
||||
return m, tea.Quit
|
||||
}
|
||||
}
|
||||
|
||||
m.spinner, cmd = m.spinner.Update(msg)
|
||||
return m, cmd
|
||||
}
|
17
spin/spinners.go
Normal file
17
spin/spinners.go
Normal file
|
@ -0,0 +1,17 @@
|
|||
package spin
|
||||
|
||||
import "github.com/charmbracelet/bubbles/spinner"
|
||||
|
||||
var spinnerMap = map[string]spinner.Spinner{
|
||||
"line": spinner.Line,
|
||||
"dot": spinner.Dot,
|
||||
"minidot": spinner.MiniDot,
|
||||
"jump": spinner.Jump,
|
||||
"pulse": spinner.Pulse,
|
||||
"points": spinner.Points,
|
||||
"globe": spinner.Globe,
|
||||
"moon": spinner.Moon,
|
||||
"monkey": spinner.Monkey,
|
||||
"meter": spinner.Meter,
|
||||
"hamburger": spinner.Hamburger,
|
||||
}
|
Loading…
Reference in a new issue