packages feed

terminal-progress-bar 0.0.1.4 → 0.1.0

raw patch · 4 files changed

+148/−126 lines, 4 filesdep −base-unicode-symbolsdep ~HUnitdep ~basedep ~terminal-progress-barnew-component:exe:examplePVP ok

version bump matches the API change (PVP)

Dependencies removed: base-unicode-symbols

Dependency ranges changed: HUnit, base, terminal-progress-bar

API changes (from Hackage documentation)

+ System.ProgressBar: hProgressBar :: Handle -> ProgressBar (IO ())
+ System.ProgressBar: type ProgressBar a = Label Prefixed label. -> Label Postfixed label. -> Integer Total progress bar width in characters. -> Integer Amount of work completed. -> Integer Total amount of work. -> a
- System.ProgressBar: incProgress :: ProgressRef -> ℤ -> IO ()
+ System.ProgressBar: incProgress :: ProgressRef -> Integer -> IO ()
- System.ProgressBar: mkProgressBar :: Label -> Label -> ℤ -> ℤ -> ℤ -> String
+ System.ProgressBar: mkProgressBar :: ProgressBar String
- System.ProgressBar: progressBar :: Label -> Label -> ℤ -> ℤ -> ℤ -> IO ()
+ System.ProgressBar: progressBar :: ProgressBar (IO ())
- System.ProgressBar: startProgress :: Label -> Label -> ℤ -> ℤ -> IO (ProgressRef, ThreadId)
+ System.ProgressBar: startProgress :: Label -> Label -> Integer -> Integer -> IO (ProgressRef, ThreadId)
- System.ProgressBar: type Label = ℤ -> ℤ -> String
+ System.ProgressBar: type Label = Integer Completed amount of work. -> Integer Total amount of work. -> String Resulting label.

Files

