on master help sign in
Merge branch 'master' of github.com:coreyoconnor/vty
commitce5b5f40f5e2d1969d5f5694856aba0140cd6bea authorCorey O'Connor <coreyoconnor@gmail.com> dateFri 25 Oct 2013, 00:25 (13 years ago) parent2492366f6d25d6
32 files changed+531−352
.travis.yml+3 src/Data/Terminfo/Eval.hs−1 src/Data/Terminfo/Parse.hs−1 src/Graphics/Vty.hs+1−1 src/Graphics/Vty/Debug.hs−1 src/Graphics/Vty/Debug/Image.hs−1 src/Graphics/Vty/Input.hs+64−118 src/Graphics/Vty/Input/Data.hs+98−58 src/Graphics/Vty/Input/Internal.hs+83 src/Graphics/Vty/PictureToSpans.hs−1 src/Graphics/Vty/Span.hs−1 src/Graphics/Vty/Terminal.hs−1 src/Graphics/Vty/Terminal/Interface.hs−1 src/Graphics/Vty/Terminal/MacOSX.hs−2 src/Graphics/Vty/Terminal/TerminfoBased.hs−2 src/Graphics/Vty/Terminal/XTermColor.hs−5 test/Rouge.hs+108 test/Test.hs−44 test/Verify.hs+4−1 test/Verify/Data/Terminfo/Parse.hs−1 test/Verify/Graphics/Vty/DisplayRegion.hs−1 test/Verify/Graphics/Vty/Terminal.hs+4−2 test/VerifyEmptyImageProps.hs−1 test/VerifyEvalTerminfoCaps.hs+1−42 test/VerifyImageOps.hs−1 test/VerifyParseTerminfoCaps.hs+2−43 test/VerifyTerminal.hs−1 test/VerifyUsingMockInput.hs+106−10 test/VerifyUsingMockTerminal.hs−1 test/benchmark.hs−1 test/interactive_terminal_test.hs−1 vty.cabal+57−8
.travis.ymlnew file+3
@@ -0,0 +1,3 @@
1+language: haskell
2+notifications:
3+ email: false
src/Data/Terminfo/Eval.hs−1
@@ -1,6 +1,5 @@
11{-# LANGUAGE MagicHash #-}
22{-# LANGUAGE BangPatterns #-}
3−{-# LANGUAGE ScopedTypeVariables #-}
43{-# LANGUAGE RecordWildCards #-}
54{-# LANGUAGE FlexibleContexts #-}
65{-# LANGUAGE NoMonomorphismRestriction #-}
src/Data/Terminfo/Parse.hs−1
@@ -1,4 +1,3 @@
1−{-# LANGUAGE ScopedTypeVariables #-}
21{-# LANGUAGE BangPatterns #-}
32{-# LANGUAGE FlexibleContexts #-}
43{-# LANGUAGE NoMonomorphismRestriction #-}
src/Graphics/Vty.hs+1−1
@@ -73,7 +73,7 @@ data Vty = Vty
7373-- | Set up the state object for using vty. At most one state object should be
7474-- created at a time.
7575mkVty :: IO Vty
76−mkVty = mkVtyEscDelay 0
76+mkVty = mkVtyEscDelay defaultEscDelay
7777
7878-- | Set up the state object for using vty. At most one state object should be
7979-- created at a time. The delay, in microseconds, specifies the period of time to wait for a key
src/Graphics/Vty/Debug.hs−1
@@ -1,5 +1,4 @@
11-- Copyright 2009-2010 Corey O'Connor
2−{-# LANGUAGE ScopedTypeVariables #-}
32module Graphics.Vty.Debug ( module Graphics.Vty.Debug
43 , module Graphics.Vty.Debug.Image
54 )
src/Graphics/Vty/Debug/Image.hs−1
@@ -1,4 +1,3 @@
1−{-# LANGUAGE ScopedTypeVariables #-}
21module Graphics.Vty.Debug.Image where
32
43import Graphics.Vty.Image
src/Graphics/Vty/Input.hs+64−118
@@ -1,28 +1,21 @@
1−{-# LANGUAGE ScopedTypeVariables #-}
21-- Copyright 2009-2010 Corey O'Connor
3−{-# OPTIONS_GHC -Wall #-}
4−{-# LANGUAGE ForeignFunctionInterface #-}
52module Graphics.Vty.Input ( Key(..)
63 , Modifier(..)
74 , Button(..)
85 , Event(..)
96 , initTermInput
7+ , defaultEscDelay
108 )
119 where
1210
1311import Graphics.Vty.Input.Data
12+import Graphics.Vty.Input.Internal
13+import Graphics.Vty.Input.Terminfo
1414
1515import Data.Char
16−import Data.Maybe ( mapMaybe
17− )
18−import Data.List( inits )
1916import Data.Word
20−import qualified Data.Map as M( fromList, lookup )
21−import qualified Data.Set as S( fromList, member )
2217
23−import Codec.Binary.UTF8.Generic (decode)
24−
25−import Control.Monad (when)
18+import Control.Monad (when, void)
2619import Control.Concurrent
2720import Control.Exception
2821
@@ -31,63 +24,54 @@ import System.Console.Terminfo
3124import System.Posix.Signals.Exts
3225import System.Posix.Terminal
3326import System.Posix.IO ( stdInput
34− ,fdReadBuf
35− ,setFdOption
36− ,FdOption(..)
27+ , fdReadBuf
28+ , setFdOption
29+ , FdOption(..)
3730 )
3831
3932import Foreign ( alloca, poke, peek, Ptr )
4033
34+defaultEscDelay :: Int
35+defaultEscDelay = 0
36+
4137-- | Set up the terminal for input. Returns a function which reads key
4238-- events, and a function for shutting down the terminal access.
4339initTermInput :: Int -> Terminal -> IO (IO Event, IO ())
4440initTermInput escDelay terminal = do
45− eventChannel <- newChan
46− inputChannel <- newChan
47− hadInput <- newEmptyMVar
48− oattr <- getTerminalAttributes stdInput
49− let nattr = foldl withoutMode oattr [ StartStopOutput, KeyboardInterrupts
41+ eventChannel <- newChan
42+ inputChannel <- newChan
43+ hadInput <- newEmptyMVar
44+ oattr <- getTerminalAttributes stdInput
45+ let nattr = foldl withoutMode oattr [ StartStopOutput, KeyboardInterrupts
5046 , EnableEcho, ProcessInput, ExtendedFunctions
5147 ]
52− setTerminalAttributes stdInput nattr Immediately
53− set_term_timing
54− let inputToEventThread :: IO ()
55− inputToEventThread = loop []
56− where loop kb = case (classify kb) of
57− Prefix -> do c <- readChan inputChannel
58− loop (kb ++ [c])
59− Invalid -> do c <- readChan inputChannel
60− loop [c]
61− MisPfx k m s -> writeChan eventChannel (EvKey k m) >> loop s
62− Valid k m -> writeChan eventChannel (EvKey k m) >> loop ""
63−
64− finishAtomicInput = writeChan inputChannel '\xFFFE'
65−
66− inputThread :: IO ()
67− inputThread = do
68− _ <- alloca $ \(input_buffer :: Ptr Word8) -> do
69− let loop = do
70− setFdOption stdInput NonBlockingRead False
71− threadWaitRead stdInput
72− setFdOption stdInput NonBlockingRead True
73− _ <- try readAll :: IO (Either IOException ())
74− when (escDelay == 0) finishAtomicInput
75− loop
76− readAll = do
77− poke input_buffer 0
78− bytes_read <- fdReadBuf stdInput input_buffer 1
79− input_char <- fmap (chr . fromIntegral) $ peek input_buffer
80− when (bytes_read > 0) $ do
81− _ <- tryPutMVar hadInput () -- signal input
82− writeChan inputChannel input_char
83− readAll
84− loop
85− return ()
86−
87− -- | If there is no input for some time, this thread puts '\xFFFE' in the
88− -- inputChannel.
89− noInputThread :: IO ()
90− noInputThread = when (escDelay > 0) loop
48+ setTerminalAttributes stdInput nattr Immediately
49+ set_term_timing
50+ let finishAtomicInput = writeChan inputChannel '\xFFFE'
51+ inputThread :: IO ()
52+ inputThread = do
53+ _ <- alloca $ \(input_buffer :: Ptr Word8) -> do
54+ let loop = do
55+ setFdOption stdInput NonBlockingRead False
56+ threadWaitRead stdInput
57+ setFdOption stdInput NonBlockingRead True
58+ _ <- try readAll :: IO (Either IOException ())
59+ when (escDelay == 0) finishAtomicInput
60+ loop
61+ readAll = do
62+ poke input_buffer 0
63+ bytes_read <- fdReadBuf stdInput input_buffer 1
64+ input_char <- fmap (chr . fromIntegral) $ peek input_buffer
65+ when (bytes_read > 0) $ do
66+ _ <- tryPutMVar hadInput () -- signal input
67+ writeChan inputChannel input_char
68+ readAll
69+ loop
70+ return ()
71+ -- | If there is no input for some time, this thread puts '\xFFFE' in the
72+ -- inputChannel.
73+ noInputThread :: IO ()
74+ noInputThread = when (escDelay > 0) loop
9175 where loop = do
9276 takeMVar hadInput -- wait for some input
9377 threadDelay escDelay -- microseconds
@@ -97,64 +81,26 @@ initTermInput escDelay terminal = do
9781 finishAtomicInput
9882 loop
9983
84+ caps_legacy_table = map_to_legacy_table $ caps_classify_table terminal keys_from_caps_table
85+ term_event_classify_table = concat $ caps_legacy_table : ansi_classify_table
86+ term_event_classifier = classify term_event_classify_table
87+
88+ eventThreadId <- forkIO $ void $ inputToEventThread term_event_classifier inputChannel eventChannel
89+ inputThreadId <- forkIO $ inputThread
90+ noInputThreadId <- forkIO $ noInputThread
91+ let pokeIO = Catch $ do
92+ let e = error "(getsize in input layer)"
93+ setTerminalAttributes stdInput nattr Immediately
94+ writeChan eventChannel (EvResize e e)
95+ _ <- installHandler windowChange pokeIO Nothing
96+ _ <- installHandler continueProcess pokeIO Nothing
97+ -- TODO(corey): killThread is a bit risky for my tastes.
98+ let uninit = do
99+ killThread eventThreadId
100+ killThread inputThreadId
101+ killThread noInputThreadId
102+ _ <- installHandler windowChange Ignore Nothing
103+ _ <- installHandler continueProcess Ignore Nothing
104+ setTerminalAttributes stdInput oattr Immediately
105+ return (readChan eventChannel, uninit)
100106
101− compile :: [[([Char],(Key,[Modifier]))]] -> [Char] -> KClass
102− compile lst = cl' where
103− lst' = concat lst
104− pfx = S.fromList $ concatMap (init . inits . fst) $ lst'
105− mlst = M.fromList lst'
106− cl' str = case S.member str pfx of
107− True -> Prefix
108− False -> case M.lookup str mlst of
109− Just (k,m) -> Valid k m
110− Nothing -> case head $ mapMaybe (\s -> (,) s `fmap` M.lookup s mlst) $ init $ inits str of
111− (s,(k,m)) -> MisPfx k m (drop (length s) str)
112−
113− -- ANSI specific bits
114−
115−
116− classify, classifyTab :: [Char] -> KClass
117−
118− -- As soon as
119− classify "\xFFFE" = Invalid
120− classify s@(c:_) | ord c >= 0xC2 =
121− if utf8Length (ord c) > length s then Prefix else classifyUtf8 s -- beginning of an utf8 sequence
122− classify other = classifyTab other
123−
124− classifyUtf8 s = case decode ((map (fromIntegral . ord) s) :: [Word8]) of
125− Just (unicodeChar, _) -> Valid (KASCII unicodeChar) []
126− _ -> Invalid -- something bad happened; just ignore and continue.
127−
128− classifyTab = compile (caps_classify_table : ansi_classify_table)
129−
130− caps_classify_table
131− = map_to_legacy_table [(x,y) | (Just x,y) <- map (first (getCapability terminal . tiGetStr)) $ caps_table]
132−
133− eventThreadId <- forkIO $ inputToEventThread
134− inputThreadId <- forkIO $ inputThread
135− noInputThreadId <- forkIO $ noInputThread
136− let pokeIO = (Catch $ do let e = error "(getsize in input layer)"
137− setTerminalAttributes stdInput nattr Immediately
138− writeChan eventChannel (EvResize e e))
139− _ <- installHandler windowChange pokeIO Nothing
140− _ <- installHandler continueProcess pokeIO Nothing
141− -- TODO(corey): killThread is a bit risky for my tastes.
142− let uninit = do killThread eventThreadId
143− killThread inputThreadId
144− killThread noInputThreadId
145− _ <- installHandler windowChange Ignore Nothing
146− _ <- installHandler continueProcess Ignore Nothing
147− setTerminalAttributes stdInput oattr Immediately
148− return (readChan eventChannel, uninit)
149−
150−first :: (a -> b) -> (a,c) -> (b,c)
151−first f (x,y) = (f x, y)
152−
153−utf8Length :: (Num t, Ord a, Num a) => a -> t
154−utf8Length c
155− | c < 0x80 = 1
156− | c < 0xE0 = 2
157− | c < 0xF0 = 3
158− | otherwise = 4
159−
160−foreign import ccall "vty_set_term_timing" set_term_timing :: IO ()
src/Graphics/Vty/Input/Data.hs+98−58
@@ -1,15 +1,13 @@
1−{-# LANGUAGE ScopedTypeVariables #-}
2−{-# LANGUAGE ForeignFunctionInterface #-}
31-- Copyright Corey O'Connor
42module Graphics.Vty.Input.Data where
53
6−-- |Representations of non-modifier keys.
4+-- | Representations of non-modifier keys.
75data Key = KEsc | KFun Int | KBackTab | KPrtScr | KPause | KASCII Char | KBS | KIns
86 | KHome | KPageUp | KDel | KEnd | KPageDown | KBegin | KNP5 | KUp | KMenu
97 | KLeft | KDown | KRight | KEnter
108 deriving (Eq,Show,Ord)
119
12−-- |Modifier keys. Key codes are interpreted such that users are more likely to
10+-- | Modifier keys. Key codes are interpreted such that users are more likely to
1311-- have Meta than Alt; for instance on the PC Linux console, 'MMeta' will
1412-- generally correspond to the physical Alt key.
1513data Modifier = MShift | MCtrl | MMeta | MAlt
@@ -24,17 +22,24 @@ data Event = EvKey Key [Modifier] | EvMouse Int Int Button [Modifier]
2422 | EvResize Int Int
2523 deriving (Eq,Show,Ord)
2624
27−data KClass = Valid Key [Modifier] | Invalid | Prefix | MisPfx Key [Modifier] [Char]
25+data KClass
26+ = Valid Key [Modifier]
27+ | Invalid
28+ | EndLoop
29+ | Prefix
30+ | MisPfx Key [Modifier] [Char]
2831 deriving(Show)
2932
30−map_to_legacy_table :: [(String, Event)] -> [(String, (Key, [Modifier]))]
33+type ClassifyTable = [(String, (Key, [Modifier]))]
34+
35+map_to_legacy_table :: [(String, Event)] -> ClassifyTable
3136map_to_legacy_table = map f
3237 where f (s, EvKey k mods) = (s, (k, mods))
3338 f _ = error "no mapping for mouse or resize events"
3439
3540-- | classify table directly generated from terminfo cap strings
36−caps_table :: [(String, Event)]
37−caps_table =
41+keys_from_caps_table :: [(String, Event)]
42+keys_from_caps_table =
3843 [ ("khome", EvKey KHome [])
3944 , ("kend", EvKey KEnd [])
4045 , ("cbt", EvKey KBackTab [])
@@ -46,62 +51,97 @@ caps_table =
4651 , ("kRIT", EvKey KRight [MShift])
4752 ]
4853
54+nav_keys_0 :: ClassifyTable
55+nav_keys_0 =
56+ [ k "G" KNP5
57+ , k "P" KPause
58+ , k "A" KUp
59+ , k "B" KDown
60+ , k "C" KRight
61+ , k "D" KLeft
62+ , k "H" KHome
63+ , k "F" KEnd
64+ , k "E" KBegin
65+ ]
66+ where k c s = ("\ESC["++c,(s,[]))
4967
50−-- | classify table for ANSI terminals
51−ansi_classify_table :: [[([Char], (Key, [Modifier]))]]
52−ansi_classify_table =
53− [ let k c s = ("\ESC["++c,(s,[])) in [ k "G" KNP5
54− , k "P" KPause
55− , k "A" KUp
56− , k "B" KDown
57− , k "C" KRight
58− , k "D" KLeft
59− , k "H" KHome
60− , k "F" KEnd
61− , k "E" KBegin
62− ],
63−
64− -- Support for arrows and KHome/KEnd
68+-- Support for arrows and KHome/KEnd
69+nav_keys_1 :: ClassifyTable
70+nav_keys_1 =
6571 [("\ESC[" ++ charCnt ++ show mc++c,(s,m))
6672 | charCnt <- ["1;", ""], -- we can have a count or not
6773 (m,mc) <- [([MShift],2::Int), ([MCtrl],5), ([MMeta],3),
6874 ([MShift, MCtrl],6), ([MShift, MMeta],4)], -- modifiers and their codes
6975 (c,s) <- [("A", KUp), ("B", KDown), ("C", KRight), ("D", KLeft), ("H", KHome), ("F", KEnd)] -- directions and their codes
70− ],
71−
72− let k n s = ("\ESC["++show n++"~",(s,[]))
73− in zipWith k [2::Int,3,5,6,1,4]
74− [KIns,KDel,KPageUp,KPageDown,KHome,KEnd],
75−
76− let k n s = ("\ESC["++show n++";5~",(s,[MCtrl]))
77− in zipWith k [2::Int,3,5,6,1,4]
78− [KIns,KDel,KPageUp,KPageDown,KHome,KEnd],
79−
80− -- Support for simple characters.
81− [ (x:[],(KASCII x,[])) | x <- map toEnum [0..255] ],
82−
83− -- Support for function keys (should use terminfo)
84− [ ("\ESC[["++[toEnum(64+i)],(KFun i,[])) | i <- [1..5] ],
85− let f ff nrs m = [ ("\ESC["++show n++"~",(KFun (n-(nrs!!0)+ff), m)) | n <- nrs ] in
86− concat [ f 6 [17..21] [], f 11 [23,24] [], f 1 [25,26] [MShift], f 3 [28,29] [MShift], f 5 [31..34] [MShift] ],
87− [ ('\ESC':[x],(KASCII x,[MMeta])) | x <- '\ESC':'\t':[' ' .. '\DEL'] ],
88−
89− -- Ctrl+Char
90− [ ([toEnum x],(KASCII y,[MCtrl]))
91− | (x,y) <- zip ([0..31]) ('@':['a'..'z']++['['..'_']),
92− y /= 'i' -- Resolve issue #3 where CTRL-i hides TAB.
93− ],
94−
95− -- Ctrl+Meta+Char
96− [ ('\ESC':[toEnum x],(KASCII y,[MMeta,MCtrl])) | (x,y) <- zip [0..31] ('@':['a'..'z']++['['..'_']) ],
76+ ]
77+
78+nav_keys_2 :: ClassifyTable
79+nav_keys_2 =
80+ let k n s = ("\ESC["++show n++"~",(s,[]))
81+ in zipWith k [2::Int,3,5,6,1,4]
82+ [KIns,KDel,KPageUp,KPageDown,KHome,KEnd]
83+
84+nav_keys_3 :: ClassifyTable
85+nav_keys_3 =
86+ let k n s = ("\ESC["++show n++";5~",(s,[MCtrl]))
87+ in zipWith k [2::Int,3,5,6,1,4]
88+ [KIns,KDel,KPageUp,KPageDown,KHome,KEnd]
89+
90+-- Support for simple characters.
91+-- we limit to < 0xC1. The UTF8 sequence detector will catch all values 0xC2 and above before this
92+-- classify table is reached.
93+simple_chars :: ClassifyTable
94+simple_chars = [ (x:[],(KASCII x,[])) | x <- map toEnum [0..0xC1] ]
95+
96+-- Support for function keys (should use terminfo)
97+function_keys_0 :: ClassifyTable
98+function_keys_0 = [ ("\ESC[["++[toEnum(64+i)],(KFun i,[])) | i <- [1..5] ]
99+
100+function_keys_1 :: ClassifyTable
101+function_keys_1 =
102+ let f ff nrs m = [ ("\ESC["++show n++"~",(KFun (n-(nrs!!0)+ff), m)) | n <- nrs ] in
103+ concat [ f 6 [17..21] [], f 11 [23,24] [], f 1 [25,26] [MShift], f 3 [28,29] [MShift], f 5 [31..34] [MShift] ]
104+
105+function_keys_2 :: ClassifyTable
106+function_keys_2 = [ ('\ESC':[x],(KASCII x,[MMeta])) | x <- '\ESC':'\t':[' ' .. '\DEL'] ]
107+
108+-- Ctrl+Char
109+ctrl_char_keys :: ClassifyTable
110+ctrl_char_keys =
111+ [ ([toEnum x],(KASCII y,[MCtrl]))
112+ | (x,y) <- zip ([0..31]) ('@':['a'..'z']++['['..'_']),
113+ y /= 'i' -- Resolve issue #3 where CTRL-i hides TAB.
114+ ]
97115
98− -- Special support
99− [ -- special support for ESC
100− ("\ESC",(KEsc,[])) , ("\ESC\ESC",(KEsc,[MMeta])),
116+-- Ctrl+Meta+Char
117+ctrl_meta_keys :: ClassifyTable
118+ctrl_meta_keys =
119+ [ ('\ESC':[toEnum x],(KASCII y,[MMeta,MCtrl])) | (x,y) <- zip [0..31] ('@':['a'..'z']++['['..'_']) ]
120+
121+-- Special support
122+special_support_keys :: ClassifyTable
123+special_support_keys =
124+ [ -- special support for ESC
125+ ("\ESC",(KEsc,[])) , ("\ESC\ESC",(KEsc,[MMeta]))
126+ -- Special support for backspace
127+ , ("\DEL",(KBS,[])), ("\ESC\DEL",(KBS,[MMeta]))
128+ -- Special support for Enter
129+ , ("\ESC\^J",(KEnter,[MMeta])), ("\^J",(KEnter,[]))
130+ ]
101131
102− -- Special support for backspace
103− ("\DEL",(KBS,[])), ("\ESC\DEL",(KBS,[MMeta])),
132+-- | classify table for ANSI terminals
133+ansi_classify_table :: [ClassifyTable]
134+ansi_classify_table =
135+ [ nav_keys_0
136+ , nav_keys_1
137+ , nav_keys_2
138+ , nav_keys_3
139+ , simple_chars
140+ , function_keys_0
141+ , function_keys_1
142+ , function_keys_2
143+ , ctrl_char_keys
144+ , ctrl_meta_keys
145+ , special_support_keys
146+ ]
104147
105− -- Special support for Enter
106− ("\ESC\^J",(KEnter,[MMeta])), ("\^J",(KEnter,[])) ]
107− ]
src/Graphics/Vty/Input/Internal.hsnew file+83
@@ -0,0 +1,83 @@
1+module Graphics.Vty.Input.Internal where
2+
3+import Graphics.Vty.Input.Data
4+
5+import Codec.Binary.UTF8.Generic (decode)
6+import Control.Concurrent
7+
8+import Data.Char
9+import Data.List( inits )
10+import qualified Data.Map as M( fromList, lookup )
11+import Data.Maybe ( mapMaybe )
12+import qualified Data.Set as S( fromList, member )
13+import Data.Word
14+
15+inputToEventThread :: (String -> KClass) -> Chan Char -> Chan Event -> IO ()
16+inputToEventThread classifier inputChannel eventChannel = loop []
17+ where loop kb = case (classifier kb) of
18+ Prefix -> do
19+ c <- readChan inputChannel
20+ if c == '\xFFFD'
21+ then return ()
22+ else loop (kb ++ [c])
23+ Invalid -> do
24+ c <- readChan inputChannel
25+ if c == '\xFFFD'
26+ then return ()
27+ else loop [c]
28+ EndLoop -> return ()
29+ MisPfx k m s -> writeChan eventChannel (EvKey k m) >> loop s
30+ Valid k m -> writeChan eventChannel (EvKey k m) >> loop ""
31+
32+compile :: ClassifyTable -> [Char] -> KClass
33+compile table = cl' where
34+ -- take all prefixes and create a set of these
35+ prefix_set = S.fromList $ concatMap (init . inits . fst) $ table
36+ -- create a map from strings to event
37+ event_for_input = flip M.lookup (M.fromList table)
38+ cl' [] = Prefix
39+ cl' input_block = case S.member input_block prefix_set of
40+ True -> Prefix
41+ -- if the input_block is exactly what is expected for an event then consume the whole
42+ -- block and return the event
43+ False -> case event_for_input input_block of
44+ Just (k,m) -> Valid k m
45+ -- look up progressively large prefixes of the input block until an event is found
46+ -- H: There will always be one match. The prefix_set contains, by definition, all
47+ -- prefixes of an event.
48+ Nothing ->
49+ let input_prefixes = init $ inits input_block
50+ in case mapMaybe (\s -> (,) s `fmap` event_for_input s) input_prefixes of
51+ (s,(k,m)) : _ -> MisPfx k m (drop (length s) input_block)
52+ [] -> error $ "vty internal inconsistency - "
53+ ++ "input not a prefix nor contains any event data "
54+ ++ show input_block
55+
56+classify, classifyTab :: ClassifyTable -> [Char] -> KClass
57+
58+-- As soon as
59+classify _table "\xFFFD" = EndLoop
60+classify _table "\xFFFE" = Invalid
61+classify _table s@(c:_) | ord c >= 0xC2
62+ = if utf8Length (ord c) > length s then Prefix else classifyUtf8 s -- beginning of an utf8 sequence
63+classify table other
64+ = classifyTab table other
65+
66+classifyUtf8 :: [Char] -> KClass
67+classifyUtf8 s = case decode ((map (fromIntegral . ord) s) :: [Word8]) of
68+ Just (unicodeChar, _) -> Valid (KASCII unicodeChar) []
69+ _ -> Invalid -- something bad happened; just ignore and continue.
70+
71+classifyTab table = compile table
72+
73+first :: (a -> b) -> (a,c) -> (b,c)
74+first f (x,y) = (f x, y)
75+
76+utf8Length :: (Num t, Ord a, Num a) => a -> t
77+utf8Length c
78+ | c < 0x80 = 1
79+ | c < 0xE0 = 2
80+ | c < 0xF0 = 3
81+ | otherwise = 4
82+
83+foreign import ccall "vty_set_term_timing" set_term_timing :: IO ()
src/Graphics/Vty/PictureToSpans.hs−1
@@ -3,7 +3,6 @@
33{-# LANGUAGE TemplateHaskell #-}
44{-# LANGUAGE BangPatterns #-}
55{-# LANGUAGE ExistentialQuantification #-}
6−{-# LANGUAGE ScopedTypeVariables #-}
76{-# LANGUAGE NamedFieldPuns #-}
87{- | Transforms an image into rows of operations.
98 -}
src/Graphics/Vty/Span.hs−1
@@ -2,7 +2,6 @@
22{-# LANGUAGE BangPatterns #-}
33{-# LANGUAGE NamedFieldPuns #-}
44{-# LANGUAGE GADTs #-}
5−{-# LANGUAGE ScopedTypeVariables #-}
65{- | A picture is translated into a sequences of state changes and character spans.
76 - State changes are currently limited to new attribute values. The attribute is applied to all
87 - following spans. Including spans of the next row. The nth element of the sequence represents the
src/Graphics/Vty/Terminal.hs−1
@@ -18,7 +18,6 @@
1818-- control codes as possible.
1919--
2020-- Copyright 2009-2010 Corey O'Connor
21−{-# LANGUAGE ScopedTypeVariables #-}
2221module Graphics.Vty.Terminal ( module Graphics.Vty.Terminal
2322 , Terminal(..) -- \todo hide constructors
2423 , AssumedState(..)
src/Graphics/Vty/Terminal/Interface.hs−1
@@ -2,7 +2,6 @@
22-- General philosophy is: MonadIO is for equations exposed to clients.
33{-# LANGUAGE BangPatterns #-}
44{-# LANGUAGE RankNTypes #-}
5−{-# LANGUAGE ScopedTypeVariables #-}
65{-# LANGUAGE ExistentialQuantification #-}
76{-# LANGUAGE GADTs #-}
87{-# LANGUAGE FlexibleContexts #-}
src/Graphics/Vty/Terminal/MacOSX.hs−2
@@ -5,8 +5,6 @@
55--
66-- This terminal implementation modifies the standard terminfo terminal as required for complete OS
77-- X support.
8−{-# LANGUAGE ForeignFunctionInterface #-}
9−{-# LANGUAGE ScopedTypeVariables #-}
108{-# LANGUAGE MagicHash #-}
119{-# LANGUAGE FlexibleInstances #-}
1210{-# LANGUAGE TypeFamilies #-}
src/Graphics/Vty/Terminal/TerminfoBased.hs−2
@@ -5,8 +5,6 @@
55-- assumptions mixed in.
66--
77-- Copyright Corey O'Connor (coreyoconnor@gmail.com)
8−{-# LANGUAGE ForeignFunctionInterface #-}
9−{-# LANGUAGE ScopedTypeVariables #-}
108{-# LANGUAGE FlexibleInstances #-}
119{-# OPTIONS_GHC -D_XOPEN_SOURCE=500 #-}
1210module Graphics.Vty.Terminal.TerminfoBased ( reserve_terminal )
src/Graphics/Vty/Terminal/XTermColor.hs−5
@@ -1,9 +1,4 @@
11-- Copyright 2009-2010 Corey O'Connor
2−{-# LANGUAGE ForeignFunctionInterface #-}
3−{-# LANGUAGE ScopedTypeVariables #-}
4−{-# LANGUAGE MagicHash #-}
5−{-# LANGUAGE FlexibleInstances #-}
6−{-# LANGUAGE TypeFamilies #-}
72module Graphics.Vty.Terminal.XTermColor ( reserve_terminal )
83 where
94
test/Rouge.hsnew file+108
@@ -0,0 +1,108 @@
1+module Main where
2+
3+import Graphics.Vty
4+
5+import Data.Array
6+import qualified Data.ByteString as B
7+import Data.Word
8+
9+import Control.Applicative
10+import Control.Monad
11+import Control.Monad.RWS
12+import Control.Monad.Writer
13+
14+import System.IO
15+import System.Random
16+
17+data Dude = Dude Int Int
18+ deriving (Show,Eq)
19+
20+data World = World
21+ { dude :: Dude
22+ , level :: Level
23+ }
24+ deriving (Show,Eq)
25+
26+data Level = Level
27+ { start :: (Int, Int)
28+ , end :: (Int, Int)
29+ , geo :: Array (Int, Int) LevelPiece
30+ }
31+ deriving (Show,Eq)
32+
33+data LevelPiece
34+ = EmptySpace
35+ | Rock
36+ deriving (Show, Eq)
37+
38+type Game = RWST Vty () World IO
39+
40+main = do
41+ vty <- mkVty
42+ level_0 <- mkLevel 0
43+ let world_0 = World (Dude (fst $ start level_0) (snd $ start level_0)) level_0
44+ (_final_world, ()) <- execRWST (play >> view_world) vty world_0
45+ shutdown vty
46+
47+mkLevel _difficulty = do
48+ level_width <- randomRIO (10,15)
49+ level_height <- randomRIO (10,15)
50+ start <- (,) <$> randomRIO (2, level_width-3) <*> randomRIO (2, level_height-3)
51+ end <- (,) <$> randomRIO (2, level_width-3) <*> randomRIO (2, level_height-3)
52+ let geo = array ((0,0), (level_width, level_height))
53+ [((x,y),p) | x <- [0..level_width-1], y <- [0..level_height-1],
54+ let p = if (x == 0 || x == level_width-1) || (y==0 || y==level_height-1)
55+ then Rock
56+ else EmptySpace
57+ ]
58+ return $ Level start end geo
59+
60+image_for_geo EmptySpace = char (def_attr `with_back_color` green) ' '
61+image_for_geo Rock = char (def_attr `with_fore_color` white) 'X'
62+
63+pieceA = def_attr `with_fore_color` red
64+dumpA = def_attr `with_style` reverse_video
65+
66+play = do
67+ view_world
68+ done <- process_event
69+ unless done play
70+
71+process_event = do
72+ k <- ask >>= liftIO . next_event
73+ if k == EvKey KEsc []
74+ then return True
75+ else do
76+ case k of
77+ EvKey (KASCII 'r') [MCtrl] -> ask >>= liftIO . refresh
78+ EvKey KLeft [] -> move_dude (-1) 0
79+ EvKey KRight [] -> move_dude 1 0
80+ EvKey KUp [] -> move_dude 0 (-1)
81+ EvKey KDown [] -> move_dude 0 1
82+ _ -> return ()
83+ return False
84+
85+move_dude dx dy = do
86+ vty <- ask
87+ world <- get
88+ let Dude x y = dude world
89+ (w, h) <- gets (snd . bounds . geo . level)
90+ put $ world { dude = Dude (min (w - 2) $ max 1 (x + dx))
91+ (min (h - 2) $ max 1 (y + dy))
92+ }
93+
94+view_world :: Game ()
95+view_world = do
96+ Dude x y <- gets dude
97+ the_level <- gets level
98+ let dude_image = translate x y (char pieceA '@')
99+ let (geo_width, geo_height) = snd $ bounds (geo the_level)
100+ geo_image = vert_cat [ geo_row | y <- [0..geo_height-1],
101+ let geo_row = horiz_cat [ i | x <- [0..geo_width-1],
102+ let i = image_for_geo (geo the_level ! (x,y))
103+ ]
104+ ]
105+ info = string def_attr "Move with the arrows keys. Press ESC to exit."
106+ let pic = pic_for_layers [info, translate 0 1 dude_image,translate 0 1 geo_image]
107+ vty <- ask
108+ liftIO $ update vty pic
test/Test.hsdeleted−44
@@ -1,44 +0,0 @@
1−{-# LANGUAGE ScopedTypeVariables #-}
2−module Main where
3−
4−import Graphics.Vty
5−
6−import qualified Data.ByteString as B
7−import Data.Word
8−
9−import System.IO
10−
11−
12−main = do
13− vt <- mkVty
14− DisplayRegion w h <- display_bounds $ terminal vt
15− putStrLn $ show $ DisplayRegion w h
16− play vt 0 1 w h ""
17−
18−pieceA = def_attr `with_fore_color` red
19−dumpA = def_attr `with_style` reverse_video
20−
21−play :: Vty -> Word -> Word -> Word -> Word -> String -> IO ()
22−play vt x y sx sy btl = do update vt (current_pic x y sx sy btl)
23− k <- next_event vt
24− case k of EvKey (KASCII 'r') [MCtrl] -> refresh vt >> play vt x y sx sy btl
25− EvKey KLeft [] | x /= 0 -> play vt (x-1) y sx sy btl
26− EvKey KRight [] | x /= (sx-1) -> play vt (x+1) y sx sy btl
27− EvKey KUp [] | y /= 1 -> play vt x (y-1) sx sy btl
28− EvKey KDown [] | y /= (sy-2) -> play vt x (y+1) sx sy btl
29− EvKey KEsc [] -> shutdown vt >> return ()
30− EvResize nx ny -> play vt (min x (toEnum nx - 1))
31− (min y (toEnum ny - 2))
32− (toEnum nx)
33− (toEnum ny)
34− btl
35− _ -> play vt x y sx sy (take (fromEnum sx) (show k ++ btl))
36−
37−
38−current_pic :: Word -> Word -> Word -> Word -> String -> Picture
39−current_pic x y sx sy btl = pic_for_image i
40− where i = string def_attr "Move the @ character around with the arrow keys. Escape exits."
41− <-> char_fill pieceA ' ' sx (y - 1)
42− <-> char_fill pieceA ' ' x 1 <|> char pieceA '@' <|> char_fill pieceA ' ' (sx - x - 1) 1
43− <-> char_fill pieceA ' ' sx (sy - y - 2)
44− <-> iso_10646_string dumpA btl
test/Verify.hs+4−1
@@ -1,6 +1,6 @@
1+{-# LANGUAGE RankNTypes #-}
12{-# LANGUAGE GADTs #-}
23{-# LANGUAGE RecordWildCards #-}
3−{-# LANGUAGE ScopedTypeVariables #-}
44{-# LANGUAGE CPP #-}
55{-# LANGUAGE TypeSynonymInstances #-}
66{-# LANGUAGE FlexibleInstances #-}
@@ -14,6 +14,7 @@ module Verify ( module Verify
1414 , module Control.Monad
1515 , module Test.QuickCheck
1616 , module Test.QuickCheck.Modifiers
17+ , module Text.Printf
1718 , succeeded
1819 , failed
1920 , result
@@ -37,6 +38,8 @@ import Test.QuickCheck.Property hiding ( Result(..) )
3738import qualified Test.QuickCheck.Property as Prop
3839import Test.QuickCheck.Monadic ( monadicIO )
3940
41+import Text.Printf
42+
4043import qualified Codec.Binary.UTF8.String as UTF8
4144
4245import Control.Applicative hiding ( (<|>) )
test/Verify/Data/Terminfo/Parse.hs−1
@@ -1,4 +1,3 @@
1−{-# LANGUAGE ScopedTypeVariables #-}
21module Verify.Data.Terminfo.Parse ( module Verify.Data.Terminfo.Parse
32 , module Data.Terminfo.Parse
43 )
test/Verify/Graphics/Vty/DisplayRegion.hs−1
@@ -1,4 +1,3 @@
1−{-# LANGUAGE ScopedTypeVariables #-}
21module Verify.Graphics.Vty.DisplayRegion ( module Verify.Graphics.Vty.DisplayRegion
32 , module Graphics.Vty.DisplayRegion
43 , MockWindow(..)
test/Verify/Graphics/Vty/Terminal.hs+4−2
@@ -1,4 +1,3 @@
1−{-# LANGUAGE ScopedTypeVariables #-}
21module Verify.Graphics.Vty.Terminal where
32
43import Graphics.Vty.Terminal.Mock
@@ -9,9 +8,12 @@ import qualified Data.String.UTF8 as UTF8
98
109import Test.QuickCheck.Property
1110
11+import Verify
12+
1213-- A list of terminals that should be supported.
1314-- This started with a list of terminals ubuntu supported. Then those terminals that really could
14−-- not be supported were removed.
15+-- not be supported were removed. Then a few more were pruned until a reasonable looking set was
16+-- made.
1517terminals_of_interest =
1618 [ "vt100"
1719 , "vt220"
test/VerifyEmptyImageProps.hs−1
@@ -1,4 +1,3 @@
1−{-# LANGUAGE ScopedTypeVariables #-}
21module VerifyEmptyImageProps where
32
43import Verify
test/VerifyEvalTerminfoCaps.hs+1−42
@@ -1,5 +1,4 @@
11{-# LANGUAGE BangPatterns #-}
2−{-# LANGUAGE ScopedTypeVariables #-}
32{-# LANGUAGE NamedFieldPuns #-}
43module VerifyEvalTerminfoCaps where
54
@@ -12,6 +11,7 @@ import Control.DeepSeq
1211import qualified System.Console.Terminfo as Terminfo
1312
1413import Verify
14+import Verify.Graphics.Vty.Terminal
1515
1616import Control.Applicative ( (<$>) )
1717import Control.Exception ( try, SomeException(..) )
@@ -23,47 +23,6 @@ import Data.Word
2323
2424import Numeric
2525
26−-- A list of terminals that ubuntu includes a terminfo cap file for.
27−-- Assuming that is a good place to start.
28−terminals_of_interest =
29− [ "wsvt25"
30− , "wsvt25m"
31− , "vt52"
32− , "vt100"
33− , "vt220"
34− , "vt102"
35− , "xterm-r5"
36− , "xterm-xfree86"
37− , "xterm-r6"
38− , "xterm-256color"
39− , "xterm-vt220"
40− , "xterm-debian"
41− , "xterm-mono"
42− , "xterm-color"
43− , "xterm"
44− , "mach"
45− , "mach-bold"
46− , "mach-color"
47− , "linux"
48− , "ansi"
49− , "hurd"
50− , "Eterm"
51− , "pcansi"
52− , "screen-256color"
53− , "screen-bce"
54− , "screen-s"
55− , "screen-w"
56− , "screen"
57− , "screen-256color-bce"
58− , "sun"
59− , "rxvt"
60− , "rxvt-unicode"
61− , "rxvt-basic"
62− , "cygwin"
63− , "cons25"
64− , "dumb"
65− ]
66−
6726-- If a terminal defines one of the caps then it's expected to be parsable.
6827caps_of_interest =
6928 [ "cup"
test/VerifyImageOps.hs−1
@@ -1,4 +1,3 @@
1−{-# LANGUAGE ScopedTypeVariables #-}
21module VerifyImageOps where
32
43import Graphics.Vty.Attributes
test/VerifyParseTerminfoCaps.hs+2−43
@@ -1,4 +1,3 @@
1−{-# LANGUAGE ScopedTypeVariables #-}
21{-# LANGUAGE NamedFieldPuns #-}
32module VerifyParseTerminfoCaps where
43
@@ -7,6 +6,7 @@ import Prelude hiding ( catch )
76import qualified System.Console.Terminfo as Terminfo
87
98import Verify.Data.Terminfo.Parse
9+import Verify.Graphics.Vty.Terminal
1010import Verify
1111
1212import Data.Maybe ( catMaybes, fromJust )
@@ -14,48 +14,8 @@ import Data.Word
1414
1515import Numeric
1616
17−-- A list of terminals that ubuntu includes a terminfo cap file for.
18−-- Assuming that is a good place to start.
19−terminals_of_interest =
20− [ "wsvt25"
21− , "wsvt25m"
22− , "vt52"
23− , "vt100"
24− , "vt220"
25− , "vt102"
26− , "xterm-r5"
27− , "xterm-xfree86"
28− , "xterm-r6"
29− , "xterm-256color"
30− , "xterm-vt220"
31− , "xterm-debian"
32− , "xterm-mono"
33− , "xterm-color"
34− , "xterm"
35− , "mach"
36− , "mach-bold"
37− , "mach-color"
38− , "linux"
39− , "ansi"
40− , "hurd"
41− , "Eterm"
42− , "pcansi"
43− , "screen-256color"
44− , "screen-bce"
45− , "screen-s"
46− , "screen-w"
47− , "screen"
48− , "screen-256color-bce"
49− , "sun"
50− , "rxvt"
51− , "rxvt-unicode"
52− , "rxvt-basic"
53− , "cygwin"
54− , "cons25"
55− , "dumb"
56− ]
57−
5817-- If a terminal defines one of the caps then it's expected to be parsable.
18+-- TODO: reduce duplication with terminfo terminal implementation.
5919caps_of_interest =
6020 [ "cup"
6121 , "sc"
@@ -81,7 +41,6 @@ from_capname ti name = fromJust $ Terminfo.getCapability ti (Terminfo.tiGetStr n
8141tests :: IO [Test]
8242tests = do
8343 parse_tests <- concat <$> forM terminals_of_interest ( \term_name -> do
84− putStrLn $ "testing parsing of caps for terminal: " ++ term_name
8544 mti <- liftIO $ try $ Terminfo.setupTerm term_name
8645 case mti of
8746 Left (_e :: SomeException)
test/VerifyTerminal.hs−1
@@ -1,4 +1,3 @@
1−{-# LANGUAGE ScopedTypeVariables #-}
21{- We setup the environment to envoke certain terminals of interest.
32 - This assumes appropriate definitions exist in the current environment for the terminals of
43 - interest.
test/VerifyUsingMockInput.hs+106−10
@@ -1,24 +1,120 @@
1−{-# LANGUAGE ScopedTypeVariables #-}
1+{-# LANGUAGE MultiParamTypeClasses #-}
2+{-# LANGUAGE FlexibleInstances #-}
23{- We setup the environment to envoke certain terminals of interest.
34 - This assumes appropriate definitions exist in the current environment for the terminals of
45 - interest.
56 -}
6−module VerifyUsingMockInput where
7−import Verify
7+module Main where
88
9−import Graphics.Vty
9+import Verify.Graphics.Vty.Terminal
1010
11+import Data.List (intersperse, permutations)
12+
13+import Graphics.Vty hiding (resize)
14+import Graphics.Vty.Input
15+import Graphics.Vty.Input.Data
16+import Graphics.Vty.Input.Internal
17+import Graphics.Vty.Input.Terminfo
18+
19+import Control.Applicative
20+import Control.Concurrent
21+import Control.Exception
1122import Control.Monad
1223
13−import System.Posix.Env
24+import System.Console.Terminfo
1425import System.IO
1526
16−data InputSpec
17− = KeySeq String -- | input sequence encoded as a string. Regardless, the input is read a byte at a time.
18− | Delay Int -- | millisecond delay
27+import Test.Framework.Providers.SmallCheck
28+import Test.Framework
29+import Test.SmallCheck
30+import Test.SmallCheck.Series
31+
32+-- processing a block of 16 chars is the largest I can do without taking too long to run the test.
33+max_block_size :: Int
34+max_block_size = 16
35+
36+forEachOf :: (Show a, Testable m b) => [a] -> (a -> b) -> Property m
37+forEachOf l = over (generate (\n -> take n l))
38+
39+data InputEvent
40+ = Bytes String -- | input sequence encoded as a string. Regardless, the input is read a byte at a time.
41+ | Delay Int -- | millisecond delay
42+ deriving Show
43+
44+type InputSpec = [InputEvent]
1945
2046type ExpectedSpec = [Event]
2147
22−tests :: IO [Test]
23−tests = return []
48+exec_input_spec :: InputSpec -> Handle -> IO ()
49+exec_input_spec input out_handle = forM_ input f
50+ where
51+ f (Bytes str) = hPutStr out_handle str >> hFlush out_handle
52+ f (Delay t) = threadDelay (t*1000)
53+
54+assert_events_from_input_block :: ClassifyTable -> InputSpec -> ExpectedSpec -> IO Bool
55+assert_events_from_input_block table input_spec expected_events = do
56+ print input_spec
57+ let classifier = classify table
58+ input <- newChan
59+ output <- newChan
60+ read_complete <- newEmptyMVar
61+ write_complete <- newEmptyMVar
62+ _ <- forkIO $ write_input_spec_to_chan input input_spec
63+ `finally` putMVar write_complete ()
64+ _ <- forkIO $ inputToEventThread classifier input output
65+ `finally` putMVar read_complete ()
66+ () <- takeMVar write_complete
67+ () <- takeMVar read_complete
68+ -- TODO: use STM channel
69+ -- assures the next line does not block.
70+ writeList2Chan output $ replicate (length expected_events) undefined
71+ out_events <- take (length expected_events) <$> getChanContents output
72+ return $ out_events == expected_events
73+
74+write_input_spec_to_chan :: Chan Char -> InputSpec -> IO ()
75+write_input_spec_to_chan chan [] = do
76+ writeChan chan '\xFFFD'
77+write_input_spec_to_chan chan (Bytes str : input_spec') = do
78+ writeList2Chan chan str
79+ write_input_spec_to_chan chan input_spec'
80+write_input_spec_to_chan chan (Delay _t : input_spec') = do
81+ writeChan chan '\xFFFE'
82+ write_input_spec_to_chan chan input_spec'
83+
84+newtype InputBlocksUsingTable event
85+ = InputBlocksUsingTable ([(String,event)] -> [(String, event)])
86+
87+instance Show (InputBlocksUsingTable event) where
88+ show (InputBlocksUsingTable _g) = "InputBlocksUsingTable"
89+
90+instance Monad m => Serial m (InputBlocksUsingTable event) where
91+ series = do
92+ n :: Int <- localDepth (max max_block_size) series -- what elements to select from the table
93+ return $ InputBlocksUsingTable $ \table -> concat (take n (permutations table))
94+
95+verify_simple_input_block_to_event :: Property IO
96+verify_simple_input_block_to_event = forAll $ \(InputBlocksUsingTable gen) -> do
97+ let input_seq = gen simple_chars
98+ input = Bytes $ concat [s | (s,_) <- input_seq]
99+ events = [e | (_,(k,ms)) <- input_seq, let e = EvKey k ms]
100+ monadic $ assert_events_from_input_block simple_chars [input] events
101+
102+verify_keys_from_caps_table_block_to_event :: Property IO
103+verify_keys_from_caps_table_block_to_event = forAll $ \(InputBlocksUsingTable gen) ->
104+ forEachOf terminals_of_interest $ \term_name -> monadic $ do
105+ term <- setupTerm term_name
106+ let table = caps_classify_table term keys_from_caps_table
107+ input_seq = gen table
108+ events = [e | (_,e) <- input_seq]
109+ keydowns = [Bytes s | (s,_) <- input_seq]
110+ input = intersperse (Delay defaultEscDelay) keydowns
111+ assert_events_from_input_block (map_to_legacy_table table) input events
112+
113+main :: IO ()
114+main = defaultMain
115+ [ testProperty "basic block generated from a single ansi chars to event translation"
116+ verify_simple_input_block_to_event
117+ , testProperty "key sequences read from caps table map to expected events"
118+ verify_keys_from_caps_table_block_to_event
119+ ]
24120
test/VerifyUsingMockTerminal.hs−1
@@ -1,4 +1,3 @@
1−{-# LANGUAGE ScopedTypeVariables #-}
21module VerifyUsingMockTerminal where
32
43import Verify.Graphics.Vty.DisplayRegion
test/benchmark.hs−1
@@ -1,5 +1,4 @@
11{-# LANGUAGE QuasiQuotes #-}
2−{-# LANGUAGE ScopedTypeVariables #-}
32module Main where
43
54import Graphics.Vty
test/interactive_terminal_test.hs−1
@@ -1,5 +1,4 @@
11{-# LANGUAGE QuasiQuotes #-}
2−{-# LANGUAGE ScopedTypeVariables #-}
32module Main where
43
54import Graphics.Vty
vty.cabal+57−8
@@ -27,8 +27,7 @@ description:
2727 &#169; 2006-2007 Stefan O'Rear; BSD3 license.
2828 .
2929 &#169; Corey O'Connor; BSD3 license.
30−-- the test suites require >= 1.17.0
31−cabal-version: >= 1.14.0
30+cabal-version: >= 1.18.0
3231build-type: Simple
3332data-files: README.md,
3433 TODO,
@@ -38,6 +37,7 @@ data-files: README.md,
3837
3938library
4039 default-language: Haskell2010
40+ default-extensions: ScopedTypeVariables
4141 build-depends: base >= 4 && < 5,
4242 bytestring,
4343 containers,
@@ -61,6 +61,8 @@ library
6161 Graphics.Vty.Inline.Unsafe
6262 Graphics.Vty.Input
6363 Graphics.Vty.Input.Data
64+ Graphics.Vty.Input.Internal
65+ Graphics.Vty.Input.Terminfo
6466 Graphics.Vty.Picture
6567 Graphics.Vty.Terminal
6668 Graphics.Text.Width
@@ -90,14 +92,18 @@ library
9092
9193 hs-source-dirs: src
9294
93− ghc-options: -O2 -funbox-strict-fields -Wall -fno-full-laziness -fspec-constr -fspec-constr-count=10
95+ default-extensions: ScopedTypeVariables
96+ ForeignFunctionInterface
9497
95− ghc-prof-options: -O2 -funbox-strict-fields -caf-all -Wall -fno-full-laziness -fspec-constr -fspec-constr-count=10
98+ ghc-options: -O2 -funbox-strict-fields -threaded -Wall -fspec-constr -fspec-constr-count=10
99+
100+ ghc-prof-options: -O2 -funbox-strict-fields -threaded -caf-all -Wall -fspec-constr -fspec-constr-count=10
96101
97102 cc-options: -O2
98103
99104test-suite verify-attribute-ops
100105 default-language: Haskell2010
106+ default-extensions: ScopedTypeVariables
101107 type: detailed-0.9
102108 hs-source-dirs: test
103109 test-module: VerifyAttributeOps
@@ -117,6 +123,7 @@ test-suite verify-attribute-ops
117123
118124test-suite verify-using-mock-terminal
119125 default-language: Haskell2010
126+ default-extensions: ScopedTypeVariables
120127
121128 type: detailed-0.9
122129
@@ -142,12 +149,14 @@ test-suite verify-using-mock-terminal
142149 deepseq >= 1.1 && < 1.4,
143150 mtl >= 1.1.1.0 && < 2.2,
144151 text >= 0.11.3,
152+ terminfo,
145153 unix,
146154 utf8-string >= 0.3 && < 0.4,
147155 vector >= 0.7
148156
149157test-suite verify-terminal
150158 default-language: Haskell2010
159+ default-extensions: ScopedTypeVariables
151160
152161 type: detailed-0.9
153162
@@ -180,6 +189,7 @@ test-suite verify-terminal
180189
181190test-suite verify-display-attributes
182191 default-language: Haskell2010
192+ default-extensions: ScopedTypeVariables
183193
184194 type: detailed-0.9
185195
@@ -210,6 +220,7 @@ test-suite verify-display-attributes
210220
211221test-suite verify-empty-image-props
212222 default-language: Haskell2010
223+ default-extensions: ScopedTypeVariables
213224
214225 type: detailed-0.9
215226
@@ -235,6 +246,7 @@ test-suite verify-empty-image-props
235246
236247test-suite verify-eval-terminfo-caps
237248 default-language: Haskell2010
249+ default-extensions: ScopedTypeVariables
238250
239251 type: detailed-0.9
240252
@@ -243,6 +255,7 @@ test-suite verify-eval-terminfo-caps
243255 test-module: VerifyEvalTerminfoCaps
244256
245257 other-modules: Verify
258+ Verify.Graphics.Vty.Terminal
246259
247260 build-depends: vty,
248261 Cabal == 1.18.*,
@@ -261,6 +274,7 @@ test-suite verify-eval-terminfo-caps
261274
262275test-suite verify-image-ops
263276 default-language: Haskell2010
277+ default-extensions: ScopedTypeVariables
264278
265279 type: detailed-0.9
266280
@@ -288,6 +302,7 @@ test-suite verify-image-ops
288302
289303test-suite verify-image-trans
290304 default-language: Haskell2010
305+ default-extensions: ScopedTypeVariables
291306
292307 type: detailed-0.9
293308
@@ -315,6 +330,7 @@ test-suite verify-image-trans
315330
316331test-suite verify-inline
317332 default-language: Haskell2010
333+ default-extensions: ScopedTypeVariables
318334
319335 type: detailed-0.9
320336
@@ -341,6 +357,7 @@ test-suite verify-inline
341357
342358test-suite verify-parse-terminfo-caps
343359 default-language: Haskell2010
360+ default-extensions: ScopedTypeVariables
344361
345362 type: detailed-0.9
346363
@@ -350,6 +367,7 @@ test-suite verify-parse-terminfo-caps
350367
351368 other-modules: Verify
352369 Verify.Data.Terminfo.Parse
370+ Verify.Graphics.Vty.Terminal
353371
354372 build-depends: vty,
355373 Cabal == 1.18.*,
@@ -368,6 +386,7 @@ test-suite verify-parse-terminfo-caps
368386
369387test-suite verify-simple-span-generation
370388 default-language: Haskell2010
389+ default-extensions: ScopedTypeVariables
371390
372391 type: detailed-0.9
373392
@@ -399,6 +418,7 @@ test-suite verify-simple-span-generation
399418
400419test-suite verify-crop-span-generation
401420 default-language: Haskell2010
421+ default-extensions: ScopedTypeVariables
402422
403423 type: detailed-0.9
404424
@@ -430,6 +450,7 @@ test-suite verify-crop-span-generation
430450
431451test-suite verify-layers-span-generation
432452 default-language: Haskell2010
453+ default-extensions: ScopedTypeVariables
433454
434455 type: detailed-0.9
435456
@@ -460,6 +481,7 @@ test-suite verify-layers-span-generation
460481
461482test-suite verify-utf8-width
462483 default-language: Haskell2010
484+ default-extensions: ScopedTypeVariables
463485
464486 type: detailed-0.9
465487
@@ -485,34 +507,40 @@ test-suite verify-utf8-width
485507
486508test-suite verify-using-mock-input
487509 default-language: Haskell2010
510+ default-extensions: ScopedTypeVariables
488511
489− type: detailed-0.9
512+ type: exitcode-stdio-1.0
490513
491514 hs-source-dirs: test
492515
493− test-module: VerifyUsingMockInput
494−
495− other-modules: Verify
516+ main-is: VerifyUsingMockInput.hs
496517
497518 build-depends: vty,
498519 Cabal == 1.18.*,
499520 QuickCheck >= 2.4,
521+ smallcheck == 1.*,
522+ quickcheck-assertions >= 0.1.1,
523+ test-framework == 0.8.*,
524+ test-framework-smallcheck == 0.2.*,
500525 random == 1.0.*,
501526 base >= 4 && < 5,
502527 bytestring,
503528 containers,
504529 deepseq >= 1.1 && < 1.4,
505530 mtl >= 1.1.1.0 && < 2.2,
531+ terminfo >= 0.3 && < 0.4,
506532 text >= 0.11.3,
507533 unix,
508534 utf8-string >= 0.3 && < 0.4,
509535 vector >= 0.7
510536
537+ ghc-options: -threaded -Wall
511538
512539executable vty-interactive-terminal-test
513540 main-is: interactive_terminal_test.hs
514541
515542 default-language: Haskell2010
543+ default-extensions: ScopedTypeVariables
516544
517545 hs-source-dirs: test
518546
@@ -533,10 +561,31 @@ executable vty-interactive-terminal-test
533561 utf8-string >= 0.3 && < 0.4,
534562 vector >= 0.7
535563
564+executable vty-rouge
565+ main-is: Rouge.hs
566+ hs-source-dirs: test
567+
568+ default-language: Haskell2010
569+ default-extensions: ScopedTypeVariables
570+
571+ build-depends: vty,
572+ base >= 4 && < 5,
573+ array >= 0.4 && < 2.0,
574+ bytestring,
575+ containers,
576+ lens,
577+ mtl >= 1.1.1.0 && < 2.2,
578+ parallel >= 2.2 && < 3.3,
579+ random >= 1.0 && < 2.0,
580+ text >= 0.11.3,
581+ utf8-string >= 0.3 && < 0.4,
582+ vector >= 0.7
583+
536584executable vty-benchmark
537585 main-is: benchmark.hs
538586
539587 default-language: Haskell2010
588+ default-extensions: ScopedTypeVariables
540589
541590 hs-source-dirs: test
542591