{-# LANGUAGE CPP #-} #if __GLASGOW_HASKELL__ >= 700 {-# LANGUAGE DeriveDataTypeable #-} #endif #if __GLASGOW_HASKELL__ >= 702 {-# LANGUAGE DeriveGeneric #-} #endif #if __GLASGOW_HASKELL__ >= 800 {-# LANGUAGE DeriveLift #-} #endif {-| Module: Web.KeyCode Copyright: (C) 2015-2016 Ryan Scott License: BSD-style (see the file LICENSE) Maintainer: Ryan Scott Stability: Experimental Portability: Portable Keyboard events in web browsers are often represented as keycodes, which (1) are difficult to remember, and (2) sometimes vary from browser to browser. This module allows one to look up a key press's 'KeyCode' and get a plain English description of the 'Key' that was pressed, to reduce confusion. /Since: 0.1/ -} module Web.KeyCode (Key(..), KeyCode, keyCodeLookup, keyCodeMap, isKeyCode) where import Data.IntMap (IntMap, findWithDefault, fromAscList) import Data.Ix (Ix) #if __GLASGOW_HASKELL__ >= 700 import Data.Data (Data, Typeable) #endif #if __GLASGOW_HASKELL__ >= 702 import GHC.Generics (Generic) #endif #if __GLASGOW_HASKELL__ >= 800 import Language.Haskell.TH.Syntax (Lift) #endif -- | A numeric code representing the value of a pressed 'Key'. Note that a particular -- 'Key' may not uniquely map to a particular 'KeyCode', as the implementation of -- key codes is browser-dependent. -- -- /Since: 0.1/ type KeyCode = Int -- | Represents a typical keyboard's keys. The lowercase and uppercase variants of any -- particular key have the same 'KeyCode', so there are not separate constructors for -- them. There is also an 'UnknownKey' constructor for keys without a particular -- 'KeyCode'. -- -- Note that the 'Enum' instance does not correspond to the 'KeyCode's, but is simply -- provided for convenience. -- -- /Since: 0.1/ data Key = Backspace | Tab | NumLock | Enter | Shift | Control | Alt | Pause | CapsLock | Escape | Space | PageUp | PageDown | End | Home | ArrowLeft | ArrowUp | ArrowRight | ArrowDown | PrintScreen | Insert | Delete | Digit0 -- ^ Without Shift: @0@. With Shift: @)@. | Digit1 -- ^ Without Shift: @1@. With Shift: @!@. | Digit2 -- ^ Without Shift: @2@. With Shift: @\@@. | Digit3 -- ^ Without Shift: @3@. With Shift: @#@. | Digit4 -- ^ Without Shift: @4@. With Shift: @$@. | Digit5 -- ^ Without Shift: @5@. With Shift: @%@. | Digit6 -- ^ Without Shift: @6@. With Shift: @^@. | Digit7 -- ^ Without Shift: @7@. With Shift: @&@. | Digit8 -- ^ Without Shift: @8@. With Shift: @*@. | Digit9 -- ^ Without Shift: @9@. With Shift: @(@. | KeyA -- ^ Without Shift: @a@. With Shift: @A@. | KeyB -- ^ Without Shift: @b@. With Shift: @B@. | KeyC -- ^ Without Shift: @c@. With Shift: @C@. | KeyD -- ^ Without Shift: @d@. With Shift: @D@. | KeyE -- ^ Without Shift: @e@. With Shift: @E@. | KeyF -- ^ Without Shift: @f@. With Shift: @F@. | KeyG -- ^ Without Shift: @g@. With Shift: @G@. | KeyH -- ^ Without Shift: @h@. With Shift: @H@. | KeyI -- ^ Without Shift: @i@. With Shift: @I@. | KeyJ -- ^ Without Shift: @j@. With Shift: @J@. | KeyK -- ^ Without Shift: @k@. With Shift: @K@. | KeyL -- ^ Without Shift: @l@. With Shift: @L@. | KeyM -- ^ Without Shift: @m@. With Shift: @M@. | KeyN -- ^ Without Shift: @n@. With Shift: @N@. | KeyO -- ^ Without Shift: @o@. With Shift: @O@. | KeyP -- ^ Without Shift: @p@. With Shift: @P@. | KeyQ -- ^ Without Shift: @q@. With Shift: @Q@. | KeyR -- ^ Without Shift: @r@. With Shift: @R@. | KeyS -- ^ Without Shift: @s@. With Shift: @S@. | KeyT -- ^ Without Shift: @t@. With Shift: @T@. | KeyU -- ^ Without Shift: @u@. With Shift: @U@. | KeyV -- ^ Without Shift: @v@. With Shift: @V@. | KeyW -- ^ Without Shift: @w@. With Shift: @W@. | KeyX -- ^ Without Shift: @x@. With Shift: @X@. | KeyY -- ^ Without Shift: @y@. With Shift: @Y@. | KeyZ -- ^ Without Shift: @z@. With Shift: @Z@. | Command -- ^ Might also be the Windows key or the Super key | Numpad0 | Numpad1 | Numpad2 | Numpad3 | Numpad4 | Numpad5 | Numpad6 | Numpad7 | Numpad8 | Numpad9 | NumpadMultiply | NumpadAdd | NumpadEnter | NumpadSubtract | NumpadDecimal | NumpadDivide | F1 | F2 | F3 | F4 | F5 | F6 | F7 | F8 | F9 | F10 | F11 | F12 | ScrollLock | Semicolon -- ^ Without Shift: @;@. With Shift: @:@. | Equals -- ^ Without Shift: @=@. With Shift: @+@. | Comma -- ^ Without Shift: @,@. With Shift: @<@. | Subtract -- ^ Without Shift: @-@. With Shift: @_@. | Period -- ^ Without Shift: @.@. With Shift: @>@. | ForwardSlash -- ^ Without Shift: @/@. With Shift: @?@. | Backquote -- ^ Without Shift: @`@. With Shift: @~@. | BracketLeft -- ^ Without Shift: @[@. With Shift: @{@. | Backslash -- ^ Without Shift: @\\@. With Shift: @|@. | BracketRight -- ^ Without Shift: @]@. With Shift: @}@. | Apostrophe -- ^ Without Shift: @\'@. With Shift: @"@. | UnknownKey deriving ( Bounded , Enum , Eq , Ix , Ord , Read , Show #if __GLASGOW_HASKELL__ >= 700 , Data , Typeable #endif #if __GLASGOW_HASKELL__ >= 702 , Generic #endif #if __GLASGOW_HASKELL__ >= 800 , Lift #endif ) -- | Determine the 'Key' that a 'KeyCode' represents. If one cannot be found, -- 'UnknownKey' is returned. -- -- /Since: 0.1/ keyCodeLookup :: KeyCode -> Key keyCodeLookup key = findWithDefault UnknownKey key keyCodeMap -- | An map of known 'KeyCode's to 'Key's. -- -- /Since: 0.1/ keyCodeMap :: IntMap Key keyCodeMap = fromAscList [ -- Thanks to David Mauro for his keyCode mapping from the Keypress library -- (https://github.com/dmauro/Keypress/blob/e5e95070d81b998b02b2d7f096267b114a3771d7/keypress.coffee#L802-L916) -- Licensed under the Apache License, version 2.0 ( 8, Backspace ) , ( 9, Tab ) , ( 12, NumLock ) , ( 13, Enter ) , ( 16, Shift ) , ( 17, Control ) , ( 18, Alt ) , ( 19, Pause ) , ( 20, CapsLock ) , ( 27, Escape ) , ( 32, Space ) , ( 33, PageUp ) , ( 34, PageDown ) , ( 35, End ) , ( 36, Home ) , ( 37, ArrowLeft ) , ( 38, ArrowUp ) , ( 39, ArrowRight ) , ( 40, ArrowDown ) , ( 44, PrintScreen ) , ( 45, Insert ) , ( 46, Delete ) , ( 48, Digit0 ) , ( 49, Digit1 ) , ( 50, Digit2 ) , ( 51, Digit3 ) , ( 52, Digit4 ) , ( 53, Digit5 ) , ( 54, Digit6 ) , ( 55, Digit7 ) , ( 56, Digit8 ) , ( 57, Digit9 ) , ( 59, Semicolon ) -- Firefox oddity , ( 61, Equals ) -- Firefox oddity , ( 65, KeyA ) , ( 66, KeyB ) , ( 67, KeyC ) , ( 68, KeyD ) , ( 69, KeyE ) , ( 70, KeyF ) , ( 71, KeyG ) , ( 72, KeyH ) , ( 73, KeyI ) , ( 74, KeyJ ) , ( 75, KeyK ) , ( 76, KeyL ) , ( 77, KeyM ) , ( 78, KeyN ) , ( 79, KeyO ) , ( 80, KeyP ) , ( 81, KeyQ ) , ( 82, KeyR ) , ( 83, KeyS ) , ( 84, KeyT ) , ( 85, KeyU ) , ( 86, KeyV ) , ( 87, KeyW ) , ( 88, KeyX ) , ( 89, KeyY ) , ( 90, KeyZ ) , ( 91, Command ) , ( 92, Command ) , ( 93, Command ) , ( 96, Numpad0 ) , ( 97, Numpad1 ) , ( 98, Numpad2 ) , ( 99, Numpad3 ) , (100, Numpad4 ) , (101, Numpad5 ) , (102, Numpad6 ) , (103, Numpad7 ) , (104, Numpad8 ) , (105, Numpad9 ) , (106, NumpadMultiply) , (107, NumpadAdd ) , (108, NumpadEnter ) , (109, NumpadSubtract) , (110, NumpadDecimal ) , (111, NumpadDivide ) , (112, F1 ) , (113, F2 ) , (114, F3 ) , (115, F4 ) , (116, F5 ) , (117, F6 ) , (118, F7 ) , (119, F8 ) , (120, F9 ) , (121, F10 ) , (122, F11 ) , (123, F12 ) , (124, PrintScreen ) , (144, NumLock ) , (145, ScrollLock ) , (173, Subtract ) -- Firefox oddity , (186, Semicolon ) , (187, Equals ) , (188, Comma ) , (189, Subtract ) , (190, Period ) , (191, ForwardSlash ) , (192, Backquote ) , (219, BracketLeft ) , (220, Backslash ) , (221, BracketRight ) , (222, Apostrophe ) , (223, Backquote ) , (224, Command ) , (225, Alt ) ] -- | Return 'True' if the given 'KeyCode' matches the given 'Key'. -- -- /Since: 0.2.2/ isKeyCode :: Key -> KeyCode -> Bool isKeyCode key code = key == keyCodeLookup code