| 🛟 Updated. 28d5985 k33g 14h ago | 1 | package acp |
| 2 | |
| 3 | import "time" |
| 4 | |
| 5 | // SpinnerPeriod is how long one frame of the spinner lasts. Eight frames a |
| 6 | // second reads as motion without drawing attention away from the text. |
| 7 | const SpinnerPeriod = 120 * time.Millisecond |
| 8 | |
| 9 | // spinnerFrames are the braille dots every terminal spinner uses. They are one |
| 10 | // column wide, which matters: a frame that changed width would shift the words |
| 11 | // beside it on every tick. |
| 12 | var spinnerFrames = []rune("⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏") |
| 13 | |
| 14 | // Spinner returns the frame to draw at a moment. |
| 15 | // |
| 16 | // It is a function of the clock rather than of a counter somebody increments, |
| 17 | // so drawing stays a pure function of state — the same rule the rest of this |
| 18 | // editor follows, and what lets a test assert on a frame without waiting for |
| 19 | // one. Nothing has to be reset when a turn starts, and two windows thinking at |
| 20 | // once turn in step. |
| 21 | // |
| 22 | // view.ruleLabel() // " ⠙ thinking — Esc stops it " |
| 23 | func Spinner(at time.Time) rune { |
| 24 | frame := at.UnixNano() / int64(SpinnerPeriod) |
| 25 | return spinnerFrames[int(frame%int64(len(spinnerFrames)))] |
| 26 | } |