@@ -1,15 +1,178 @@
11module Graphics.Vty.Input.Terminfo where
22
3−import Graphics.Vty.Input.Data
4−import Graphics.Vty.Input.Internal
3+import Graphics.Vty.Input.Events
4+import qualified Graphics.Vty.Input.Terminfo.VT100 as VT100
5+import qualified Graphics.Vty.Input.Terminfo.XTerm7Bit as XTerm7Bit
56
67import System.Console.Terminfo
78
9+-- | queries the terminal for all capability based input sequences then adds on a terminal dependent
10+-- input sequence mapping.
11+--
12+-- For reference see:
13+--
14+-- * http://vimdoc.sourceforge.net/htmldoc/term.html
15+--
16+-- * vim74/src/term.c
17+--
18+-- * http://invisible-island.net/vttest/
19+--
20+-- * http://aperiodic.net/phil/archives/Geekery/term-function-keys.html
21+--
22+-- This is painful. Terminfo is incomplete. The vim source implies that terminfo is also incorrect.
23+-- Vty assumes that the an internal terminfo table added to the system provided terminfo table is
24+-- correct.
25+--
26+-- 1. build terminfo table for all caps. Missing caps are not added.
27+--
28+-- 2. add tables for visible chars, esc, del plus ctrl and meta.
29+--
30+-- 3. add internally defined table for given terminal type.
31+--
32+-- The override is currently done in 'compile'. Which is a bit odd.
33+--
34+-- \todo terminfo meta is not supported.
35+-- \todo no 8bit
36+classify_table_for_term :: String -> Terminal -> ClassifyTableV1
37+classify_table_for_term term_name term =
38+ concatMap map_to_legacy_table
39+ $ caps_classify_table term keys_from_caps_table
40+ : visible_chars
41+ : ctrl_chars
42+ : ctrl_meta_chars
43+ : special_support_keys
44+ : internal_tables term_name
45+
846caps_classify_table :: Terminal -> [(String,Event)] -> [(String,Event)]
947caps_classify_table terminal table = [(x,y) | (Just x,y) <- map extract_cap table]
1048 where extract_cap = first (getCapability terminal . tiGetStr)
1149
12−classify_table_for_term :: Terminal -> ClassifyTableV1
13−classify_table_for_term term =
14− let caps_legacy_table = map_to_legacy_table $ caps_classify_table term keys_from_caps_table
15− in concat $ caps_legacy_table : ansi_classify_table
50+internal_tables term_name
51+ | ANSI.supports term_name = ANSI.tables
52+ | XTerm7Bit.supports term_name = XTerm7Bit.tables
53+ | otherwise = []
54+
55+-- | Visible characters in the ISO-8859-1 and UTF-8 common set.
56+--
57+-- we limit to < 0xC1. The UTF8 sequence detector will catch all values 0xC2 and above before this
58+-- classify table is reached.
59+--
60+-- TODO: resolve
61+-- 1. start at ' '. The earlier characters are all ctrl_char_keys
62+visible_chars :: ClassifyTable
63+visible_chars = [ ([x], EvKey (KChar x) [])
64+ | x <- [' ' .. toEnum 0xC1]
65+ ]
66+
67+-- | Non visible cahracters in the ISO-8859-1 and UTF-8 common set translated to ctrl + char.
68+--
69+-- \todo resolve CTRL-i is the same as tab
70+ctrl_chars :: ClassifyTable
71+ctrl_chars =
72+ [ ([toEnum x],EvKey (KChar y) [MCtrl])
73+ | (x,y) <- zip ([0..31]) ('@':['a'..'z']++['['..'_']),
74+ y /= 'i' -- Resolve issue #3 where CTRL-i hides TAB.
75+ ]
76+
77+-- | Ctrl+Meta+Char
78+ctrl_meta_chars :: ClassifyTable
79+ctrl_meta_chars = map (\(s,EvKey c m) -> ('\ESC':s, EvKey c (MMeta:m)))
80+
81+-- | esc, meta esc, delete, meta delete, enter, meta enter
82+special_support_keys :: ClassifyTable
83+special_support_keys =
84+ [ -- special support for ESC
85+ ("\ESC",EvKey KEsc []), ("\ESC\ESC",EvKey KEsc [MMeta])
86+ -- Special support for backspace
87+ , ("\DEL",EvKey KBS []), ("\ESC\DEL",EvKey KBS [MMeta])
88+ -- Special support for Enter
89+ , ("\ESC\^J",EvKey KEnter [MMeta]), ("\^J",EvKey KEnter [])
90+ ]
91+
92+-- | classify table directly generated from terminfo cap strings
93+--
94+-- these are:
95+--
96+-- * ka1 - keypad up-left
97+--
98+-- * ka3 - keypad up-right
99+--
100+-- * kb2 - keypad center
101+--
102+-- * kbs - keypad backspace
103+--
104+-- * kbeg - begin
105+--
106+-- * kcbt - back tab
107+--
108+-- * kc1 - keypad left-down
109+--
110+-- * kc3 - keypad right-down
111+--
112+-- * kdch1 - delete
113+--
114+-- * kcud1 - down
115+--
116+-- * kend - end
117+--
118+-- * kent - enter
119+--
120+-- * kf0 - kf63 - function keys
121+--
122+-- * khome - KHome
123+--
124+-- * kich1 - insert
125+--
126+-- * kcub1 - left
127+--
128+-- * knp - next page (page down)
129+--
130+-- * kpp - previous page (page up)
131+--
132+-- * kcuf1 - right
133+--
134+-- * kDC - shift delete
135+--
136+-- * kEND - shift end
137+--
138+-- * kHOM - shift home
139+--
140+-- * kIC - shift insert
141+--
142+-- * kLFT - shift left
143+--
144+-- * kRIT - shift right
145+--
146+-- * kcuu1 - up
147+keys_from_caps_table :: ClassifyTable
148+keys_from_caps_table =
149+ [ ("ka1", EvKey KUpLeft [])
150+ , ("ka3", EvKey KUpRight [])
151+ , ("kb2", EvKey KCenter [])
152+ , ("kbs", EvKey KBS [])
153+ , ("kbeg", EvKey KBegin [])
154+ , ("kcbt", EvKey KBackTab [])
155+ , ("kc1", EvKey KDownLeft [])
156+ , ("kc3", EvKey KDownRight [])
157+ , ("kdch1", EvKey KDel [])
158+ , ("kcud1", EvKey KDown [])
159+ , ("kend", EvKey KEnd [])
160+ , ("kent", EvKey KEnter [])
161+ , ("khome", EvKey KHome [])
162+ , ("kich1", EvKey KIns [])
163+ , ("kcub1", EvKey KLeft [])
164+ , ("knp", EvKey KPageDown [])
165+ , ("kpp", EvKey KPageUp [])
166+ , ("kcuf1", EvKey KRight [])
167+ , ("kDC", EvKey KDel [MShift])
168+ , ("kEND", EvKey KEnd [MShift])
169+ , ("kHOM", EvKey KHome [MShift])
170+ , ("kIC", EvKey KIns [MShift])
171+ , ("kLFT", EvKey KLeft [MShift])
172+ , ("kRIT", EvKey KRight [MShift])
173+ , ("kcuu1", EvKey KUp [])
174+ ] ++ function_key_caps_table
175+
176+-- | cap names for function keys
177+function_key_caps_table :: ClassifyTable
178+function_key_caps_table = flip map [0..63] $ \n -> ("kf" ++ show n, EvKey (KFun n) [])