Skip to content

Commit

Permalink
Merge pull request #53 from theckman/example_files
Browse files Browse the repository at this point in the history
Add simple and advanced example files
  • Loading branch information
theckman committed Dec 28, 2021
2 parents 1916b71 + 4bdf066 commit 324fd5b
Show file tree
Hide file tree
Showing 3 changed files with 263 additions and 2 deletions.
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,12 @@ Within the `yacspin` package there are some default spinners stored in the
`yacspin.CharSets` variable, and you can also provide your own. There is also a
list of known colors in the `yacspin.ValidColors` variable.

### Example

There are runnable examples in the [examples/](https://github.com/theckman/yacspin/tree/master/examples)
directory, with one simple example and one more advanced one. Here is a quick
snippet showing usage from a very high level, with error handling omitted:

```Go
cfg := yacspin.Config{
Frequency: 100 * time.Millisecond,
Expand All @@ -146,7 +152,7 @@ cfg := yacspin.Config{
spinner, err := yacspin.New(cfg)
// handle the error

spinner.Start()
err = spinner.Start()

// doing some work
time.Sleep(2 * time.Second)
Expand All @@ -156,7 +162,7 @@ spinner.Message("uploading data")
// upload...
time.Sleep(2 * time.Second)

spinner.Stop()
err = spinner.Stop()
```

## Spinners
Expand Down
157 changes: 157 additions & 0 deletions examples/advanced/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
package main

import (
"fmt"
"os"
"os/signal"
"syscall"
"time"

"github.com/theckman/yacspin"
)

func main() {
// createSpinnerFromStruct()
useSpinner(createSpinnerFromStruct(), true) // failure message
useSpinner(createSpinnerFromStruct(), false) // success message

// createSpinnerFromMethods()
useSpinner(createSpinnerFromMethods(), true) // failure message
useSpinner(createSpinnerFromMethods(), false) // success message
}

// createSpinnerFromStruct shows configuring the spinner mostly from the Config
// struct.
func createSpinnerFromStruct() *yacspin.Spinner {
cfg := yacspin.Config{
Frequency: 100 * time.Millisecond,
Colors: []string{"fgYellow"},
CharSet: yacspin.CharSets[11],
Suffix: " ",
SuffixAutoColon: true,
Message: "only spinner is colored",
StopCharacter: "✓",
StopColors: []string{"fgGreen"},
StopMessage: "done",
StopFailCharacter: "✗",
StopFailColors: []string{"fgRed"},
StopFailMessage: "failed",
}

s, err := yacspin.New(cfg)
if err != nil {
exitf("failed to make spinner from struct: %v", err)
}

return s
}

// createSpinnerFromMethods shows configuring the spinner mostly from its
// methods.
func createSpinnerFromMethods() *yacspin.Spinner {
cfg := yacspin.Config{
Frequency: 100 * time.Millisecond,
ColorAll: true,
SuffixAutoColon: true,
Message: "spinner and text is colored",
}

s, err := yacspin.New(cfg)
if err != nil {
exitf("failed to generate spinner from methods: %v", err)
}

if err := s.CharSet(yacspin.CharSets[11]); err != nil {
exitf("failed to set charset: %v", err)
}

if err := s.Colors("fgYellow"); err != nil {
exitf("failed to set color: %v", err)
}

if err := s.StopColors("fgGreen"); err != nil {
exitf("failed to set stop colors: %v", err)
}

if err := s.StopFailColors("fgRed"); err != nil {
exitf("failed to set stop fail colors: %v", err)
}

s.Suffix(" ")
s.StopCharacter("✓")
s.StopMessage("done")
s.StopFailCharacter("✗")
s.StopFailMessage("failed")

return s
}

// useSpinner utilizes the differently configured spinners, if shouldFail is
// true it uses the .StopFail method instead of .Stop.
func useSpinner(spinner *yacspin.Spinner, shouldFail bool) {
// handle spinner cleanup on interrupts
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)

defer signal.Stop(sigCh)

go func() { // this is just an example signal handler, should be more robust
<-sigCh

spinner.StopFailMessage("interrupted")

// ignoring error intentionally
_ = spinner.StopFail()

os.Exit(0)
}()

// start animating the spinner
if err := spinner.Start(); err != nil {
exitf("failed to start spinner: %v", err)
}

// let spinner animation render for a bit
time.Sleep(2 * time.Second)

// pause spinner to do an "atomic" config update
if err := spinner.Pause(); err != nil {
exitf("failed to pause spinner: %v", err)
}

spinner.Suffix(" uploading files")
spinner.Message("")

// start to animate the spinner again
if err := spinner.Unpause(); err != nil {
exitf("failed to unpause spinner: %v", err)
}

// let spinner animation render for a bit
time.Sleep(time.Second)

// simulate uploading a series of different files
for _, f := range []string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j"} {
spinner.Message(fmt.Sprintf("%s.zip", f))

time.Sleep(150 * time.Millisecond)
}

// let spinner animation render for a bit
time.Sleep(1500 * time.Millisecond)

if shouldFail {
if err := spinner.StopFail(); err != nil {
exitf("failed to stopfail: %v", err)
}
} else {
if err := spinner.Stop(); err != nil {
exitf("failed to stop: %v", err)
}
}
}

func exitf(format string, a ...interface{}) {
fmt.Printf(format, a...)
os.Exit(1)
}
98 changes: 98 additions & 0 deletions examples/simple/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package main

import (
"fmt"
"os"
"os/signal"
"syscall"
"time"

"github.com/theckman/yacspin"
)

func main() {
spinner, err := createSpinner()
if err != nil {
fmt.Printf("failed to make spinner from config struct: %v\n", err)
os.Exit(1)
}

stopOnSignal(spinner)

err = renderSpinner(spinner)
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
}

func createSpinner() (*yacspin.Spinner, error) {
// build the configuration, each field is documented
cfg := yacspin.Config{
Frequency: 100 * time.Millisecond,
CharSet: yacspin.CharSets[11],
Suffix: " ", // puts a least one space between the animating spinner and the Message
Message: "collecting files",
SuffixAutoColon: true,
ColorAll: true,
Colors: []string{"fgYellow"},
StopCharacter: "✓",
StopColors: []string{"fgGreen"},
StopMessage: "done",
StopFailCharacter: "✗",
StopFailColors: []string{"fgRed"},
StopFailMessage: "failed",
}

s, err := yacspin.New(cfg)
if err != nil {
return nil, fmt.Errorf("failed to make spinner from struct: %w", err)
}

return s, nil
}

func stopOnSignal(spinner *yacspin.Spinner) {
// ensure we stop the spinner before exiting, otherwise cursor will remain
// hidden and terminal will require a `reset`
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
go func() {
<-sigCh

spinner.StopFailMessage("interrupted")

// ignoring error intentionally
_ = spinner.StopFail()

os.Exit(0)
}()
}

func renderSpinner(spinner *yacspin.Spinner) error {
// start the spinner animation
if err := spinner.Start(); err != nil {
return fmt.Errorf("failed to start spinner: %w", err)
}

// let spinner render
time.Sleep(5 * time.Second)

// update message
spinner.Message("uploading files")

// let spinner render some more
time.Sleep(5 * time.Second)

// if you wanted to print a failure message...
//
// if err := spinner.StopFail(); err != nil {
// return fmt.Errorf("failed to stop spinner: %w", err)
// }

if err := spinner.Stop(); err != nil {
return fmt.Errorf("failed to stop spinner: %w", err)
}

return nil
}

0 comments on commit 324fd5b

Please sign in to comment.