on master help sign in
start refactoring input layer into a nice interface structure
commitb3013245fdfe16b5b89304d241b3efba05bbd41b authorCorey O'Connor <corey@ooyala.com> dateSat 21 Dec 2013, 23:22 (13 years ago) parente994b3b
5 files changed+54−29
cbits/set_term_timing.c−1 src/Graphics/Vty.hs+18−10 src/Graphics/Vty/Input.hs+27−14 src/Graphics/Vty/Input/Internal.hs+7−2 test/VerifyUsingMockInput.hs+2−2
cbits/set_term_timing.c−1
@@ -11,4 +11,3 @@ void vty_set_term_timing(void)
1111 trm.c_cc[VTIME] = 0;
1212 tcsetattr(STDIN_FILENO, TCSANOW, &trm);
1313}
14−
src/Graphics/Vty.hs+18−10
@@ -41,6 +41,8 @@ import Graphics.Vty.Input
4141import Graphics.Vty.Output
4242import Graphics.Vty.Picture
4343
44+import Control.Concurrent
45+
4446import Data.IORef
4547
4648import qualified System.Console.Terminfo as Terminfo
@@ -69,7 +71,9 @@ data Vty = Vty
6971 update :: Picture -> IO ()
7072 -- | Get one Event object, blocking if necessary.
7173 , next_event :: IO Event
72− -- | The output interface. See `Output`
74+ -- | The input interface. See 'Input'
75+ , input_iface :: Input
76+ -- | The output interface. See 'Output'
7377 , output_iface :: Output
7478 -- | Refresh the display. Normally the library takes care of refreshing. Nonetheless, some
7579 -- other program might output to the terminal and mess the display. In that case the user
@@ -91,14 +95,17 @@ mkVty = mkVtyEscDelay defaultEscDelay
9195-- \todo move input init into terminal interface
9296mkVtyEscDelay :: Int -> IO Vty
9397mkVtyEscDelay escDelay = do
94− term_info <- Terminfo.setupTermFromEnv
95− t <- output_for_current_terminal
96− reserve_display t
97− (kvar, endi) <- initTermInput escDelay term_info
98− intMkVty kvar ( endi >> release_display t >> release_terminal t ) t
98+ input <- input_for_current_terminal escDelay
99+ out <- output_for_current_terminal
100+ reserve_display out
101+ intMkVty input out
99102
100−intMkVty :: IO Event -> IO () -> Output -> IO Vty
101−intMkVty kvar fend out = do
103+intMkVty :: Input -> Output -> IO Vty
104+intMkVty input out = do
105+ let shutdown_io = do
106+ shutdown_input input
107+ release_display out
108+ release_terminal out
102109 last_pic_ref <- newIORef Nothing
103110 last_update_ref <- newIORef Nothing
104111
@@ -141,7 +148,7 @@ intMkVty kvar fend out = do
141148 >> readIORef last_pic_ref
142149 >>= maybe ( return () ) ( \pic -> inner_update pic )
143150
144− let gkey = do k <- kvar
151+ let gkey = do k <- readChan $ event_channel input
145152 case k of
146153 (EvResize _ _) -> inner_refresh
147154 >> display_bounds out
@@ -150,8 +157,9 @@ intMkVty kvar fend out = do
150157
151158 return $ Vty { update = inner_update
152159 , next_event = gkey
160+ , input_iface = input
153161 , output_iface = out
154162 , refresh = inner_refresh
155− , shutdown = fend
163+ , shutdown = shutdown_io
156164 }
157165
src/Graphics/Vty/Input.hs+27−14
@@ -4,8 +4,10 @@ module Graphics.Vty.Input ( Key(..)
44 , Modifier(..)
55 , Button(..)
66 , Event(..)
7− , initTermInput
7+ , Input(..)
88 , defaultEscDelay
9+ , input_for_current_terminal
10+ , input_for_name_and_io
911 )
1012 where
1113
@@ -15,11 +17,12 @@ import Graphics.Vty.Input.Terminfo
1517
1618import Control.Concurrent
1719
18−import System.Console.Terminfo
19−
20+import qualified System.Console.Terminfo as Terminfo
21+import System.Environment
2022import System.Posix.Signals.Exts
2123import System.Posix.Terminal
2224import System.Posix.IO (stdInput)
25+import System.Posix.Types (Fd)
2326
2427-- Right, I'm mostly guessing on these details. So, as far as I can figure:
2528--
@@ -45,6 +48,13 @@ import System.Posix.IO (stdInput)
4548defaultEscDelay :: Int
4649defaultEscDelay = 10000
4750
51+-- | Set up the current terminal for input.
52+-- This determines the current terminal then invokes 'input_for_name_and_io'
53+input_for_current_terminal :: Int -> IO Input
54+input_for_current_terminal escDelay = do
55+ term_name <- getEnv "TERM"
56+ input_for_name_and_io escDelay term_name stdInput
57+
4858-- | Set up the terminal for input. Returns a function which reads key
4959-- events, and a function for shutting down the terminal access.
5060--
@@ -71,26 +81,29 @@ defaultEscDelay = 10000
7181-- * IEXTEN disabled
7282-- - extended functions are disabled. Uh. Whatever these are.
7383--
74−initTermInput :: Int -> Terminal -> IO (IO Event, IO ())
75−initTermInput escDelay terminal = do
76− attr <- getTerminalAttributes stdInput
84+input_for_name_and_io :: Int -> String -> Fd -> IO Input
85+input_for_name_and_io escDelay term_name term_in = do
86+ terminal <- Terminfo.setupTerm term_name
87+ attr <- getTerminalAttributes term_in
7788 let attr' = foldl withoutMode attr [ StartStopOutput, KeyboardInterrupts
7889 , EnableEcho, ProcessInput, ExtendedFunctions
7990 ]
80− setTerminalAttributes stdInput attr' Immediately
91+ setTerminalAttributes term_in attr' Immediately
92+ -- TODO: pass Fd to set_term_timing
8193 set_term_timing
8294 let classify_table = classify_table_for_term terminal
83− (eventChannel, shutdown_input) <- initInputForFd escDelay classify_table stdInput
95+ (eventChannel, shutdown_event_processing) <- initInputForFd escDelay classify_table term_in
8496 let pokeIO = Catch $ do
8597 let e = error "(getsize in input layer)"
86− setTerminalAttributes stdInput attr' Immediately
98+ setTerminalAttributes term_in attr' Immediately
8799 writeChan eventChannel (EvResize e e)
88100 _ <- installHandler windowChange pokeIO Nothing
89101 _ <- installHandler continueProcess pokeIO Nothing
90− let shutdown_input' = do
91− shutdown_input
102+ return $ Input
103+ { event_channel = eventChannel
104+ , shutdown_input = do
105+ shutdown_event_processing
92106 _ <- installHandler windowChange Ignore Nothing
93107 _ <- installHandler continueProcess Ignore Nothing
94− setTerminalAttributes stdInput attr Immediately
95− return (readChan eventChannel, shutdown_input')
96−
108+ setTerminalAttributes term_in attr Immediately
109+ }
src/Graphics/Vty/Input/Internal.hs+7−2
@@ -22,6 +22,11 @@ import System.Posix.IO ( fdReadBuf
2222 )
2323import System.Posix.Types (Fd(..))
2424
25+data Input = Input
26+ { event_channel :: Chan Event
27+ , shutdown_input :: IO ()
28+ }
29+
2530data KClass
2631 = Valid Key [Modifier]
2732 | Invalid
@@ -141,11 +146,11 @@ initInputForFd escDelay classify_table input_fd = do
141146 noInputThreadId <- forkIO $ noInputThread
142147 -- TODO(corey): killThread is a bit risky for my tastes.
143148 -- H - somewhat mitigated by sending a magic terminate character?
144− let shutdown_input = do
149+ let shutdown_event_processing = do
145150 writeChan inputChannel '\xFFFD'
146151 killThread noInputThreadId
147152 killThread eventThreadId
148153 killThread inputThreadId
149− return (eventChannel, shutdown_input)
154+ return (eventChannel, shutdown_event_processing)
150155
151156foreign import ccall "vty_set_term_timing" set_term_timing :: IO ()
test/VerifyUsingMockInput.hs+2−2
@@ -107,12 +107,12 @@ assert_events_from_syn_input table input_spec expected_events = do
107107 let max_duration = sum [t | Delay t <- input_spec] + min_detectable_delay
108108 event_count = length expected_events
109109 (output_fd, input_fd) <- createPipe
110− (output, shutdown_input) <- initInputForFd test_esc_sample_delay table output_fd
110+ (output, shutdown_event_processing) <- initInputForFd test_esc_sample_delay table output_fd
111111 events_ref <- newIORef []
112112 let write_wait_close = do
113113 synthesize_input input_spec input_fd
114114 threadDelay min_detectable_delay
115− shutdown_input
115+ shutdown_event_processing
116116 threadDelay min_detectable_delay
117117 closeFd input_fd
118118 closeFd output_fd