packages feed

vty-ui 0.3 → 0.4

raw patch · 12 files changed

+217/−100 lines, 12 filesdep ~containersdep ~vty

Dependency ranges changed: containers, vty

Files

src/Demo.hs view
@@ -148,7 +148,7 @@ handleEvent (EvKey KPageDown []) = modify pageListDown >> continue handleEvent (EvKey (KASCII 'q') []) = stop handleEvent (EvResize _ h) = do-  let newSize = ceiling (0.05 * fromIntegral h)+  let newSize = ceiling ((0.05 :: Double) * fromIntegral h)   when (newSize > 0) $ modify (resizeList newSize)   continue handleEvent _ = continue
src/Graphics/Vty/Widgets/Base.hs view
@@ -8,6 +8,8 @@     , vBox     , hFill     , vFill+    , hLimit+    , vLimit     ) where @@ -144,3 +146,25 @@ -- |An alias for 'vBox' intended as sugar to chain widgets vertically. (<-->) :: Widget -> Widget -> Widget (<-->) = vBox++-- |Impose a maximum horizontal size, in columns, on a 'Widget'.+hLimit :: Int -> Widget -> Widget+hLimit maxWidth w = w { growHorizontal = False+                      , render = restrictedRender+                      }+    where+      restrictedRender sz =+          if region_width sz < fromIntegral maxWidth+          then render w sz+          else render w $ sz `withWidth` fromIntegral maxWidth++-- |Impose a maximum vertical size, in rows, on a 'Widget'.+vLimit :: Int -> Widget -> Widget+vLimit maxHeight w = w { growVertical = False+                       , render = restrictedRender+                       }+    where+      restrictedRender sz =+          if region_height sz < fromIntegral maxHeight+          then render w sz+          else render w $ sz `withHeight` fromIntegral maxHeight
src/Graphics/Vty/Widgets/Borders.hs view
@@ -3,6 +3,8 @@ module Graphics.Vty.Widgets.Borders     ( vBorder     , hBorder+    , vBorderWith+    , hBorderWith     , bordered     ) where@@ -32,23 +34,33 @@  -- |Create a single-row horizontal border. hBorder :: Attr -> Widget-hBorder att = Widget {-                growVertical = False-              , growHorizontal = True-              , primaryAttribute = att-              , withAttribute = hBorder-              , render = \s -> renderImg $ char_fill att '-' (region_width s) 1-              }+hBorder = hBorderWith '-' +-- |Create a single-row horizontal border using the specified+-- attribute and character.+hBorderWith :: Char -> Attr -> Widget+hBorderWith ch att =+    Widget { growVertical = False+           , growHorizontal = True+           , primaryAttribute = att+           , withAttribute = hBorder+           , render = \s -> renderImg $ char_fill att ch (region_width s) 1+           }+ -- |Create a single-column vertical border. vBorder :: Attr -> Widget-vBorder att = Widget {-                growHorizontal = False-              , growVertical = True-              , primaryAttribute = att-              , render = \s -> renderImg $ char_fill att '|' 1 (region_height s)-              , withAttribute = vBorder-              }+vBorder = vBorderWith '|'++-- |Create a single-column vertical border using the specified+-- attribute and character.+vBorderWith :: Char -> Attr -> Widget+vBorderWith ch att =+    Widget { growHorizontal = False+           , growVertical = True+           , primaryAttribute = att+           , render = \s -> renderImg $ char_fill att ch 1 (region_height s)+           , withAttribute = vBorder+           }  -- |Wrap a widget in a bordering box using the specified attribute. bordered :: Attr -> Widget -> Widget
src/Graphics/Vty/Widgets/Composed.hs view
@@ -2,6 +2,7 @@ module Graphics.Vty.Widgets.Composed     ( bottomPadded     , topPadded+    , boxLimit     ) where @@ -11,6 +12,8 @@ import Graphics.Vty.Widgets.Base     ( (<-->)     , vFill+    , vLimit+    , hLimit     )  -- |Add expanding bottom padding to a widget.@@ -20,3 +23,10 @@ -- |Add expanding top padding to a widget. topPadded :: Widget -> Widget topPadded w = vFill (primaryAttribute w) ' ' <--> w++-- |Impose a maximum size (width, height) on a widget.+boxLimit :: Int -- ^Maximum width in columns+         -> Int -- ^Maximum height in rows+         -> Widget+         -> Widget+boxLimit maxWidth maxHeight = vLimit maxHeight . hLimit maxWidth
src/Graphics/Vty/Widgets/Text.hs view
@@ -94,8 +94,7 @@ wrap :: Formatter wrap sz t = t { tokens = newTokens }     where-      newTokens = concatMap (wrapLine attr width) $ tokens t-      attr = defaultAttr t+      newTokens = concatMap (wrapLine width) $ tokens t       width = fromEnum $ region_width sz  -- |A highlight formatter takes a regular expression used to scan the
src/Text/Trans/Tokenize.hs view
@@ -28,7 +28,6 @@ import Data.List     ( inits     , intercalate-    , splitAt     )  -- |The type of textual tokens.  Tokens have an "annotation" type,@@ -63,6 +62,7 @@  -- |Tokenize a string using a default annotation value. tokenize :: String -> a -> [[Token a]]+tokenize [] _ = [[]] tokenize s def = map (tokenize' def) $ splitWith s (== '\n')  tokenize' :: a -> String -> [Token a]@@ -101,18 +101,21 @@       passing = dropWhile ((> width) . sum) cases  -- |Given a list of tokens without Newlines, (potentially) wrap the--- list to the specified column width, using the specified default--- annotation.-wrapLine :: (Eq a) => a -> Int -> [Token a] -> [[Token a]]-wrapLine _ _ [] = []-wrapLine def width ts =+-- list to the specified column width.+wrapLine :: Int -> [Token a] -> [[Token a]]+wrapLine _ [] = []+wrapLine width ts =     -- If there were no passing cases, that means the line can't be     -- wrapped so just return it as-is (e.g., one long unbroken     -- string).  Otherwise, package up the acceptable tokens and     -- continue wrapping.     if null passing     then [ts]-    else these : wrapLine def width those+    else if null these+         then if length those' == 1+              then [those']+              else [head those'] : (wrapLine width $ tail those')+         else these : wrapLine width those     where       lengths = map (length . tokenString) ts       cases = reverse $ inits lengths
test/TestDriver.hs view
@@ -2,83 +2,16 @@ module Main where  import System.Exit ( exitFailure, exitSuccess )--import Data.Word ( Word8 )-import Data.Char ( isPrint ) import Test.QuickCheck import Test.QuickCheck.Test-import Control.Applicative ( (<$>), (<*>), pure ) -import Graphics.Vty-import Graphics.Vty.Widgets.Text-import Graphics.Vty.Widgets.Rendering--import Text.Trans.Tokenize--instance (Arbitrary a, Eq a) => Arbitrary (MaybeDefault a) where-    arbitrary = oneof [ pure Default-                      , pure KeepCurrent-                      , SetTo <$> arbitrary-                      ]--instance Arbitrary Word8 where-    arbitrary = toEnum <$> choose (0, 255)--instance Arbitrary Color where-    arbitrary = oneof [ ISOColor <$> arbitrary-                      , Color240 <$> arbitrary-                      ]--instance Arbitrary Attr where-    arbitrary = Attr <$> arbitrary <*> arbitrary <*> arbitrary--instance Arbitrary DisplayRegion where-    arbitrary = DisplayRegion <$> coord <*> coord-        where-          coord = sized $ \n -> fromIntegral <$> choose (0, n)--instance (Arbitrary a) =>  Arbitrary (Token a) where-    arbitrary = oneof [ Whitespace <$> ws <*> arbitrary-                      , Token <$> s <*> arbitrary-                      ]-        where-          ws = oneof [ pure " ", pure "\t" ]-          s = replicate <$> choose (1, 10) <*> pure 'a'--toImage :: DisplayRegion -> Widget -> Image-toImage sz w = fst $ mkImageSize upperLeft sz w-    where upperLeft = DisplayRegion 0 0--textSize :: Property-textSize =-    property $ forAll textString $ \str attr sz ->-        let img = toImage sz $ simpleText attr str-        in-          if null str || region_height sz == 0 || region_width sz == 0-          then image_height img == 0 && image_width img == 0-          else image_width img <= (toEnum $ length str) && image_height img <= 1--imageSize :: Widget -> DisplayRegion -> Bool-imageSize w sz =-    image_width img <= region_width sz && image_height img <= region_height sz-        where-          img = toImage sz w--textString :: Gen String-textString = listOf (arbitrary `suchThat` (\c -> isPrint c && c /= '\n'))--tokenGen :: Gen [[Token ()]]-tokenGen = listOf $ listOf arbitrary+import qualified Tests.Text as Text+import qualified Tests.Tokenize as Tokenize  tests :: [Property]-tests = [ textSize-        , property $ forAll textString $-                       \str attr -> imageSize (simpleText attr str)-        -- Round-trip property for token serialization and string-        -- tokenization.-        , property $ forAll tokenGen $-                       \ts -> serialize ts == (serialize $ tokenize (serialize ts) ())-        ]+tests = concat [ Text.tests+               , Tokenize.tests+               ]  main :: IO () main = do
+ test/src/Tests/Instances.hs view
@@ -0,0 +1,30 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}+module Tests.Instances where++import Test.QuickCheck+import Control.Applicative ( (<*>), (<$>), pure )+import Data.Word ( Word8 )++import Graphics.Vty++instance (Arbitrary a, Eq a) => Arbitrary (MaybeDefault a) where+    arbitrary = oneof [ pure Default+                      , pure KeepCurrent+                      , SetTo <$> arbitrary+                      ]++instance Arbitrary Word8 where+    arbitrary = toEnum <$> choose (0, 255)++instance Arbitrary Color where+    arbitrary = oneof [ ISOColor <$> arbitrary+                      , Color240 <$> arbitrary+                      ]++instance Arbitrary Attr where+    arbitrary = Attr <$> arbitrary <*> arbitrary <*> arbitrary++instance Arbitrary DisplayRegion where+    arbitrary = DisplayRegion <$> coord <*> coord+        where+          coord = sized $ \n -> fromIntegral <$> choose (0, n)
+ test/src/Tests/Text.hs view
@@ -0,0 +1,28 @@+module Tests.Text where++import Test.QuickCheck+import Data.Char ( isPrint )++import Graphics.Vty+import Graphics.Vty.Widgets.Text++import Tests.Util+import Tests.Instances ()++textSize :: Property+textSize =+    property $ forAll textString $ \str attr sz ->+        let img = toImage sz $ simpleText attr str+        in+          if null str || region_height sz == 0 || region_width sz == 0+          then image_height img == 0 && image_width img == 0+          else image_width img <= (toEnum $ length str) && image_height img <= 1++textString :: Gen String+textString = listOf (arbitrary `suchThat` (\c -> isPrint c && c /= '\n'))++tests :: [Property]+tests = [ label "textSize" textSize+        , label "imageSize" $ property $ forAll textString $+                    \str attr -> imageSize (simpleText attr str)+        ]
+ test/src/Tests/Tokenize.hs view
@@ -0,0 +1,58 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}+module Tests.Tokenize where++import Data.Char ( isPrint )+import Control.Applicative ( (<$>), (<*>), pure )+import Test.QuickCheck++import Text.Trans.Tokenize++instance (Arbitrary a) => Arbitrary (Token a) where+    arbitrary = oneof [ Whitespace <$> ws <*> arbitrary+                      , Token <$> s <*> arbitrary+                      ]+        where+          ws = oneof [ pure " ", pure "\t" ]+          s = replicate <$> choose (1, 10) <*> pure 'a'++tokenGen :: Gen [[Token ()]]+tokenGen = listOf $ listOf arbitrary++lineGen :: Gen [Token ()]+lineGen = listOf1 arbitrary++stringGen :: Gen String+stringGen = listOf (arbitrary `suchThat` (\c -> isPrint c))++checkToken :: Token a -> Bool+checkToken (Whitespace s _) = all (`elem` " \t") s+checkToken (Token s _) = all (not . (`elem` " \t")) s++count :: (a -> Bool) -> [a] -> Int+count _ [] = 0+count f (a:as) = count f as + if f a then 1 else 0++numNewlines :: String -> Int+numNewlines = count (== '\n')++tests :: [Property]+tests = [ label "tokenizeConsistency" $ property $ forAll tokenGen $+                    \ts -> serialize ts == (serialize $ tokenize (serialize ts) ())+        , label "tokenizeContents" $ property $ forAll stringGen $+                    \s -> all (all checkToken) $ tokenize s undefined+        , label "tokenizeNewlines" $ property $ forAll stringGen $+                    \s -> numNewlines s + 1 == (length $ tokenize s undefined)+        , label "truncLine" $ property $ forAll lineGen $+                    \ts -> forAll (arbitrary :: Gen (Positive Int)) $+                    \width -> length (truncLine (fromIntegral width) ts) <=+                              (fromIntegral width)+        -- wrapping: a single line wrapped should always result in+        -- lines that are no greater than the wrapping width, unless+        -- they have a single token.+        , label "wrapLine" $ property $ forAll lineGen $+                    \ts -> forAll (choose (0, length ts + 1)) $+                    \width -> let ls = wrapLine w ts+                                  w = fromIntegral width+                                  f l = length (serialize [l]) <= w || length l == 1+                              in all f ls+        ]
+ test/src/Tests/Util.hs view
@@ -0,0 +1,14 @@+module Tests.Util where++import Graphics.Vty+import Graphics.Vty.Widgets.Rendering++toImage :: DisplayRegion -> Widget -> Image+toImage sz w = fst $ mkImageSize upperLeft sz w+    where upperLeft = DisplayRegion 0 0++imageSize :: Widget -> DisplayRegion -> Bool+imageSize w sz =+    image_width img <= region_width sz && image_height img <= region_height sz+        where+          img = toImage sz w
vty-ui.cabal view
@@ -1,5 +1,5 @@ Name:                vty-ui-Version:             0.3+Version:             0.4 Synopsis:            A user interface composition library for Vty Description:         An extensible library of user interface widgets                      for composing and laying out Vty user interfaces.@@ -25,8 +25,8 @@ Library   Build-Depends:     base >= 4 && < 5,-    vty >= 4.0 && < 4.1,-    containers >= 0.2 && < 0.3,+    vty >= 4.0 && < 4.5,+    containers >= 0.2 && < 0.4,     pcre-light >= 0.3 && < 0.4    GHC-Options:       -Wall@@ -52,8 +52,14 @@   if !flag(testing)     Buildable:     False   end-  Hs-Source-Dirs:  src,test+  Hs-Source-Dirs:  src,test,test/src   Main-is:         TestDriver.hs++  Other-Modules:+        Tests.Instances+        Tests.Util+        Tests.Text+        Tests.Tokenize  Executable vty-ui-demo   Hs-Source-Dirs:  src