func (r *Run) Run(ctx *cli.Context) error {
	return r.RunWithOptions(optionsFrom(ctx))
}
Run executes the run in the provided CLI context.
package demo
import (
	"bufio"
	"fmt"
	"io"
	"math/rand"
	"os"
	"os/exec"
	"strings"
	"time"
	"github.com/gookit/color"
	"github.com/pkg/errors"
	"github.com/urfave/cli/v2"
)
const bash = "bash"
type Run struct {
	title       string
	description []string
	steps       []step
	out         io.Writer
	options     *Options
	setup       func() error
	cleanup     func() error
}
type step struct {
	r             *Run
	text, command []string
	canFail       bool
}
type Options struct {
	AutoTimeout      time.Duration
	Auto             bool
	HideDescriptions bool
	Immediate        bool
	SkipSteps        int
}
func emptyFn() error { return nil }
func NewRun(title string, description ...string) *Run {
	return &Run{
		title:       title,
		description: description,
		steps:       nil,
		out:         os.Stdout,
		options:     nil,
		setup:       emptyFn,
		cleanup:     emptyFn,
	}
}
func optionsFrom(ctx *cli.Context) Options {
	return Options{
		AutoTimeout:      ctx.Duration(FlagAutoTimeout),
		Auto:             ctx.Bool(FlagAuto),
		HideDescriptions: ctx.Bool(FlagHideDescriptions),
		Immediate:        ctx.Bool(FlagImmediate),
		SkipSteps:        ctx.Int(FlagSkipSteps),
	}
}
func S(s ...string) []string {
	return s
}
func (r *Run) SetOutput(output io.Writer) error {
	if output == nil {
		return errors.New("provided output is nil")
	}
	r.out = output
	return nil
}
func (r *Run) Setup(setupFn func() error) {
	r.setup = setupFn
}
func (r *Run) Cleanup(cleanupFn func() error) {
	r.cleanup = cleanupFn
}
func (r *Run) Step(text, command []string) {
	r.steps = append(r.steps, step{r, text, command, false})
}
func (r *Run) StepCanFail(text, command []string) {
	r.steps = append(r.steps, step{r, text, command, true})
}