packages feed

hackport-0.2.6: BlingBling.hs

module BlingBling where

import qualified Progress

import System.IO
import Control.Exception as Exception (bracket)

-- what nobody needs but everyone wants...

-- FIXME: do something more fun here
forMbling :: [a] -> (a -> IO b) -> IO [b]
forMbling lst f =
  withBuffering stdout NoBuffering $ do
    xs <- mapM (\x -> putStr "." >> f x) lst
    putStrLn ""
    return xs

blingProgress :: Progress.Progress s String a -> IO a
blingProgress progress = do
  isTerm <- hIsTerminalDevice stdout
  if isTerm
    then canIHasTehBling
    else boring

  where
    boring = Progress.fold (flip const) fail return progress

    canIHasTehBling =
      withBuffering stdout NoBuffering $ do
        putChar (fst (char 0))
        result <- spin 0 progress
        putStr "\b \b"
        return result

    spin _ (Progress.Fail e) = fail e
    spin _ (Progress.Done r) = return r
    spin n (Progress.Step _ p) = do
        putStr ['\b', c]
        spin n' p
      where (c, n') = char n

    char :: Int -> (Char, Int)
    char 0 = ('/',  1)
    char 1 = ('-',  2)
    char 2 = ('\\', 3)
    char _ = ('|',  0)

withBuffering :: Handle -> BufferMode -> IO a -> IO a
withBuffering hnd mode action =
  Exception.bracket
    (hGetBuffering hnd) (hSetBuffering hnd)
    (\_ -> hSetBuffering hnd mode >> action)