package acp import "time" // SpinnerPeriod is how long one frame of the spinner lasts. Eight frames a // second reads as motion without drawing attention away from the text. const SpinnerPeriod = 120 * time.Millisecond // spinnerFrames are the braille dots every terminal spinner uses. They are one // column wide, which matters: a frame that changed width would shift the words // beside it on every tick. var spinnerFrames = []rune("⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏") // Spinner returns the frame to draw at a moment. // // It is a function of the clock rather than of a counter somebody increments, // so drawing stays a pure function of state — the same rule the rest of this // editor follows, and what lets a test assert on a frame without waiting for // one. Nothing has to be reset when a turn starts, and two windows thinking at // once turn in step. // // view.ruleLabel() // " ⠙ thinking — Esc stops it " func Spinner(at time.Time) rune { frame := at.UnixNano() / int64(SpinnerPeriod) return spinnerFrames[int(frame%int64(len(spinnerFrames)))] }