futhark-0.22.2: src/Futhark/Util/ProgressBar.hs
-- | Facilities for generating and otherwise handling pretty-based progress bars.
module Futhark.Util.ProgressBar
( progressBar,
ProgressBar (..),
progressSpinner,
)
where
import Data.Text qualified as T
-- | Information about a progress bar to render. The "progress space"
-- spans from 0 and up to the `progressBarBound`, but can be
-- visualised in any number of steps.
data ProgressBar = ProgressBar
{ -- | Number of steps in the visualisation.
progressBarSteps :: Int,
-- | The logical upper bound.
progressBarBound :: Double,
-- | The current position in the progress bar, relative to the
-- upper bound.
progressBarElapsed :: Double
}
-- | Render the progress bar.
progressBar :: ProgressBar -> T.Text
progressBar (ProgressBar steps bound elapsed) =
"|" <> T.pack (map cell [1 .. steps]) <> "| "
where
step_size :: Double
step_size = bound / fromIntegral steps
chars = " ▏▎▍▍▌▋▊▉█"
num_chars = T.length chars
char i
| i >= 0 && i < num_chars = T.index chars i
| otherwise = ' '
cell :: Int -> Char
cell i
| i' * step_size <= elapsed = char 9
| otherwise =
char (floor (((elapsed - (i' - 1) * step_size) * fromIntegral num_chars) / step_size))
where
i' = fromIntegral i
-- | Render a spinner - a kind of progress bar where there is no upper
-- bound because we don't know how long it'll take. You certainly
-- know these from THE INTERNET. The non-negative integer is how many
-- "steps" have been taken. The spinner looks best if this is
-- incremented by one for every call.
progressSpinner :: Int -> T.Text
progressSpinner spin_idx =
T.singleton $ T.index spin_load (spin_idx `rem` n)
where
spin_load = "⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"
n = T.length spin_load