module System.ProgressBar
(
progressBar
, mkProgressBar
, Label
, noLabel
, msg
, percentage
, exact
) where
import "base" Data.Bool ( otherwise )
import "base" Data.Function ( ($) )
import "base" Data.List ( null, length, genericLength, genericReplicate )
import "base" Data.Ord ( min, max )
import "base" Data.Ratio ( (%) )
import "base" Data.String ( String )
import "base" Prelude ( (+), (), round, floor )
import "base" System.IO ( IO, putStr, putChar )
import "base" Text.Printf ( printf )
import "base" Text.Show ( show )
import "base-unicode-symbols" Data.Bool.Unicode ( (∧) )
import "base-unicode-symbols" Data.Eq.Unicode ( (≢) )
import "base-unicode-symbols" Prelude.Unicode ( ℤ, ℚ, (⋅) )
progressBar ∷ Label
→ Label
→ ℤ
→ ℤ
→ ℤ
→ IO ()
progressBar mkPreLabel mkPostLabel width todo done = do
putChar '\r'
putStr $ mkProgressBar mkPreLabel mkPostLabel width todo done
mkProgressBar ∷ Label
→ Label
→ ℤ
→ ℤ
→ ℤ
→ String
mkProgressBar mkPreLabel mkPostLabel width todo done =
printf "%s%s[%s%s%s]%s%s"
preLabel
prePad
(genericReplicate completed '=')
(if remaining ≢ 0 ∧ completed ≢ 0 then ">" else "")
(genericReplicate (remaining if completed ≢ 0 then 1 else 0)
'.'
)
postPad
postLabel
where
fraction ∷ ℚ
fraction | done ≢ 0 = todo % done
| otherwise = 0 % 1
effectiveWidth = max 0 $ width usedSpace
usedSpace = 2 + genericLength preLabel
+ genericLength postLabel
+ genericLength prePad
+ genericLength postPad
numCompletedChars ∷ ℚ
numCompletedChars = fraction ⋅ (effectiveWidth % 1)
completed, remaining ∷ ℤ
completed = min effectiveWidth $ floor numCompletedChars
remaining = effectiveWidth completed
preLabel, postLabel ∷ String
preLabel = mkPreLabel todo done
postLabel = mkPostLabel todo done
prePad, postPad ∷ String
prePad = pad preLabel
postPad = pad postLabel
pad ∷ String → String
pad s | null s = ""
| otherwise = " "
type Label = ℤ → ℤ → String
noLabel ∷ Label
noLabel = msg ""
msg ∷ String → Label
msg s _ _ = s
percentage ∷ Label
percentage done todo = printf "%3i%%" (round (done % todo ⋅ 100) ∷ ℤ)
exact ∷ Label
exact done total = printf "%*i/%s" (length totalStr) done totalStr
where
totalStr = show total