LICENSE view
@@ -1,4 +1,4 @@-Copyright 2012–2014 Roel van Dijk+Copyright 2012–2016 Roel van Dijk  All rights reserved. 
+ example.hs view
@@ -0,0 +1,28 @@+{-# LANGUAGE PackageImports #-}++module Main where++import "base" Control.Concurrent ( threadDelay )+import "base" Control.Monad ( forM_ )+import "terminal-progress-bar" System.ProgressBar+    ( progressBar, percentage, exact, startProgress, incProgress )++main :: IO ()+main = do+  example  60 (13 + 60) 25000+  example' 60 (13 + 60) 25000++example :: Integer -> Integer -> Int -> IO ()+example t w delay = do+    forM_ [1..t] $ \d -> do+      progressBar percentage exact w d t+      threadDelay delay+    putStrLn ""++example' :: Integer -> Integer -> Int -> IO ()+example' t w delay = do+    (pr, _) <- startProgress percentage exact w t+    forM_ [1..t] $ \_d -> do+      incProgress pr 1+      threadDelay delay+    putStrLn ""
src/System/ProgressBar.hs view
@@ -1,8 +1,10 @@-{-# LANGUAGE NoImplicitPrelude, PackageImports, NamedFieldPuns, RecordWildCards, UnicodeSyntax #-}+{-# language PackageImports, NamedFieldPuns, RecordWildCards #-}  module System.ProgressBar     ( -- * Progress bars-      progressBar+      ProgressBar+    , progressBar+    , hProgressBar     , mkProgressBar       -- * Labels     , Label@@ -10,77 +12,69 @@     , msg     , percentage     , exact-    -- * auto-printing+      -- * Auto printing     , ProgressRef     , startProgress     , incProgress     ) where -import "base" Control.Monad ( (=<<), (>>), return, when )-import "base" Data.Bool     ( otherwise )-import "base" Data.Function ( ($), (.) )-import "base" Data.List     ( null, length, genericLength, genericReplicate )-import "base" Data.Maybe    ( maybe )-import "base" Data.Ord      ( min, max, (>=) )+import "base" Control.Monad ( when )+import "base" Data.List     ( genericLength, genericReplicate ) import "base" Data.Ratio    ( (%) )-import "base" Data.String   ( String )-import "base" Prelude       ( (+), (-), round, floor, Bool(..) )-import "base" System.IO     ( IO, putStr, putChar )+import "base" System.IO     ( Handle, stderr, hPutChar, hPutStr, hFlush ) import "base" Text.Printf   ( printf )-import "base" Text.Show     ( show )-import "base"  Control.Concurrent ( ThreadId, forkIO )-import "stm"  Control.Concurrent.STM ( TVar, readTVar, writeTVar, newTVar, atomically, STM )-import "stm-chans"  Control.Concurrent.STM.TMQueue ( TMQueue, readTMQueue, closeTMQueue, writeTMQueue, newTMQueue )-import "base-unicode-symbols" Data.Bool.Unicode ( (∧) )-import "base-unicode-symbols" Data.Eq.Unicode   ( (≢) )-import "base-unicode-symbols" Prelude.Unicode   ( ℤ, ℚ, (⋅) )+import "base" Control.Concurrent ( ThreadId, forkIO )+import "stm"  Control.Concurrent.STM+    ( TVar, readTVar, writeTVar, newTVar, atomically, STM )+import "stm-chans"  Control.Concurrent.STM.TMQueue+    ( TMQueue, readTMQueue, closeTMQueue, writeTMQueue, newTMQueue ) +-- | Type of functions producing a progress bar.+type ProgressBar a+   = Label   -- ^ Prefixed label.+  -> Label   -- ^ Postfixed label.+  -> Integer -- ^ Total progress bar width in characters.+  -> Integer -- ^ Amount of work completed.+  -> Integer -- ^ Total amount of work.+  -> a --- | Print a progress bar+-- | Print a progress bar to 'stderr' --+-- See 'hProgressBar'.+progressBar :: ProgressBar (IO ())+progressBar = hProgressBar stderr++-- | Print a progress bar to a file handle.+-- -- Erases the current line! (by outputting '\r') Does not print a -- newline '\n'. Subsequent invocations will overwrite the previous -- output.------ Remember to set the correct buffering mode for stdout:------ > import System.IO ( hSetBuffering, BufferMode(NoBuffering), stdout )--- > hSetBuffering stdout NoBuffering-progressBar ∷ Label -- ^ Prefixed label.-            → Label -- ^ Postfixed label.-            → ℤ     -- ^ Total progress bar width in characters.-            → ℤ     -- ^ Amount of work completed.-            → ℤ     -- ^ Total amount of work.-            → IO ()-progressBar mkPreLabel mkPostLabel width todo done = do-    putChar '\r'-    putStr $ mkProgressBar mkPreLabel mkPostLabel width todo done+hProgressBar :: Handle -> ProgressBar (IO ())+hProgressBar hndl mkPreLabel mkPostLabel width todo done = do+    hPutChar hndl '\r'+    hPutStr hndl $ mkProgressBar mkPreLabel mkPostLabel width todo done+    hFlush hndl  -- | Renders a progress bar -- -- >>> mkProgressBar (msg "Working") percentage 40 30 100 -- "Working [=======>.................]  30%"-mkProgressBar ∷ Label -- ^ Prefixed label.-              → Label -- ^ Postfixed label.-              → ℤ     -- ^ Total progress bar width in characters.-              → ℤ     -- ^ Amount of work completed.-              → ℤ     -- ^ Total amount of work.-              → String+mkProgressBar :: ProgressBar 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)+           (if remaining /= 0 && completed /= 0 then ">" else "")+           (genericReplicate (remaining - if completed /= 0 then 1 else 0)                              '.'            )            postPad            postLabel   where     -- Amount of work completed.-    fraction ∷ ℚ-    fraction | done ≢ 0  = todo % done+    fraction :: Rational+    fraction | done /= 0  = todo % done              | otherwise = 0 % 1      -- Amount of characters available to visualize the progress.@@ -93,41 +87,44 @@     -- Number of characters needed to represent the amount of work     -- that is completed. Note that this can not always be represented     -- by an integer.-    numCompletedChars ∷ ℚ-    numCompletedChars = fraction ⋅ (effectiveWidth % 1)+    numCompletedChars :: Rational+    numCompletedChars = fraction * (effectiveWidth % 1) -    completed, remaining ∷ ℤ+    completed, remaining :: Integer     completed = min effectiveWidth $ floor numCompletedChars     remaining = effectiveWidth - completed -    preLabel, postLabel ∷ String+    preLabel, postLabel :: String     preLabel  = mkPreLabel  todo done     postLabel = mkPostLabel todo done -    prePad, postPad ∷ String+    prePad, postPad :: String     prePad  = pad preLabel     postPad = pad postLabel -    pad ∷ String → String+    pad :: String -> String     pad s | null s    = ""           | otherwise = " "   -- | A label that can be pre- or postfixed to a progress bar.-type Label = ℤ → ℤ → String+type Label+   = Integer -- ^ Completed amount of work.+  -> Integer -- ^ Total amount of work.+  -> String  -- ^ Resulting label.  -- | The empty label. -- -- >>> noLabel 30 100 -- ""-noLabel ∷ Label+noLabel :: Label noLabel = msg ""  -- | A label consisting of a static string. -- -- >>> msg "foo" 30 100 -- "foo"-msg ∷ String → Label+msg :: String -> Label msg s _ _ = s  -- | A label which displays the progress as a percentage.@@ -138,9 +135,9 @@ -- >>> percentage 30 100 -- " 30%" --- ∀ d t : ℕ. d ≤ t → length (percentage d t) ≡ 3-percentage ∷ Label-percentage done todo = printf "%3i%%" (round (done % todo ⋅ 100) ∷ ℤ)+-- ∀ d t : ℕ. d ≤ t -> length (percentage d t) ≡ 3+percentage :: Label+percentage done todo = printf "%3i%%" (round (done % todo * 100) :: Integer)  -- | A label which displays the progress as a fraction of the total -- amount of work.@@ -151,28 +148,32 @@ -- >>> exact 30 100 -- " 30/100" --- ∀ d₁ d₂ t : ℕ. d₁ ≤ d₂ ≤ t → length (exact d₁ t) ≡ length (exact d₂ t)-exact ∷ Label+-- ∀ d₁ d₂ t : ℕ. d₁ ≤ d₂ ≤ t -> length (exact d₁ t) ≡ length (exact d₂ t)+exact :: Label exact done total = printf "%*i/%s" (length totalStr) done totalStr   where     totalStr = show total  -- * Auto-Printing Progress -data ProgressRef = ProgressRef { prPrefix    ∷ Label-                               , prPostfix   ∷ Label-                               , prWidth     ∷ ℤ-                               , prCompleted ∷ TVar ℤ-                               , prTotal     ∷ ℤ-                               , prQueue     ∷ TMQueue ℤ }+data ProgressRef+   = ProgressRef+     { prPrefix    :: Label+     , prPostfix   :: Label+     , prWidth     :: Integer+     , prCompleted :: TVar Integer+     , prTotal     :: Integer+     , prQueue     :: TMQueue Integer+     }  -- | Start a thread to automatically display progress. Use incProgress to step -- the progress bar.-startProgress ∷ Label -- ^ Prefixed label.-              → Label -- ^ Postfixed label.-              → ℤ     -- ^ Total progress bar width in characters.-              → ℤ     -- ^ Total amount of work.-              → IO (ProgressRef, ThreadId)+startProgress+    :: Label   -- ^ Prefixed label.+    -> Label   -- ^ Postfixed label.+    -> Integer -- ^ Total progress bar width in characters.+    -> Integer -- ^ Total amount of work.+    -> IO (ProgressRef, ThreadId) startProgress mkPreLabel mkPostLabel width total = do     pr  <- buildProgressRef     tid <- forkIO $ reportProgress pr@@ -184,36 +185,32 @@         return $ ProgressRef mkPreLabel mkPostLabel width completed total queue  -- | Increment the progress bar. Negative values will reverse the progress.--- Progress will never be negative and will silently stop taking data when it--- completes.-incProgress ∷ ProgressRef-            → ℤ-            → IO ()-incProgress ProgressRef {prQueue} = atomically . writeTMQueue prQueue+-- Progress will never be negative and will silently stop taking data+-- when it completes.+incProgress :: ProgressRef -> Integer -> IO ()+incProgress progressRef =+    atomically . writeTMQueue (prQueue progressRef) -reportProgress ∷ ProgressRef-               → IO ()+reportProgress :: ProgressRef -> IO () reportProgress pr = do-  continue <- atomically $ updateProgress pr-  renderProgress pr-  when continue $ reportProgress pr+    continue <- atomically $ updateProgress pr+    renderProgress pr+    when continue $ reportProgress pr -updateProgress ∷ ProgressRef-               → STM Bool+updateProgress :: ProgressRef -> STM Bool updateProgress ProgressRef {prCompleted, prQueue, prTotal} = do-  maybe dontContinue doUpdate =<< readTMQueue prQueue-  where-    dontContinue = return False-    doUpdate countDiff = do-      count <- readTVar prCompleted-      let newCount = min prTotal $ max 0 $ count + countDiff-      writeTVar prCompleted newCount-      if newCount >= prTotal-        then closeTMQueue prQueue >> dontContinue-        else return True-                       -renderProgress ∷ ProgressRef-               → IO ()+    maybe dontContinue doUpdate =<< readTMQueue prQueue+    where+      dontContinue = return False+      doUpdate countDiff = do+        count <- readTVar prCompleted+        let newCount = min prTotal $ max 0 $ count + countDiff+        writeTVar prCompleted newCount+        if newCount >= prTotal+          then closeTMQueue prQueue >> dontContinue+          else return True++renderProgress :: ProgressRef -> IO () renderProgress ProgressRef {..} = do-  completed <- atomically $ readTVar prCompleted-  progressBar prPrefix prPostfix prWidth completed prTotal+    completed <- atomically $ readTVar prCompleted+    progressBar prPrefix prPostfix prWidth completed prTotal
terminal-progress-bar.cabal view
@@ -1,6 +1,6 @@ name:          terminal-progress-bar-version:       0.0.1.4-cabal-version: >=1.8+version:       0.1.0+cabal-version: >=1.10 build-type:    Simple stability:     provisional author:        Roel van Dijk <vandijk.roel@gmail.com>@@ -24,10 +24,6 @@   the carriage return character (\'\\r\'). If your terminal interprets   it as something else then \"move cursor to beginning of line\", the   animation won't work.-  .-  Note: Due to a bug in \"cabal haddock\" you will have to manually-  uncomment the example section in the cabal file. But uncommenting-  that section will result in \"cabal haddock\" failing.  extra-source-files: LICENSE, README.markdown @@ -42,32 +38,33 @@ library     hs-source-dirs: src     build-depends: base                 >= 3.0.3.1 && < 5.0-                 , base-unicode-symbols >= 0.2.2.3 && < 0.3                  , stm                  >= 2.4     && < 3.0                  , stm-chans            >= 3.0.0   && < 4.0     exposed-modules: System.ProgressBar     ghc-options: -Wall+    default-language: Haskell2010 -test-suite test-terminal-progress-bar-  type: exitcode-stdio-1.0-  main-is: test.hs-  hs-source-dirs: test-  ghc-options: -Wall-  build-depends: base                  >= 3.0.3.1 && < 5.0-               , base-unicode-symbols  >= 0.2.2.3 && < 0.3-               , HUnit                 >= 1.2.4.2 && < 1.3-               , terminal-progress-bar-               , test-framework        >= 0.3.3   && < 0.9-               , test-framework-hunit  >= 0.2.6   && < 0.4 --- executable example---   main-is: example.hs---   hs-source-dirs: .---   if flag(example)---     build-depends: base                  >= 3.0.3.1 && < 4.6---                  , base-unicode-symbols  >= 0.2.2.3 && < 0.3---                  , terminal-progress-bar == 0.0.1---     buildable: True---   else---     buildable: False+test-suite test-terminal-progress-bar+    type: exitcode-stdio-1.0+    main-is: test.hs+    hs-source-dirs: test+    ghc-options: -Wall+    build-depends: base                  >= 3.0.3.1 && < 5.0+                 , HUnit                 >= 1.2.4.2 && < 1.4+                 , terminal-progress-bar == 0.1.0+                 , test-framework        >= 0.3.3   && < 0.9+                 , test-framework-hunit  >= 0.2.6   && < 0.4+    default-language: Haskell2010 +executable example+    main-is: example.hs+    hs-source-dirs: .+    ghc-options: -Wall+    if flag(example)+      build-depends: base                  >= 3.0.3.1 && < 5.0+                   , terminal-progress-bar == 0.1.0+      buildable: True+    else+      buildable: False+    default-language: Haskell2010