@@ -52,9 +52,14 @@ data Input = Input
5252 -- 'nextEvent' this will not refresh the display if the next event
5353 -- is an 'EvResize'.
5454 _eventChannel :: TChan Event
55− -- | Shuts down the input processing. This should return the
56− -- terminal input state to before he input initialized.
55+ -- | Shuts down the input processing. As part of shutting down the
56+ -- input, this should also restore the input state.
5757 , shutdownInput :: IO ()
58+ -- | Restore the terminal's input state to what it was prior
59+ -- to configuring input for Vty. This should be done as part of
60+ -- 'shutdownInput' but is exposed in case you need to access it
61+ -- directly.
62+ , restoreInputState :: IO ()
5863 -- | Changes to this value are reflected after the next event.
5964 , _configRef :: IORef Config
6065 -- | input debug log
@@ -171,15 +176,47 @@ runInputProcessorLoop classifyTable input = do
171176 <*> pure (classify classifyTable)
172177 runReaderT (evalStateT loopInputProcessor s0) input
173178
179+-- | Construct two IO actions: one to configure the terminal for Vty and
180+-- one to restore the terminal mode flags to the values they had at the
181+-- time this function was called.
182+--
183+-- This function constructs a configuration action to clear the
184+-- following terminal mode flags:
185+--
186+-- * IXON disabled: disables software flow control on outgoing data.
187+-- This stops the process from being suspended if the output terminal
188+-- cannot keep up.
189+--
190+-- * Raw mode is used for input.
191+--
192+-- * ISIG (enables keyboard combinations that result in
193+-- signals)
194+--
195+-- * ECHO (input is not echoed to the output)
196+--
197+-- * ICANON (canonical mode (line mode) input is not used)
198+--
199+-- * IEXTEN (extended functions are disabled)
200+--
201+-- The configuration action also explicitly sets these flags:
202+--
203+-- * ICRNL (input carriage returns are mapped to newlines)
174204attributeControl :: Fd -> IO (IO (), IO ())
175205attributeControl fd = do
176206 original <- getTerminalAttributes fd
177− let vtyMode = foldl withoutMode original [ StartStopOutput, KeyboardInterrupts
178− , EnableEcho, ProcessInput, ExtendedFunctions
179− ]
207+ let vtyMode = foldl withMode clearedFlags flagsToSet
208+ clearedFlags = foldl withoutMode original flagsToUnset
209+ flagsToSet = [ MapCRtoLF -- ICRNL
210+ ]
211+ flagsToUnset = [ StartStopOutput -- IXON
212+ , KeyboardInterrupts -- ISIG
213+ , EnableEcho -- ECHO
214+ , ProcessInput -- ICANON
215+ , ExtendedFunctions -- IEXTEN
216+ ]
180217 let setAttrs = setTerminalAttributes fd vtyMode Immediately
181218 unsetAttrs = setTerminalAttributes fd original Immediately
182− return (setAttrs,unsetAttrs)
219+ return (setAttrs, unsetAttrs)
183220
184221logInitialInputState :: Input -> ClassifyMap -> IO()
185222logInitialInputState input classifyTable = case _inputDebug input of
@@ -203,6 +240,7 @@ initInput config classifyTable = do
203240 applyConfig fd config
204241 stopSync <- newEmptyMVar
205242 input <- Input <$> atomically newTChan
243+ <*> pure (return ())
206244 <*> pure (return ())
207245 <*> newIORef config
208246 <*> maybe (return Nothing)