mirror of
https://github.com/charmbracelet/gum
synced 2024-06-17 04:55:05 +02:00
* feat(spin): Add support for `--show-error` for the spinner. This makes it so that if the `--show-error` flag is provided then the full output of the command will be printed if the command fails. This kind of works in conjuncture with `--show-output` in that if the command succeeds only STDOUT is pushed. If the command fails both `STDOUT` and `STDERR` are pushed. This builds off of https://github.com/charmbracelet/gum/pull/371 Resolves #55 * chore: Fix formatting --------- Co-authored-by: Elliot Courant <me@elliotcourant.dev>
This commit is contained in:
parent
2f2fa3bf00
commit
f4d198396f
|
@ -44,6 +44,9 @@ func (o Options) Run() error {
|
||||||
return fmt.Errorf("failed to access stdout: %w", err)
|
return fmt.Errorf("failed to access stdout: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the command succeeds, and we are printing output and we are in a TTY then push the STDOUT we got to the actual
|
||||||
|
// STDOUT for piping or other things.
|
||||||
|
if m.status == 0 {
|
||||||
if o.ShowOutput {
|
if o.ShowOutput {
|
||||||
// BubbleTea writes the View() to stderr.
|
// BubbleTea writes the View() to stderr.
|
||||||
// If the program is being piped then put the accumulated output in stdout.
|
// If the program is being piped then put the accumulated output in stdout.
|
||||||
|
@ -54,6 +57,14 @@ func (o Options) Run() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if o.ShowError {
|
||||||
|
// Otherwise if we are showing errors and the command did not exit with a 0 status code then push all of the command
|
||||||
|
// output to the terminal. This way failed commands can be debugged.
|
||||||
|
_, err := os.Stdout.WriteString(m.output)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to write to stdout: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
os.Exit(m.status)
|
os.Exit(m.status)
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -11,6 +11,7 @@ type Options struct {
|
||||||
Command []string `arg:"" help:"Command to run"`
|
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"`
|
ShowOutput bool `help:"Show or pipe output of command during execution" default:"false" env:"GUM_SPIN_SHOW_OUTPUT"`
|
||||||
|
ShowError bool `help:"Show output of command only if the command fails" default:"false" env:"GUM_SPIN_SHOW_ERROR"`
|
||||||
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"`
|
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_"`
|
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"`
|
Title string `help:"Text to display to user while spinning" default:"Loading..." env:"GUM_SPIN_TITLE"`
|
||||||
|
|
18
spin/spin.go
18
spin/spin.go
|
@ -15,6 +15,7 @@
|
||||||
package spin
|
package spin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -37,16 +38,22 @@ type model struct {
|
||||||
aborted bool
|
aborted bool
|
||||||
status int
|
status int
|
||||||
stdout string
|
stdout string
|
||||||
|
stderr string
|
||||||
|
output string
|
||||||
showOutput bool
|
showOutput bool
|
||||||
|
showError bool
|
||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
hasTimeout bool
|
hasTimeout bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var bothbuf strings.Builder
|
||||||
var outbuf strings.Builder
|
var outbuf strings.Builder
|
||||||
var errbuf strings.Builder
|
var errbuf strings.Builder
|
||||||
|
|
||||||
type finishCommandMsg struct {
|
type finishCommandMsg struct {
|
||||||
stdout string
|
stdout string
|
||||||
|
stderr string
|
||||||
|
output string
|
||||||
status int
|
status int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,8 +66,11 @@ func commandStart(command []string) tea.Cmd {
|
||||||
cmd := exec.Command(command[0], args...) //nolint:gosec
|
cmd := exec.Command(command[0], args...) //nolint:gosec
|
||||||
|
|
||||||
if isatty.IsTerminal(os.Stdout.Fd()) {
|
if isatty.IsTerminal(os.Stdout.Fd()) {
|
||||||
cmd.Stdout = &outbuf
|
stdout := io.MultiWriter(&bothbuf, &errbuf)
|
||||||
cmd.Stderr = &errbuf
|
stderr := io.MultiWriter(&bothbuf, &outbuf)
|
||||||
|
|
||||||
|
cmd.Stdout = stdout
|
||||||
|
cmd.Stderr = stderr
|
||||||
} else {
|
} else {
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
}
|
}
|
||||||
|
@ -75,6 +85,8 @@ func commandStart(command []string) tea.Cmd {
|
||||||
|
|
||||||
return finishCommandMsg{
|
return finishCommandMsg{
|
||||||
stdout: outbuf.String(),
|
stdout: outbuf.String(),
|
||||||
|
stderr: errbuf.String(),
|
||||||
|
output: bothbuf.String(),
|
||||||
status: status,
|
status: status,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,6 +135,8 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
return m, timeout.Tick(msg.TimeoutValue, msg.Data)
|
return m, timeout.Tick(msg.TimeoutValue, msg.Data)
|
||||||
case finishCommandMsg:
|
case finishCommandMsg:
|
||||||
m.stdout = msg.stdout
|
m.stdout = msg.stdout
|
||||||
|
m.stderr = msg.stderr
|
||||||
|
m.output = msg.output
|
||||||
m.status = msg.status
|
m.status = msg.status
|
||||||
m.quitting = true
|
m.quitting = true
|
||||||
return m, tea.Quit
|
return m, tea.Quit
|
||||||
|
|
Loading…
Reference in a new issue