From 0f4e056641d58ecddc24020180d623bc498c6e56 Mon Sep 17 00:00:00 2001 From: Joshua Clayton Date: Fri, 6 May 2016 16:11:09 -0400 Subject: [PATCH] Introduce a Spinner when no progress bar is displayed Why? ==== With a spinner in place, there's visual indication that something's happening. --- src/Unused/CLI/SearchWithoutProgress.hs | 7 ++-- src/Unused/CLI/Spinner.hs | 45 +++++++++++++++++++++++++ unused.cabal | 1 + 3 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 src/Unused/CLI/Spinner.hs diff --git a/src/Unused/CLI/SearchWithoutProgress.hs b/src/Unused/CLI/SearchWithoutProgress.hs index 2f6f8b9..6b4d059 100644 --- a/src/Unused/CLI/SearchWithoutProgress.hs +++ b/src/Unused/CLI/SearchWithoutProgress.hs @@ -3,7 +3,10 @@ module Unused.CLI.SearchWithoutProgress ) where import Unused.TermSearch (search) +import Unused.CLI.Spinner (startSpinner, stopSpinner) searchWithoutProgressBar :: [String] -> IO [String] -searchWithoutProgressBar terms = - concat <$> mapM search terms +searchWithoutProgressBar terms = do + putStr " " + sp <- startSpinner + concat <$> mapM search terms <* stopSpinner sp diff --git a/src/Unused/CLI/Spinner.hs b/src/Unused/CLI/Spinner.hs new file mode 100644 index 0000000..0065bcc --- /dev/null +++ b/src/Unused/CLI/Spinner.hs @@ -0,0 +1,45 @@ +module Unused.CLI.Spinner + ( startSpinner + , stopSpinner + ) where + +import Control.Monad (forever) +import Control.Concurrent (ThreadId, killThread, threadDelay, forkIO) +import Unused.CLI.Util + +data Spinner = Spinner + { sSnapshots :: [String] + , sLength :: Int + , sDelay :: Int + , sColors :: [Color] + , sThreadId :: Maybe ThreadId + } + +startSpinner :: IO Spinner +startSpinner = do + let s = buildSpinner + tid <- forkIO $ runSpinner 0 s + return $ s { sThreadId = Just tid } + +stopSpinner :: Spinner -> IO () +stopSpinner Spinner{ sThreadId = Nothing } = return () +stopSpinner Spinner{ sThreadId = Just tid } = killThread tid + +buildSpinner :: Spinner +buildSpinner = + Spinner snapshots (length snapshots) 100000 colors Nothing + where + snapshots = ["⣾", "⣽", "⣻", "⢿", "⡿", "⣟", "⣯", "⣷"] + colors = cycle [Black, Red, Yellow, Green, Blue, Cyan, Magenta] + +runSpinner :: Int -> Spinner -> IO () +runSpinner i s = forever $ do + setSGR [SetColor Foreground Dull currentColor] + putStr currentSnapshot + cursorBackward 1 + threadDelay $ sDelay s + runSpinner (i + 1) s + where + currentSnapshot = sSnapshots s !! (i `mod` snapshotLength) + currentColor = sColors s !! (i `div` snapshotLength) + snapshotLength = sLength s diff --git a/unused.cabal b/unused.cabal index 26b288d..7de00e7 100644 --- a/unused.cabal +++ b/unused.cabal @@ -27,6 +27,7 @@ library , Unused.CLI.SearchWithProgress , Unused.CLI.SearchWithoutProgress , Unused.CLI.Util + , Unused.CLI.Spinner build-depends: base >= 4.7 && < 5 , process , parsec