module Graphics.Vty.Input.Classify where
import Graphics.Vty.Input.Events
import Codec.Binary.UTF8.Generic (decode)
import Data.List(tails,inits)
import qualified Data.Map as M( fromList, lookup )
import Data.Maybe ( mapMaybe )
import qualified Data.Set as S( fromList, member )
import Data.Char
import Data.Word
data KClass
= Valid Event [Char]
| Invalid
| Prefix
deriving(Show, Eq)
compile :: ClassifyMap -> [Char] -> KClass
compile table = cl' where
prefixSet = S.fromList $ concatMap (init . inits . fst) $ table
eventForInput = M.fromList table
cl' [] = Prefix
cl' inputBlock = case M.lookup inputBlock eventForInput of
Just e -> Valid e []
Nothing -> case S.member inputBlock prefixSet of
True -> Prefix
False ->
let inputTails = init $ tail $ tails inputBlock
in case mapMaybe (\s -> (,) s `fmap` M.lookup s eventForInput) inputTails of
(s,e) : _ -> Valid e (drop (length s) inputBlock)
[] -> Invalid
classify, classifyTab :: ClassifyMap -> [Char] -> KClass
classify _table s@(c:_) | ord c >= 0xC2
= if utf8Length (ord c) > length s then Prefix else classifyUtf8 s
classify table other
= classifyTab table other
classifyUtf8 :: [Char] -> KClass
classifyUtf8 s = case decode ((map (fromIntegral . ord) s) :: [Word8]) of
Just (unicodeChar, _) -> Valid (EvKey (KChar unicodeChar) []) []
_ -> Invalid
classifyTab table = compile table
first :: (a -> b) -> (a,c) -> (b,c)
first f (x,y) = (f x, y)
utf8Length :: (Num t, Ord a, Num a) => a -> t
utf8Length c
| c < 0x80 = 1
| c < 0xE0 = 2
| c < 0xF0 = 3
| otherwise = 4