roguestar-gl-0.6.0.0: src/KeyStroke.hs
{-# LANGUAGE OverloadedStrings, GeneralizedNewtypeDeriving #-}
module KeyStroke
(KeyStroke(..),
KeyString,
asString,
prettyString,
keyStroke,
KeyStroke.null,
KeyStroke.init,
KeyStroke.length,
KeyStroke.isSuffixOf,
KeyStroke.inits)
where
import qualified Data.ByteString.Char8 as B
import Data.String
import Data.Char
import Data.Monoid
import qualified Data.List as List
data KeyStroke =
Stroke Char
| KeyUp
| KeyDown
| KeyLeft
| KeyRight
| KeyActivate -- spacebar, and any enter key
| KeyEscape -- escape, delete, backspace, etc
| KeyTab -- tab and any key that might be used for completions
| KeyAmpersand
| KeySemicolon
| NumPad1
| NumPad2
| NumPad3
| NumPad4
| NumPad5
| NumPad6
| NumPad7
| NumPad8
| NumPad9
| NumPad0
| KeyIgnored
deriving (Eq,Read,Show)
newtype KeyString = KeyString { fromKeyString :: [KeyStroke] }
deriving (Eq,Read,Show,Monoid)
null :: KeyString -> Bool
null = Prelude.null . fromKeyString
init :: KeyString -> KeyString
init = KeyString . Prelude.init . fromKeyString
inits :: KeyString -> [KeyString]
inits = map KeyString . List.inits . fromKeyString
length :: KeyString -> Int
length = Prelude.length . fromKeyString
isSuffixOf :: KeyString -> KeyString -> Bool
isSuffixOf a b = fromKeyString a `List.isSuffixOf` fromKeyString b
keyStroke :: KeyStroke -> KeyString
keyStroke s = KeyString [s]
prettyString :: KeyString -> String
prettyString (KeyString ks) = concatMap f ks
where f (Stroke c) = [c]
f KeyUp = "[UP]"
f KeyDown = "[DOWN]"
f KeyLeft = "[LEFT]"
f KeyRight = "[RIGHT]"
f KeyActivate = "[ENTER]"
f KeyEscape = "[ESC]"
f KeyTab = "^T"
f KeyAmpersand = "&"
f KeySemicolon = ";"
f NumPad1 = "[1]"
f NumPad2 = "[2]"
f NumPad3 = "[3]"
f NumPad4 = "[4]"
f NumPad5 = "[5]"
f NumPad6 = "[6]"
f NumPad7 = "[7]"
f NumPad8 = "[8]"
f NumPad9 = "[9]"
f KeyIgnored = "[IGNORED]"
asString :: (IsString s) => KeyString -> s
asString = fromString . asString_
where asString_ (KeyString []) = []
asString_ (KeyString (Stroke c: rest)) = c:asString (KeyString rest)
asString_ (KeyString (KeyIgnored:rest)) = asString_ (KeyString rest)
asString_ (KeyString (s:rest)) = "&" ++ show s ++ ";" ++ asString (KeyString rest)
instance IsString KeyString where
fromString s = KeyString $ fromString_ s
fromString_ :: String -> [KeyStroke]
fromString_ [] = []
fromString_ ('\n':rest) = KeyActivate:fromString_ rest
fromString_ ('\r':rest) = KeyActivate:fromString_ rest
fromString_ ('\t':rest) = KeyTab:fromString_ rest
fromString_ ('\ESC':rest) = KeyEscape:fromString_ rest
fromString_ ('&':rest) | ';' `elem` rest =
key_string : fromString_ (drop 1 $ dropWhile (/= ';') rest)
where key_string = case map toUpper (takeWhile (/= ';') rest) of
"KEYUP" -> KeyUp
"KEYDOWN" -> KeyDown
"KEYLEFT" -> KeyLeft
"KEYRIGHT" -> KeyRight
"KEYACTIVATE" -> KeyActivate
"KEYESCAPE" -> KeyEscape
"KEYTAB" -> KeyTab
"NUMPAD1" -> NumPad1
"NUMPAD2" -> NumPad2
"NUMPAD3" -> NumPad3
"NUMPAD4" -> NumPad4
"NUMPAD5" -> NumPad5
"NUMPAD6" -> NumPad6
"NUMPAD7" -> NumPad7
"NUMPAD8" -> NumPad8
"NUMPAD9" -> NumPad9
"NUMPAD0" -> NumPad0
_ -> KeyIgnored
fromString_ ('&':rest) = KeyAmpersand:fromString_ rest
fromString_ (';':rest) = KeySemicolon:fromString_ rest
fromString_ (c:rest) = Stroke c:fromString_ rest