Initial QSfera import
This commit is contained in:
+274
@@ -0,0 +1,274 @@
|
||||
# Yet Another CLi Spinner (for Go)
|
||||
[](https://github.com/theckman/yacspin/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/theckman/yacspin)
|
||||
[](https://github.com/theckman/yacspin/releases)
|
||||
[](https://github.com/theckman/yacspin/actions/workflows/tests.yaml)
|
||||
[](https://goreportcard.com/report/github.com/theckman/yacspin)
|
||||
[](https://codecov.io/gh/theckman/yacspin)
|
||||
|
||||
Package `yacspin` provides yet another CLi spinner for Go, taking inspiration
|
||||
(and some utility code) from the https://github.com/briandowns/spinner project.
|
||||
Specifically `yacspin` borrows the default character sets, and color mappings to
|
||||
github.com/fatih/color colors, from that project.
|
||||
|
||||
## License
|
||||
Because this package adopts the spinner character sets from https://github.com/briandowns/spinner,
|
||||
this package is released under the Apache 2.0 License.
|
||||
|
||||
## Yet Another CLi Spinner?
|
||||
This project was created after it was realized that the most popular spinner
|
||||
library for Go had some limitations, that couldn't be fixed without a massive
|
||||
overhaul of the API.
|
||||
|
||||
The other spinner ties the ability to show updated messages to the spinner's
|
||||
animation, meaning you can't always show all the information you want to the end
|
||||
user without changing the animation speed. This means you need to trade off
|
||||
animation aesthetics to show "realtime" information. It was a goal to avoid this
|
||||
problem.
|
||||
|
||||
In addition, there were also some API design choices that have made it unsafe
|
||||
for concurrent use, which presents challenges when trying to update the text in
|
||||
the spinner while it's animating. This could result in undefined behavior due to
|
||||
data races.
|
||||
|
||||
There were also some variable-width spinners in that other project that did
|
||||
not render correctly. Because the width of the spinner animation would change,
|
||||
so would the position of the message on the screen. `yacspin` uses a dynamic
|
||||
width when animating, so your message should appear static relative to the
|
||||
animating spinner.
|
||||
|
||||
Finally, there was an interest in the spinner being able to represent a task, and to
|
||||
indicate whether it failed or was successful. This would have further compounded
|
||||
the API changes needed above to support in an intuitive way.
|
||||
|
||||
This project takes inspiration from that other project, and takes a new approach
|
||||
to address the challenges above.
|
||||
|
||||
## Features
|
||||
#### Provided Spinners
|
||||
There are over 90 spinners available in the `CharSets` package variable. They
|
||||
were borrowed from [github.com/briandowns/spinner](https://github.com/briandowns/spinner).
|
||||
There is a table with most of the spinners [at the bottom of this README](#Spinners).
|
||||
|
||||
#### Dynamic Width of Animation
|
||||
Because of how some spinners are animated, they may have different widths are
|
||||
different times in the animation. `yacspin` calculates the maximum width, and
|
||||
pads the animation to ensure the text's position on the screen doesn't change.
|
||||
This results in a smoother looking animation.
|
||||
|
||||
##### yacspin
|
||||

|
||||
|
||||
##### other spinners
|
||||

|
||||
|
||||
#### Success and Failure Results
|
||||
The spinner has both a `Stop()` and `StopFail()` method, which allows the
|
||||
spinner to result in a success message or a failure message. The messages,
|
||||
colors, and even the character used to denote success or failure are
|
||||
customizable in either the initial config or via the spinner's methods.
|
||||
|
||||
By doing this you can use a single `yacspin` spinner to display the status of a
|
||||
list of tasks being executed serially.
|
||||
|
||||
##### Stop
|
||||

|
||||
|
||||
##### StopFail
|
||||

|
||||
|
||||
#### Animation At End of Line
|
||||
The `SpinnerAtEnd` field of the `Config` struct allows you to specify whether
|
||||
the spinner is rendered at the end of the line instead of the beginning. The
|
||||
default value (`false`) results in the spinner being rendered at the beginning
|
||||
of the line.
|
||||
|
||||
#### Concurrency
|
||||
The spinner is safe for concurrent use, so you can update any of its settings
|
||||
via methods whether the spinner is stopped or is currently animating.
|
||||
|
||||
#### Live Updates
|
||||
Most spinners tie the ability to show new messages with the animation of the
|
||||
spinner. So if the spinner animates every 200ms, you can only show updated
|
||||
information every 200ms. If you wanted more frequent updates, you'd need to
|
||||
tradeoff the asthetics of the animation to display more data.
|
||||
|
||||
This spinner updates the printed information of the spinner immediately on
|
||||
change, without the animation updating. This allows you to use an animation
|
||||
speed that looks astheticaly pleasing, while also knowing the data presented to
|
||||
the user will be updated live.
|
||||
|
||||
You can see this in action in the following gif, where the filenames being
|
||||
uploaded are rendered independent of the spinner being animated:
|
||||
|
||||

|
||||
|
||||
#### Pausing for Updates
|
||||
Sometimes you want to change a few settings, and don't want the spinner to
|
||||
render your partially applied configuration. If your spinner is running, and you
|
||||
want to change a few configuration items via method calls, you can `Pause()` the
|
||||
spinner first. After making the changes you can call `Unpause()`, and it will
|
||||
continue rendering like normal with the newly applied configuration.
|
||||
|
||||
#### Supporting Non-Interactive (TTY) Output Targets
|
||||
`yacspin` also has native support for non-interactive (TTY) output targets. By
|
||||
default this is detected in the constructor, or can be overriden via the
|
||||
`TerminalMode` `Config` struct field. When detecting the application is not
|
||||
running withn a TTY session, the behavior of the spinner is different.
|
||||
|
||||
Specifically, when this is automatically detected the spinner no longer uses
|
||||
colors, disables the automatic spinner animation, and instead only animates the
|
||||
spinner when updating the message. In addition, each animation is rendered on a
|
||||
new line instead of overwriting the current line.
|
||||
|
||||
This should result in human-readable output without any changes needed by
|
||||
consumers, even when the system is writing to a non-TTY destination.
|
||||
|
||||
#### Manually Stepping Animation
|
||||
If you'd like to manually animate the spinner, you can do so by setting the
|
||||
`TerminalMode` to `ForceNoTTYMode | ForceSmartTerminalMode`. In this mode the
|
||||
spinner will still use colors and other text stylings, but the animation only
|
||||
happens when data is updated and on individual lines. You can accomplish this by
|
||||
calling the `Message()` method with the same used previously.
|
||||
|
||||
## Usage
|
||||
```
|
||||
go get github.com/theckman/yacspin
|
||||
```
|
||||
|
||||
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,
|
||||
CharSet: yacspin.CharSets[59],
|
||||
Suffix: " backing up database to S3",
|
||||
SuffixAutoColon: true,
|
||||
Message: "exporting data",
|
||||
StopCharacter: "✓",
|
||||
StopColors: []string{"fgGreen"},
|
||||
}
|
||||
|
||||
spinner, err := yacspin.New(cfg)
|
||||
// handle the error
|
||||
|
||||
err = spinner.Start()
|
||||
|
||||
// doing some work
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
spinner.Message("uploading data")
|
||||
|
||||
// upload...
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
err = spinner.Stop()
|
||||
```
|
||||
|
||||
## Spinners
|
||||
|
||||
The spinner animations below are recorded at a refresh frequency of 200ms. Some
|
||||
animations may look better at a different speed, so play around with the
|
||||
frequency until you find a value you find aesthetically pleasing.
|
||||
|
||||
yacspin.CharSets index | sample gif (Frequency: 200ms)
|
||||
-----------------------|------------------------------
|
||||
0 | 
|
||||
1 | 
|
||||
2 | 
|
||||
3 | 
|
||||
4 | 
|
||||
5 | 
|
||||
6 | 
|
||||
7 | 
|
||||
8 | 
|
||||
9 | 
|
||||
10 | 
|
||||
11 | 
|
||||
12 | 
|
||||
13 | 
|
||||
14 | 
|
||||
15 | 
|
||||
16 | 
|
||||
17 | 
|
||||
18 | 
|
||||
19 | 
|
||||
20 | 
|
||||
21 | 
|
||||
22 | 
|
||||
23 | 
|
||||
24 | 
|
||||
25 | 
|
||||
26 | 
|
||||
27 | 
|
||||
28 | 
|
||||
29 | 
|
||||
30 | 
|
||||
31 | 
|
||||
32 | 
|
||||
33 | 
|
||||
34 | 
|
||||
35 | 
|
||||
36 | 
|
||||
37 | 
|
||||
38 | 
|
||||
39 | 
|
||||
40 | 
|
||||
41 | 
|
||||
42 | 
|
||||
43 | 
|
||||
44 | 
|
||||
45 | 
|
||||
46 | 
|
||||
47 | 
|
||||
48 | 
|
||||
49 | 
|
||||
50 | 
|
||||
51 | 
|
||||
52 | 
|
||||
53 | 
|
||||
54 | 
|
||||
55 | 
|
||||
56 | 
|
||||
57 | 
|
||||
58 | 
|
||||
59 | 
|
||||
60 | 
|
||||
61 | 
|
||||
62 | 
|
||||
63 | 
|
||||
64 | 
|
||||
65 | 
|
||||
66 | 
|
||||
67 | 
|
||||
68 | 
|
||||
69 | 
|
||||
70 | 
|
||||
71 | 
|
||||
72 | 
|
||||
73 | 
|
||||
74 | 
|
||||
75 | 
|
||||
76 | 
|
||||
77 | 
|
||||
78 | 
|
||||
79 | 
|
||||
80 | 
|
||||
81 | 
|
||||
82 | 
|
||||
83 | 
|
||||
84 | 
|
||||
85 | 
|
||||
86 | 
|
||||
87 | 
|
||||
88 | 
|
||||
89 | 
|
||||
90 | 
|
||||
Reference in New Issue
Block a user