@@ -8,6 +8,8 @@
9-- This is an example of an algorithm where code coverage could be high, even 100%, but the
9-- This is an example of an algorithm where code coverage could be high, even 100%, but the
10-- behavior is still under tested. I should collect more of these examples...
10-- behavior is still under tested. I should collect more of these examples...
12+-- reference: http://www.unixwiz.net/techtips/termios-vmin-vtime.html
11module Graphics.Vty.Input.Loop where
13module Graphics.Vty.Input.Loop where
13import Graphics.Vty.Config
15import Graphics.Vty.Config
@@ -30,7 +32,7 @@ import Foreign ( allocaArray, peekArray, Ptr )
30import Foreign.C.Types (CInt(..))
32import Foreign.C.Types (CInt(..))
32import System.IO
34import System.IO
33−import System.Posix.IO (fdReadBuf)
35+import System.Posix.IO (fdReadBuf, setFdOption, FdOption(..))
34import System.Posix.Terminal
36import System.Posix.Terminal
35import System.Posix.Types (Fd(..))
37import System.Posix.Types (Fd(..))
@@ -108,6 +110,7 @@ readFromDevice = do
108 oldConfig <- use appliedConfig
110 oldConfig <- use appliedConfig
109 fd <- view inputFd
111 fd <- view inputFd
110 when (newConfig /= oldConfig) $ do
112 when (newConfig /= oldConfig) $ do
113+ logMsg $ "new config: " ++ show newConfig
111 liftIO $ applyTimingConfig fd newConfig
114 liftIO $ applyTimingConfig fd newConfig
112 appliedConfig .= newConfig
115 appliedConfig .= newConfig
113 bufferPtr <- use $ inputBuffer.ptr
116 bufferPtr <- use $ inputBuffer.ptr
@@ -117,13 +120,12 @@ readFromDevice = do
117 if bytesRead > 0
120 if bytesRead > 0
118 then fmap (map $ chr . fromIntegral) $ peekArray (fromIntegral bytesRead) bufferPtr
121 then fmap (map $ chr . fromIntegral) $ peekArray (fromIntegral bytesRead) bufferPtr
119 else return []
122 else return []
120− logMsg $ "input bytes: " ++ show stringRep
123+ when (not $ null stringRep) $ logMsg $ "input bytes: " ++ show stringRep
121 return stringRep
124 return stringRep
123applyTimingConfig :: Fd -> Config -> IO ()
126applyTimingConfig :: Fd -> Config -> IO ()
124−applyTimingConfig fd config =
127+applyTimingConfig fd config = setTermTiming fd (derivedVmin config)
125− let vtime = min 255 $ singleEscPeriod config `div` 100000
128+ (derivedVtime config `div` 100)
126− in setTermTiming fd 1 vtime
128parseEvent :: InputM Event
130parseEvent :: InputM Event
129parseEvent = do
131parseEvent = do
@@ -131,6 +133,8 @@ parseEvent = do
131 b <- use unprocessedBytes
133 b <- use unprocessedBytes
132 case c b of
134 case c b of
133 Valid e remaining -> do
135 Valid e remaining -> do
136+ logMsg $ "valid parse: " ++ show e
137+ logMsg $ "remaining: " ++ show remaining
134 unprocessedBytes .= remaining
138 unprocessedBytes .= remaining
136 _ -> mzero
140 _ -> mzero
@@ -139,7 +143,9 @@ dropInvalid :: InputM ()
139dropInvalid = do
143dropInvalid = do
140 c <- use classifier
144 c <- use classifier
141 b <- use unprocessedBytes
145 b <- use unprocessedBytes
146+ when (c b == Invalid) $ do
147+ logMsg "dropping input bytes"
142− when (c b == Invalid) $ unprocessedBytes .= []
148+ unprocessedBytes .= []
144stopIfRequested :: InputM ()
150stopIfRequested :: InputM ()
145stopIfRequested = do
151stopIfRequested = do
@@ -166,10 +172,12 @@ attributeControl fd = do
166 unsetAttrs = setTerminalAttributes fd original Immediately
172 unsetAttrs = setTerminalAttributes fd original Immediately
167 return (setAttrs,unsetAttrs)
173 return (setAttrs,unsetAttrs)
169−logClassifyMap :: Input -> String -> ClassifyMap -> IO()
175+logInitialInputState :: Input -> String -> ClassifyMap -> IO()
170−logClassifyMap input termName classifyTable = case _inputDebug input of
176+logInitialInputState input termName classifyTable = case _inputDebug input of
171 Nothing -> return ()
177 Nothing -> return ()
172 Just h -> do
178 Just h -> do
179+ config <- readIORef $ _configRef input
180+ hPrintf h "initial (vmin,vtime): %s\n" (show (vmin config, vtime config))
173 forM_ classifyTable $ \i -> case i of
181 forM_ classifyTable $ \i -> case i of
174 (inBytes, EvKey k mods) -> hPrintf h "map %s %s %s %s\n" (show termName)
182 (inBytes, EvKey k mods) -> hPrintf h "map %s %s %s %s\n" (show termName)
175 (show inBytes)
183 (show inBytes)
@@ -179,6 +187,7 @@ logClassifyMap input termName classifyTable = case _inputDebug input of
180initInputForFd :: Config -> String -> ClassifyMap -> Fd -> IO Input
188initInputForFd :: Config -> String -> ClassifyMap -> Fd -> IO Input
181initInputForFd config termName classifyTable inFd = do
189initInputForFd config termName classifyTable inFd = do
190+ setFdOption inFd NonBlockingRead False
182 applyTimingConfig inFd config
191 applyTimingConfig inFd config
183 stopFlag <- newIORef False
192 stopFlag <- newIORef False
184 input <- Input <$> newChan
193 input <- Input <$> newChan
@@ -188,7 +197,7 @@ initInputForFd config termName classifyTable inFd = do
188 <*> maybe (return Nothing)
197 <*> maybe (return Nothing)
189 (\f -> Just <$> openFile f AppendMode)
198 (\f -> Just <$> openFile f AppendMode)
190 (debugLog config)
199 (debugLog config)
191− logClassifyMap input termName classifyTable
200+ logInitialInputState input termName classifyTable
192 _ <- forkOS $ runInputProcessorLoop classifyTable input stopFlag
201 _ <- forkOS $ runInputProcessorLoop classifyTable input stopFlag
193 return input
202 return input