@@ -5,12 +5,12 @@ module Graphics.Vty.LLInput ( Key(..)
55 , Modifier(..)
66 , Button(..)
77 , Event(..)
8− , initTermInput
9− )
8+ , initTermInput
9+ )
1010 where
1111
1212import Data.Char
13−import Data.Maybe ( mapMaybe
13+import Data.Maybe ( mapMaybe
1414 )
1515import Data.List( inits )
1616import Data.Word
@@ -36,22 +36,22 @@ import System.Posix.IO ( stdInput
3636-- |Representations of non-modifier keys.
3737data Key = KEsc | KFun Int | KBackTab | KPrtScr | KPause | KASCII Char | KBS | KIns
3838 | KHome | KPageUp | KDel | KEnd | KPageDown | KBegin | KNP5 | KUp | KMenu
39− | KLeft | KDown | KRight | KEnter
39+ | KLeft | KDown | KRight | KEnter
4040 deriving (Eq,Show,Ord)
4141
4242-- |Modifier keys. Key codes are interpreted such that users are more likely to
4343-- have Meta than Alt; for instance on the PC Linux console, 'MMeta' will
4444-- generally correspond to the physical Alt key.
45−data Modifier = MShift | MCtrl | MMeta | MAlt
45+data Modifier = MShift | MCtrl | MMeta | MAlt
4646 deriving (Eq,Show,Ord)
4747
4848-- |Mouse buttons. Not yet used.
49−data Button = BLeft | BMiddle | BRight
49+data Button = BLeft | BMiddle | BRight
5050 deriving (Eq,Show,Ord)
5151
5252-- |Generic events.
5353data Event = EvKey Key [Modifier] | EvMouse Int Int Button [Modifier]
54− | EvResize Int Int
54+ | EvResize Int Int
5555 deriving (Eq,Show,Ord)
5656
5757data KClass = Valid Key [Modifier] | Invalid | Prefix | MisPfx Key [Modifier] [Char]
@@ -70,7 +70,7 @@ initTermInput escDelay terminal = do
7070 setTerminalAttributes stdInput nattr Immediately
7171 set_term_timing
7272 let inputToEventThread :: IO ()
73− inputToEventThread = loop []
73+ inputToEventThread = loop []
7474 where loop kb = case (classify kb) of
7575 Prefix -> do c <- readChan inputChannel
7676 loop (kb ++ [c])
@@ -82,7 +82,7 @@ initTermInput escDelay terminal = do
8282
8383 inputThread :: IO ()
8484 inputThread = loop
85− where
85+ where
8686 loop = do
8787 setFdOption stdInput NonBlockingRead False
8888 threadWaitRead stdInput
@@ -97,7 +97,7 @@ initTermInput escDelay terminal = do
9797 writeChan inputChannel (head bytes)
9898 readAll
9999 -- | If there is no input for some time, this thread puts '\xFFFE' in the
100− -- inputChannel.
100+ -- inputChannel.
101101 noInputThread :: IO ()
102102 noInputThread = when (escDelay > 0) loop
103103 where loop = do
@@ -107,7 +107,7 @@ initTermInput escDelay terminal = do
107107 when hadNoInput $ do
108108 finishAtomicInput
109109 loop
110−
110+
111111
112112 compile :: [[([Char],(Key,[Modifier]))]] -> [Char] -> KClass
113113 compile lst = cl' where
@@ -120,25 +120,25 @@ initTermInput escDelay terminal = do
120120 Just (k,m) -> Valid k m
121121 Nothing -> case head $ mapMaybe (\s -> (,) s `fmap` M.lookup s mlst) $ init $ inits str of
122122 (s,(k,m)) -> MisPfx k m (drop (length s) str)
123−
123+
124124 -- ANSI specific bits
125125
126126
127127 classify, classifyTab :: [Char] -> KClass
128−
128+
129129 -- As soon as
130130 classify "\xFFFE" = Invalid
131− classify s@(c:_) | ord c >= 0xC2 =
131+ classify s@(c:_) | ord c >= 0xC2 =
132132 if utf8Length (ord c) > length s then Prefix else classifyUtf8 s -- beginning of an utf8 sequence
133133 classify other = classifyTab other
134134
135135 classifyUtf8 s = case decode ((map (fromIntegral . ord) s) :: [Word8]) of
136136 Just (unicodeChar, _) -> Valid (KASCII unicodeChar) []
137137 _ -> Invalid -- something bad happened; just ignore and continue.
138−
138+
139139 classifyTab = compile (caps_classify_table : ansi_classify_table)
140−
141− caps_tabls = [("khome", (KHome, [])),
140+
141+ caps_tabls = [("khome", (KHome, [])),
142142 ("kend", (KEnd, [])),
143143 ("cbt", (KBackTab, [])),
144144 ("kcud1", (KDown, [])),
@@ -149,9 +149,9 @@ initTermInput escDelay terminal = do
149149 ("kLFT", (KLeft, [MShift])),
150150 ("kRIT", (KRight, [MShift]))
151151 ]
152−
152+
153153 caps_classify_table = [(x,y) | (Just x,y) <- map (first (getCapability terminal . tiGetStr)) $ caps_tabls]
154−
154+
155155 ansi_classify_table :: [[([Char], (Key, [Modifier]))]]
156156 ansi_classify_table =
157157 [ let k c s = ("\ESC["++c,(s,[])) in [ k "G" KNP5
@@ -159,22 +159,27 @@ initTermInput escDelay terminal = do
159159 , k "A" KUp
160160 , k "B" KDown
161161 , k "C" KRight
162− , k "D" KLeft
162+ , k "D" KLeft
163163 , k "H" KHome
164164 , k "F" KEnd
165165 , k "E" KBegin
166166 ],
167167
168− -- Support for arrows
169− [("\ESC[" ++ charCnt ++ show mc++c,(s,m))
168+ -- Support for arrows and KHome/KEnd
169+ [("\ESC[" ++ charCnt ++ show mc++c,(s,m))
170170 | charCnt <- ["1;", ""], -- we can have a count or not
171− (m,mc) <- [([MShift],2::Int), ([MCtrl],5), ([MMeta],3),
171+ (m,mc) <- [([MShift],2::Int), ([MCtrl],5), ([MMeta],3),
172172 ([MShift, MCtrl],6), ([MShift, MMeta],4)], -- modifiers and their codes
173− (c,s) <- [("A", KUp), ("B", KDown), ("C", KRight), ("D", KLeft)] -- directions and their codes
173+ (c,s) <- [("A", KUp), ("B", KDown), ("C", KRight), ("D", KLeft), ("H", KHome), ("F", KEnd)] -- directions and their codes
174174 ],
175−
176− let k n s = ("\ESC["++show n++"~",(s,[])) in zipWith k [2::Int,3,5,6,1,4]
177− [KIns,KDel,KPageUp,KPageDown,KHome,KEnd],
175+
176+ let k n s = ("\ESC["++show n++"~",(s,[]))
177+ in zipWith k [2::Int,3,5,6,1,4]
178+ [KIns,KDel,KPageUp,KPageDown,KHome,KEnd],
179+
180+ let k n s = ("\ESC["++show n++";5~",(s,[MCtrl]))
181+ in zipWith k [2::Int,3,5,6,1,4]
182+ [KIns,KDel,KPageUp,KPageDown,KHome,KEnd],
178183
179184 -- Support for simple characters.
180185 [ (x:[],(KASCII x,[])) | x <- map toEnum [0..255] ],
@@ -186,25 +191,25 @@ initTermInput escDelay terminal = do
186191 [ ('\ESC':[x],(KASCII x,[MMeta])) | x <- '\ESC':'\t':[' ' .. '\DEL'] ],
187192
188193 -- Ctrl+Char
189− [ ([toEnum x],(KASCII y,[MCtrl]))
194+ [ ([toEnum x],(KASCII y,[MCtrl]))
190195 | (x,y) <- zip ([0..31]) ('@':['a'..'z']++['['..'_']),
191196 y /= 'i' -- Resolve issue #3 where CTRL-i hides TAB.
192197 ],
193−
198+
194199 -- Ctrl+Meta+Char
195200 [ ('\ESC':[toEnum x],(KASCII y,[MMeta,MCtrl])) | (x,y) <- zip [0..31] ('@':['a'..'z']++['['..'_']) ],
196201
197202 -- Special support
198− [ -- special support for ESC
199− ("\ESC",(KEsc,[])) , ("\ESC\ESC",(KEsc,[MMeta])),
203+ [ -- special support for ESC
204+ ("\ESC",(KEsc,[])) , ("\ESC\ESC",(KEsc,[MMeta])),
200205
201206 -- Special support for backspace
202207 ("\DEL",(KBS,[])), ("\ESC\DEL",(KBS,[MMeta])),
203−
208+
204209 -- Special support for Enter
205− ("\ESC\^J",(KEnter,[MMeta])), ("\^J",(KEnter,[])) ]
210+ ("\ESC\^J",(KEnter,[MMeta])), ("\^J",(KEnter,[])) ]
206211 ]
207−
212+
208213 eventThreadId <- forkIO $ inputToEventThread
209214 inputThreadId <- forkIO $ inputThread
210215 noInputThreadId <- forkIO $ noInputThread
@@ -225,11 +230,10 @@ first :: (a -> b) -> (a,c) -> (b,c)
225230first f (x,y) = (f x, y)
226231
227232utf8Length :: (Num t, Ord a, Num a) => a -> t
228−utf8Length c
233+utf8Length c
229234 | c < 0x80 = 1
230235 | c < 0xE0 = 2
231236 | c < 0xF0 = 3
232237 | otherwise = 4
233238
234239foreign import ccall "set_term_timing" set_term_timing :: IO ()
235−