ansigraph 0.2.0.0 → 0.3.0.0
raw patch · 9 files changed
+119/−65 lines, 9 filesdep +transformersdep ~basePVP ok
version bump matches the API change (PVP)
Dependencies added: transformers
Dependency ranges changed: base
API changes (from Hackage documentation)
+ System.Console.Ansigraph.Core: Black :: Color
+ System.Console.Ansigraph.Core: Blue :: Color
+ System.Console.Ansigraph.Core: Cyan :: Color
+ System.Console.Ansigraph.Core: Dull :: ColorIntensity
+ System.Console.Ansigraph.Core: Green :: Color
+ System.Console.Ansigraph.Core: Magenta :: Color
+ System.Console.Ansigraph.Core: Red :: Color
+ System.Console.Ansigraph.Core: Vivid :: ColorIntensity
+ System.Console.Ansigraph.Core: White :: Color
+ System.Console.Ansigraph.Core: Yellow :: Color
+ System.Console.Ansigraph.Core: clearBack :: MonadIO m => Int -> m ()
+ System.Console.Ansigraph.Core: data Color :: *
+ System.Console.Ansigraph.Core: data ColorIntensity :: *
- System.Console.Ansigraph.Core: animate :: Graphable a => [a] -> IO ()
+ System.Console.Ansigraph.Core: animate :: MonadIO m => Graphable a => [a] -> m ()
- System.Console.Ansigraph.Core: animateWith :: Graphable a => GraphSettings -> [a] -> IO ()
+ System.Console.Ansigraph.Core: animateWith :: MonadIO m => Graphable a => GraphSettings -> [a] -> m ()
- System.Console.Ansigraph.Core: applyColoring :: Coloring -> IO ()
+ System.Console.Ansigraph.Core: applyColoring :: MonadIO m => Coloring -> m ()
- System.Console.Ansigraph.Core: boldStr :: Coloring -> String -> IO ()
+ System.Console.Ansigraph.Core: boldStr :: MonadIO m => Coloring -> String -> m ()
- System.Console.Ansigraph.Core: boldStrLn :: Coloring -> String -> IO ()
+ System.Console.Ansigraph.Core: boldStrLn :: MonadIO m => Coloring -> String -> m ()
- System.Console.Ansigraph.Core: clear :: IO ()
+ System.Console.Ansigraph.Core: clear :: MonadIO m => m ()
- System.Console.Ansigraph.Core: clearLn :: IO ()
+ System.Console.Ansigraph.Core: clearLn :: MonadIO m => m ()
- System.Console.Ansigraph.Core: colorStr :: Coloring -> String -> IO ()
+ System.Console.Ansigraph.Core: colorStr :: MonadIO m => Coloring -> String -> m ()
- System.Console.Ansigraph.Core: colorStrLn :: Coloring -> String -> IO ()
+ System.Console.Ansigraph.Core: colorStrLn :: MonadIO m => Coloring -> String -> m ()
- System.Console.Ansigraph.Core: displayCMat :: GraphSettings -> [[Complex Double]] -> IO ()
+ System.Console.Ansigraph.Core: displayCMat :: MonadIO m => GraphSettings -> [[Complex Double]] -> m ()
- System.Console.Ansigraph.Core: displayCV :: GraphSettings -> [Complex Double] -> IO ()
+ System.Console.Ansigraph.Core: displayCV :: MonadIO m => GraphSettings -> [Complex Double] -> m ()
- System.Console.Ansigraph.Core: displayMat :: GraphSettings -> [[Double]] -> IO ()
+ System.Console.Ansigraph.Core: displayMat :: MonadIO m => GraphSettings -> [[Double]] -> m ()
- System.Console.Ansigraph.Core: displayPV :: GraphSettings -> [Double] -> IO ()
+ System.Console.Ansigraph.Core: displayPV :: MonadIO m => GraphSettings -> [Double] -> m ()
- System.Console.Ansigraph.Core: displayRV :: GraphSettings -> [Double] -> IO ()
+ System.Console.Ansigraph.Core: displayRV :: MonadIO m => GraphSettings -> [Double] -> m ()
- System.Console.Ansigraph.Core: graphWith :: Graphable a => GraphSettings -> a -> IO ()
+ System.Console.Ansigraph.Core: graphWith :: (Graphable a, MonadIO m) => GraphSettings -> a -> m ()
- System.Console.Ansigraph.Core: setColor :: ConsoleLayer -> AnsiColor -> IO ()
+ System.Console.Ansigraph.Core: setColor :: MonadIO m => ConsoleLayer -> AnsiColor -> m ()
- System.Console.Ansigraph.Core: transientAnim :: Graphable a => [a] -> IO ()
+ System.Console.Ansigraph.Core: transientAnim :: (MonadIO m, Graphable a) => [a] -> m ()
- System.Console.Ansigraph.Core: transientAnimWith :: Graphable a => GraphSettings -> [a] -> IO ()
+ System.Console.Ansigraph.Core: transientAnimWith :: MonadIO m => Graphable a => GraphSettings -> [a] -> m ()
Files
- CHANGELOG.md +8/−0
- README.md +1/−1
- ansigraph.cabal +6/−2
- src/System/Console/Ansigraph/Core.hs +28/−16
- src/System/Console/Ansigraph/Examples.hs +9/−6
- src/System/Console/Ansigraph/Internal/Core.hs +44/−28
- src/System/Console/Ansigraph/Internal/Horizontal.hs +7/−3
- src/System/Console/Ansigraph/Internal/Matrix.hs +13/−9
- test/test-ansigraph.hs +3/−0
CHANGELOG.md view
@@ -1,5 +1,13 @@ # Ansigraph Changelog +## Version 0.3++* Change all IO operations to work over any `MonadIO`. Since GHC 8 this is available in `base`, so the dependency on `transformers` is only required for previous versions.++* Support GHC versions back to 7.6.++* Reexport the `Color` and `ColorIntensity` data types from `ansi-terminal` for full use of the range of ANSI colors without importing that package.+ ## Version 0.2 * Improved method of displaying animations so that successive frames overwrite previous ones instead of generating many pages of output. This requires the addition of the `graphHeight :: Graphable a => a -> Int` type class method.
README.md view
@@ -7,7 +7,7 @@ __Terminal-based graphing via ANSI and Unicode__ -<img src="img/wavedemo.gif">+ ### Overview
ansigraph.cabal view
@@ -1,5 +1,5 @@ name: ansigraph-version: 0.2.0.0+version: 0.3.0.0 synopsis: Terminal-based graphing via ANSI and Unicode description: Ansigraph is an ultralightweight terminal-based graphing utility. It uses@@ -59,9 +59,12 @@ System.Console.Ansigraph.Internal.Horizontal, System.Console.Ansigraph.Internal.Matrix - build-depends: base >=4.8 && <4.10,+ build-depends: base >=4.6 && <4.10, ansi-terminal >=0.6 && <0.7 + if (impl(ghc < 8.0))+ build-depends: transformers >= 0.3 && <0.5+ hs-source-dirs: src default-language: Haskell2010@@ -70,6 +73,7 @@ -fno-warn-orphans -fno-warn-unused-do-bind -fno-warn-missing-signatures+ -fno-warn-unused-imports test-suite test-ansigraph
src/System/Console/Ansigraph/Core.hs view
@@ -29,12 +29,18 @@ -- *** Graphing options , GraphSettings (..) - -- *** Default options+ -- **** Default options , graphDefaults , blue, pink, white, red, green , noColoring -- *** ANSI data+ -- **** Basic types from ANSI package+ , Color (..)+ , ColorIntensity (..)+++-- **** Custom composite data types , AnsiColor (..) , Coloring (..) @@ -83,6 +89,9 @@ , posGraph , posAnim +-- *** For clearing+ , clearBack+ ) where import System.Console.Ansigraph.Internal.Core@@ -90,9 +99,10 @@ import System.Console.Ansigraph.Internal.Matrix import System.Console.ANSI-import Control.Concurrent (threadDelay)-import Control.Monad (replicateM_)-import Data.Complex (Complex)+import Control.Concurrent (threadDelay)+import Control.Monad (replicateM_)+import Data.Complex (Complex)+import Control.Monad.IO.Class (MonadIO, liftIO) -- | Things that ansigraph knows how to render at the terminal are instances of this class.@@ -106,7 +116,7 @@ class Graphable a where -- | Render a graph to standard output.- graphWith :: GraphSettings -> a -> IO ()+ graphWith :: MonadIO m => GraphSettings -> a -> m () -- | The number of vertical lines a graph occupies. graphHeight :: a -> Int@@ -119,10 +129,12 @@ ---- IO / ANSI helpers ---- -clearBack :: Int -> IO ()+-- | Clear the last @n@ lines of terminal text. Used to make graph animations. Rexported as+-- a handy convenience for other uses.+clearBack :: MonadIO m => Int -> m () clearBack n = do- putStr "\r" -- return cursor to horizontal position 0- replicateM_ n (cursorUpLine 1 *> clearLine)+ putStr' "\r" -- return cursor to horizontal position 0+ replicateM_ n (liftIO $ cursorUpLine 1 >> clearLine) -- | For some number of frames per second, return the corresponding time delta in microseconds. deltaFromFPS :: Int -> Int@@ -131,34 +143,34 @@ ---- Animation ---- -clearGraph :: Graphable a => a -> IO ()+clearGraph :: MonadIO m => Graphable a => a -> m () clearGraph = clearBack . graphHeight -animationFrame :: Graphable a => GraphSettings -> a -> IO ()+animationFrame :: MonadIO m => Graphable a => GraphSettings -> a -> m () animationFrame s x = do graphWith s x- threadDelay . deltaFromFPS . framerate $ s+ liftIO . threadDelay . deltaFromFPS . framerate $ s clearGraph x -- | Any list of a 'Graphable' type can be made into an animation, by -- 'graph'ing each element with a time delay and screen-clear after each. -- 'GraphSettings' are used to determine the time delta and any coloring/scaling options.-animateWith :: Graphable a => GraphSettings -> [a] -> IO ()+animateWith :: MonadIO m => Graphable a => GraphSettings -> [a] -> m () animateWith _ [] = return () animateWith s [x] = graphWith s x-animateWith s (x:y:zs) = animationFrame s x *> animateWith s (y:zs)+animateWith s (x:y:zs) = animationFrame s x >> animateWith s (y:zs) -- | Perform 'animateWith' using default options. Equivalent to 'graph'ing each member -- of the supplied list with a short delay and screen-clear after each.-animate :: Graphable a => [a] -> IO ()+animate :: MonadIO m => Graphable a => [a] -> m () animate = animateWith graphDefaults -- | Like 'animateWith', only it does not leave the final frame of the animation visible.-transientAnimWith :: Graphable a => GraphSettings -> [a] -> IO ()+transientAnimWith :: MonadIO m => Graphable a => GraphSettings -> [a] -> m () transientAnimWith = mapM_ . animationFrame -- | Like 'animate', only it does not leave the final frame of the animation visible.-transientAnim :: Graphable a => [a] -> IO ()+transientAnim :: (MonadIO m, Graphable a) => [a] -> m () transientAnim = transientAnimWith graphDefaults
src/System/Console/Ansigraph/Examples.hs view
@@ -24,6 +24,8 @@ import System.Console.ANSI import Control.Monad (forM_) import Data.Complex (Complex (..), cis, realPart)+-- for GHC <= 7.8+import Control.Applicative ---- Wave Demo ----@@ -77,13 +79,14 @@ fromRealMs = zipWith fromRealVs vox :: Num a => [a] -> [a] -> [a]-vox v w = concat $ map (flip vscale w) v+vox v w = concatMap (`vscale` w) v -- matrix tensor product-stepOne, stepTwo, mox :: Num a => [[a]] -> [[a]] -> [[a]]-stepOne m1 m2 = concat $ map (replicate (length m2)) m1-stepTwo m1 m2 = concat $ replicate (length m1) m2-mox m1 m2 = zipWith vox (stepOne m1 m2) (stepTwo m1 m2)+mox :: Num a => [[a]] -> [[a]] -> [[a]]+mox m1 m2 = zipWith vox (stepOne m1 m2) (stepTwo m1 m2)+ where stepOne, stepTwo :: [[a]] -> [[a]] -> [[a]]+ stepOne x y = concatMap (replicate (length y)) x+ stepTwo x y = concat $ replicate (length x) y ---- Complex matrix example ----@@ -116,7 +119,7 @@ ---- Real matrix example ---- ry :: Double -> [[Double]]-ry t = [[cos t, 0, (sin t)]+ry t = [[cos t, 0, sin t] ,[0, 1, 0] ,[-(sin t),0,cos t]]
src/System/Console/Ansigraph/Internal/Core.hs view
@@ -4,6 +4,9 @@ import System.Console.ANSI import System.IO (hFlush, stdout)+import Control.Monad.IO.Class (MonadIO, liftIO)+-- for GHC <= 7.8+import Control.Applicative ---- Basics ---- @@ -51,6 +54,19 @@ -- | 'Dull' 'Green' – used as the default foreground color for negative imaginary component. green = AnsiColor Dull Green +-- | 'Dull' 'Black'.+black = AnsiColor Dull Blue++-- | 'Vivid' 'Yellow'.+yellow = AnsiColor Vivid Yellow++-- | 'Vivid' 'Magenta'.+magenta = AnsiColor Vivid Magenta++-- | 'Vivid' 'Cyan'.+cyan = AnsiColor Vivid Cyan++ -- | Default graph settings. graphDefaults = GraphSettings blue pink red green white white 15 @@ -84,14 +100,6 @@ invert :: Coloring -> Coloring invert (Coloring fg bg) = Coloring bg fg --- | The SGR command corresponding to a particular 'ConsoleLayer' and 'AnsiColor'.-interpAnsiColor :: ConsoleLayer -> AnsiColor -> SGR-interpAnsiColor l (AnsiColor i c) = SetColor l i c---- | Set the given 'AnsiColor' on the given 'ConsoleLayer'.-setColor :: ConsoleLayer -> AnsiColor -> IO ()-setColor l c = setSGR [interpAnsiColor l c]- -- | Easily create a 'Coloring' by specifying the background 'AnsiColor' and no custom foreground. fromBG :: AnsiColor -> Coloring fromBG c = Coloring Nothing (Just c)@@ -100,53 +108,61 @@ fromFG :: AnsiColor -> Coloring fromFG c = Coloring (Just c) Nothing +-- | The SGR command corresponding to a particular 'ConsoleLayer' and 'AnsiColor'.+interpAnsiColor :: ConsoleLayer -> AnsiColor -> SGR+interpAnsiColor l (AnsiColor i c) = SetColor l i c+ -- | Produce a (possibly empty) list of 'SGR' commands from a 'ConsoleLayer' and 'AnsiColor'. -- An empty 'SGR' list is equivalent to 'Reset'. sgrList :: ConsoleLayer -> Maybe AnsiColor -> [SGR]-sgrList l = fmap (interpAnsiColor l) . maybe [] (\x -> [x])+sgrList l = fmap (interpAnsiColor l) . maybe [] pure +-- | Set the given 'AnsiColor' on the given 'ConsoleLayer'.+setColor :: MonadIO m => ConsoleLayer -> AnsiColor -> m ()+setColor l c = liftIO $ setSGR [interpAnsiColor l c]+ -- | Apply both foreground and background color contained in a 'Coloring'.-applyColoring :: Coloring -> IO ()-applyColoring (Coloring fg bg) = do+applyColoring :: MonadIO m => Coloring -> m ()+applyColoring (Coloring fg bg) = liftIO $ do setSGR [Reset] setSGR $ sgrList Foreground fg ++ sgrList Background bg -- | Clear any SGR settings and then flush stdout.-clear :: IO ()-clear = setSGR [Reset] *> hFlush stdout+clear :: MonadIO m => m ()+clear = liftIO $ setSGR [Reset] >> hFlush stdout +putStrLn', putStr' :: MonadIO m => String -> m ()+putStrLn' = liftIO . putStrLn+putStr' = liftIO . putStr+ -- | Clear any SGR settings, flush stdout and print a new line.-clearLn :: IO ()-clearLn = clear *> putStrLn ""+clearLn :: MonadIO m => m ()+clearLn = clear >> putStrLn' "" -- | Use a particular ANSI 'Coloring' to print a string at the terminal (without a new line), -- then clear all ANSI SGR codes and flush stdout.-colorStr :: Coloring -> String -> IO ()+colorStr :: MonadIO m => Coloring -> String -> m () colorStr c s = do applyColoring c- putStr s+ putStr' s clear -- | Use a particular ANSI 'Coloring' to print a string at the terminal, -- then clear all ANSI SGR codes, flush stdout and print a new line.-colorStrLn :: Coloring -> String -> IO ()+colorStrLn :: MonadIO m => Coloring -> String -> m () colorStrLn c s = do applyColoring c- putStr s+ putStr' s clearLn -- | Like 'colorStr' but prints bold text.-boldStr :: Coloring -> String -> IO ()+boldStr :: MonadIO m => Coloring -> String -> m () boldStr c s = do applyColoring c- setSGR [SetConsoleIntensity BoldIntensity]- putStr s+ liftIO $ setSGR [SetConsoleIntensity BoldIntensity]+ putStr' s clear -- | Like 'colorStrLn' but prints bold text.-boldStrLn :: Coloring -> String -> IO ()-boldStrLn c s = do- applyColoring c- setSGR [SetConsoleIntensity BoldIntensity]- putStr s- clearLn+boldStrLn :: MonadIO m => Coloring -> String -> m ()+boldStrLn c s = boldStr c s >> putStrLn' ""
src/System/Console/Ansigraph/Internal/Horizontal.hs view
@@ -11,7 +11,11 @@ import System.Console.Ansigraph.Internal.Core import Data.Complex+import Control.Monad.IO.Class (MonadIO)+-- for GHC <= 7.8+import Control.Applicative + ---- Graphing Infrastructure ---- barChars = "█▇▆▅▄▃▂▁ "@@ -74,13 +78,13 @@ -- | ANSI based display for positive real vectors. Primarily invoked via 'graph', 'graphWith', -- 'animate', 'animateWith'.-displayPV :: GraphSettings -> [Double] -> IO ()+displayPV :: MonadIO m => GraphSettings -> [Double] -> m () displayPV s l = let (rp,_) = renderRV l rcol = realColors s in colorStrLn rcol rp -- | ANSI based display for real vectors. Primarily invoked via 'graph', 'graphWith', -- 'animate', 'animateWith'.-displayRV :: GraphSettings -> [Double] -> IO ()+displayRV :: MonadIO m => GraphSettings -> [Double] -> m () displayRV s l = let (rp,rm) = renderRV l rcol = realColors s in do colorStrLn rcol rp@@ -88,7 +92,7 @@ -- | ANSI based display for complex vectors. Primarily invoked via 'graph', 'graphWith', -- 'animate', 'animateWith'.-displayCV :: GraphSettings -> [Complex Double] -> IO ()+displayCV :: MonadIO m => GraphSettings -> [Complex Double] -> m () displayCV s l = let (rp,rm,ip,im) = renderCV l (rcol,icol) = colorSets s in do colorStrLn rcol rp
src/System/Console/Ansigraph/Internal/Matrix.hs view
@@ -10,7 +10,11 @@ import Data.Complex import Data.List (intersperse)+import Control.Monad.IO.Class (MonadIO, liftIO)+-- for GHC <= 7.8+import Control.Applicative + ---- Matrices ---- mmap :: (a -> b) -> [[a]] -> [[b]]@@ -34,12 +38,12 @@ elemChar (MatElement _ c) = c -putRealElement :: GraphSettings -> MatElement -> IO ()+putRealElement :: MonadIO m => GraphSettings -> MatElement -> m () putRealElement s (MatElement b c) = colorStr clring (c : " ") where clr = if b then realNegColor s else realColor s clring = mkColoring clr (realBG s) -putImagElement :: GraphSettings -> MatElement -> IO ()+putImagElement :: MonadIO m => GraphSettings -> MatElement -> m () putImagElement s (MatElement b c) = colorStr clring $ c : " " where clr = if b then imagNegColor s else imagColor s clring = mkColoring clr (imagBG s)@@ -60,26 +64,26 @@ matShow :: [[Double]] -> [String] matShow = mmap elemChar . matElements -newline = putStrLn ""+newline = putStrLn' "" intersperse' x l = intersperse x l ++ [x] -- | Use ANSI coloring (specified by an 'GraphSettings') to visually display a Real matrix.-displayMat :: GraphSettings -> [[Double]] -> IO ()-displayMat s = sequence_ . concat . intersperse' [newline] . displayRealMat s+displayMat :: MonadIO m => GraphSettings -> [[Double]] -> m ()+displayMat s = liftIO . sequence_ . concat . intersperse' [newline] . displayRealMat s -- | Use ANSI coloring (specified by a 'GraphSettings') to visually display a Real matrix.-displayRealMat :: GraphSettings -> [[Double]] -> [[IO ()]]+displayRealMat :: MonadIO m => GraphSettings -> [[Double]] -> [[m ()]] displayRealMat s = mmap (putRealElement s) . matElements -- | Use ANSI coloring (specified by a 'GraphSettings') to visually display a Real matrix.-displayImagMat :: GraphSettings -> [[Double]] -> [[IO ()]]+displayImagMat :: MonadIO m => GraphSettings -> [[Double]] -> [[m ()]] displayImagMat s = mmap (putImagElement s) . matElements -- | Use ANSI coloring (specified by an 'GraphSettings') to visually display a Complex matrix.-displayCMat :: GraphSettings -> [[Complex Double]] -> IO ()-displayCMat s m = sequence_ . concat . intersperse' [newline] $+displayCMat :: MonadIO m => GraphSettings -> [[Complex Double]] -> m ()+displayCMat s m = liftIO . sequence_ . concat . intersperse' [newline] $ zipWith (\xs ys -> xs ++ putStr " " : ys) (displayRealMat s $ mmap realPart m) (displayImagMat s $ mmap imagPart m)
test/test-ansigraph.hs view
@@ -6,6 +6,9 @@ import System.Console.Ansigraph.Examples (wave) import Data.Complex import Data.Char (isSpace)+-- for GHC <= 7.8+import Control.Applicative+ ---- For horizontal graphing tests ----