@@ -25,6 +25,9 @@ import Control.Monad
25
25
import Control.Monad.Catch (MonadMask , handle , finally )
26
26
import Control.Concurrent.STM
27
27
import Control.Concurrent hiding (throwTo )
28
+ import Control.Concurrent.Async (runConcurrently , Concurrently (.. ))
29
+ import Control.Applicative ((<|>) )
30
+ import Data.Functor (($>) )
28
31
import Data.Maybe (catMaybes )
29
32
import System.Posix.Signals.Exts
30
33
import System.Posix.Types (Fd (.. ))
@@ -244,21 +247,33 @@ getEvent h baseMap = keyEventLoop $ do
244
247
return [KeyInput $ lexKeys baseMap cs]
245
248
246
249
-- Read at least one character of input, and more if immediately
247
- -- available. In particular the characters making up a control sequence
248
- -- will all be available at once, so they can be processed together
249
- -- (with Posix.lexKeys).
250
+ -- available. If an ESC character is seen, timeout mode is
251
+ -- activated to prevent control sequences from being broken across
252
+ -- getBlockofChars calls. A timeout of 20ms was shown to work
253
+ -- well with a 9600bps serial port.
250
254
getBlockOfChars :: Handle -> IO String
251
255
getBlockOfChars h = do
252
256
c <- hGetChar h
253
- loop [c]
254
- where
255
- loop cs = do
256
- isReady <- hReady h
257
- if not isReady
258
- then return $ reverse cs
259
- else do
260
- c <- hGetChar h
261
- loop (c: cs)
257
+ loop c [] False
258
+ where
259
+ loop :: Char -> String -> Bool -> IO String
260
+ loop c' cs' timeout' = do
261
+ let
262
+ timeout = timeout' || (c' == ' \ESC ' )
263
+ cs = (c': cs')
264
+ maybeC <- do
265
+ isReady <- hReady h
266
+ case (timeout, isReady) of
267
+ (_, True ) -> do -- fast new character case
268
+ Just <$> hGetChar h
269
+ (True , False ) -> -- wait up to 20ms for next char
270
+ runConcurrently $ Concurrently (Just <$> hGetChar h)
271
+ <|> Concurrently (threadDelay 20000 $> Nothing )
272
+ (False , False ) -> -- no new char and timeout mode has not been triggered
273
+ pure Nothing
274
+ case maybeC of
275
+ Just c -> loop c cs timeout
276
+ Nothing -> pure $ reverse cs
262
277
263
278
stdinTTYHandles , ttyHandles :: MaybeT IO Handles
264
279
stdinTTYHandles = do
0 commit comments