@@ -7,11 +7,12 @@
8-- This is an example of an algorithm where code coverage could be high, even 100%, but the
8-- This is an example of an algorithm where code coverage could be high, even 100%, but the
9-- behavior is still under tested. I should collect more of these examples...
9-- behavior is still under tested. I should collect more of these examples...
10−module Graphics.Vty.Input.Internal where
10+module Graphics.Vty.Input.Loop where
12+import Graphics.Vty.Config
13+import Graphics.Vty.Input.Classify
12import Graphics.Vty.Input.Events
14import Graphics.Vty.Input.Events
14−import Codec.Binary.UTF8.Generic (decode)
15import Control.Applicative
16import Control.Applicative
16import Control.Concurrent
17import Control.Concurrent
17import Control.Lens
18import Control.Lens
@@ -21,13 +22,8 @@ import Control.Monad.Trans.State (StateT(..), evalStateT)
21import Control.Monad.Trans.Reader (ReaderT(..))
22import Control.Monad.Trans.Reader (ReaderT(..))
23import Data.Char
24import Data.Char
25import Data.IORef
25import Data.IORef
26−import Data.List(tails,inits)
26+import Data.Word (Word8)
27−import qualified Data.Map as M( fromList, lookup )
28−import Data.Maybe ( mapMaybe )
29−import qualified Data.Set as S( fromList, member )
32import Foreign ( allocaArray, peekArray, Ptr )
28import Foreign ( allocaArray, peekArray, Ptr )
33import Foreign.C.Types (CInt(..))
29import Foreign.C.Types (CInt(..))
@@ -36,17 +32,6 @@ import System.Posix.IO (fdReadBuf)
36import System.Posix.Terminal
32import System.Posix.Terminal
37import System.Posix.Types (Fd(..))
33import System.Posix.Types (Fd(..))
40− { singleEscPeriod :: Int -- ^ AKA VTIME. The default is 100000 microseconds or 0.1 seconds.
41− , debugInputLog :: Maybe FilePath -- ^ Debug information about the input process is appended to the file.
42− } deriving (Show, Eq)
44−instance Default Config where
46− { singleEscPeriod = 100000
47− , debugInputLog = Nothing
50data Input = Input
35data Input = Input
51 { -- | Channel of events direct from input processing. Unlike 'nextEvent' this will not refresh
36 { -- | Channel of events direct from input processing. Unlike 'nextEvent' this will not refresh
52 -- the display if the next event is an 'EvResize'.
37 -- the display if the next event is an 'EvResize'.
@@ -62,12 +47,6 @@ data Input = Input
63makeLenses ''Input
48makeLenses ''Input
71data InputBuffer = InputBuffer
50data InputBuffer = InputBuffer
72 { _ptr :: Ptr Word8
51 { _ptr :: Ptr Word8
73 , _size :: Int
52 , _size :: Int
@@ -148,63 +127,6 @@ stopIfRequested = do
148 True <- (liftIO . readIORef) =<< use stopRequestRef
127 True <- (liftIO . readIORef) =<< use stopRequestRef
149 return ()
128 return ()
151−-- This makes a kind of tri. Has space efficiency issues with large input blocks.
152−-- Likely building a parser and just applying that would be better.
153−-- I did not write this so I might just rewrite it for better understanding. Not the best of
155−-- TODO: measure and rewrite if required.
156−-- TODO: The ClassifyTable interface requires this code to always assure later entries override
158−compile :: ClassifyTable -> [Char] -> KClass
159−compile table = cl' where
160− -- take all prefixes and create a set of these
161− prefixSet = S.fromList $ concatMap (init . inits . fst) $ table
162− eventForInput = M.fromList table
164− cl' inputBlock = case M.lookup inputBlock eventForInput of
165− Just e -> Valid e []
166− Nothing -> case S.member inputBlock prefixSet of
168− -- if the inputBlock is exactly what is expected for an event then consume the whole
169− -- block and return the event
170− -- look up progressively smaller tails of the input block until an event is found
171− -- The assumption is that the event that consumes the most input bytes should be
173− -- The test verifyFullSynInputToEvent2x verifies this.
174− -- H: There will always be one match. The prefixSet contains, by definition, all
175− -- prefixes of an event.
177− let inputTails = init $ tail $ tails inputBlock
178− in case mapMaybe (\s -> (,) s `fmap` M.lookup s eventForInput) inputTails of
179− (s,e) : _ -> Valid e (drop (length s) inputBlock)
180− -- neither a prefix or a full event. Might be interesting to log.
183−classify, classifyTab :: ClassifyTable -> [Char] -> KClass
186−classify _table s@(c:_) | ord c >= 0xC2
187− = if utf8Length (ord c) > length s then Prefix else classifyUtf8 s -- beginning of an utf8 sequence
189− = classifyTab table other
191−classifyUtf8 :: [Char] -> KClass
192−classifyUtf8 s = case decode ((map (fromIntegral . ord) s) :: [Word8]) of
193− Just (unicodeChar, _) -> Valid (EvKey (KChar unicodeChar) []) []
194− _ -> Invalid -- something bad happened; just ignore and continue.
196−classifyTab table = compile table
198−first :: (a -> b) -> (a,c) -> (b,c)
199−first f (x,y) = (f x, y)
201−utf8Length :: (Num t, Ord a, Num a) => a -> t
208runInputProcessorLoop :: ClassifyTable -> Input -> IORef Bool -> IO ()
130runInputProcessorLoop :: ClassifyTable -> Input -> IORef Bool -> IO ()
209runInputProcessorLoop classifyTable input stopFlag = do
131runInputProcessorLoop classifyTable input stopFlag = do
210 let bufferSize = 1024
132 let bufferSize = 1024