{-# LANGUAGE TemplateHaskell #-} -- | provides the parser functions module EmacsKeys.Parser (Modifier(..) ,parseEmacsKeys) where import Data.Char import Data.Either import Data.List.Split import Language.Haskell.TH.Lift import Text.XkbCommon -- | Represents the accepted modifiers 'C','M','S' data Modifier = Ctrl | Meta | Shift deriving (Show,Eq,Ord) deriveLift ''Modifier parseModifier :: String -> Either Modifier String parseModifier s = case lookup s modifiers of Just m -> Left m Nothing -> Right s parseKeys :: [Either Modifier String] -> Either String ([Modifier],[Keysym]) parseKeys keys = fmap (\keysyms -> (mods,keysyms)) $ sequence $ fmap (parseKeysym . if shift then fmap toUpper else id) $ unparsedSyms where (mods,unparsedSyms) = partitionEithers keys shift = Shift `elem` mods parseKeysym :: String -> Either String Keysym parseKeysym s = case keysymFromName s of Just ks -> Right ks Nothing -> Left $ "Invalid key: \"" ++ s ++ "\"" -- | Parse a string into a list of modifiers and keysyms -- If Shift is part of the modifiers, the keysyms are converted to upper case -- -- >>> parseEmacsKeys "M-a" -- Right ([Meta],[Keysym 97]) -- -- >>> parseEmacsKeys "Return" -- Right ([],[Keysym 65293]) -- -- >>> parseEmacsKeys "S-a" -- Right ([Shift],[Keysym 65]) parseEmacsKeys :: String -> Either String ([Modifier],[Keysym]) parseEmacsKeys = parseKeys . fmap parseModifier . splitOn "-" modifiers :: [(String,Modifier)] modifiers = [("C",Ctrl),("M",Meta),("S",Shift)]