kmonad-0.4.1: src/KMonad/Keyboard.hs
{-# LANGUAGE DeriveAnyClass #-}
{-|
Module : KMonad.Keyboard
Description : Basic keyboard types
Copyright : (c) David Janssen, 2019
License : MIT
Maintainer : janssen.dhj@gmail.com
Stability : experimental
Portability : portable
This module contains or reexports all the basic, non-IO concepts related to
dealing with key codes, events, and mappings. For keyboard-related IO see
"KMonad.Keyboard.IO".
-}
module KMonad.Keyboard
( -- * KeyEvents and their helpers
-- $event
Switch(..)
, KeyEvent
, switch
, keycode
, mkKeyEvent
, mkPress
, mkRelease
-- * Predicates
, KeyPred
, isPress
, isRelease
, isKeycode
, isPressOf
, isReleaseOf
-- * LMaps
-- $lmap
, LayerTag
, LMap
-- * Reexports
, module KMonad.Keyboard.Keycode
)
where
import KMonad.Prelude
import KMonad.Keyboard.Keycode
import qualified Data.LayerStack as Ls
--------------------------------------------------------------------------------
-- $event
--
-- An 'KeyEvent' in KMonad is either the 'Press' or 'Release' of a particular
-- 'Keycode'. A complete list of keycodes can be found in
-- "KMonad.Keyboard.Keycode".
-- | KMonad recognizes 2 different types of actions: presses and releases. Note
-- that we do not handle repeat events at all.
data Switch
= Press
| Release
deriving (Eq, Ord, Show, Enum, Generic, Hashable)
-- | An 'KeyEvent' is a 'Switch' on a particular 'Keycode'
data KeyEvent = KeyEvent
{ _switch :: Switch -- ^ Whether the 'KeyEvent' was a 'Press' or 'Release'
, _keycode :: Keycode -- ^ The 'Keycode' mapped to this 'KeyEvent'
} deriving (Eq, Show, Generic, Hashable)
makeLenses ''KeyEvent
-- | A 'Display' instance for 'KeyEvent's that prints them out nicely.
instance Display KeyEvent where
textDisplay a = tshow (a^.switch) <> " " <> textDisplay (a^.keycode)
-- | An 'Ord' instance, where Press > Release, and otherwise we 'Ord' on the
-- 'Keycode'
instance Ord KeyEvent where
a `compare` b = case (a^.switch) `compare` (b^.switch) of
EQ -> (a^.keycode) `compare` (b^.keycode)
x -> x
-- | Create a new 'KeyEvent' from a 'Switch' and a 'Keycode'
mkKeyEvent :: Switch -> Keycode -> KeyEvent
mkKeyEvent = KeyEvent
-- | Create a 'KeyEvent' that represents pressing a key
mkPress :: Keycode -> KeyEvent
mkPress = KeyEvent Press
-- | Create a 'KeyEvent' that represents releaseing a key
mkRelease :: Keycode -> KeyEvent
mkRelease = KeyEvent Release
-- | Predicate on KeyEvent's
type KeyPred = KeyEvent -> Bool
-- | Return whether the provided KeyEvent is a Press
isPress :: KeyPred
isPress = (== Press) . view switch
-- | Return whether the provided KeyEvent is a Release
isRelease :: KeyPred
isRelease = not . isPress
-- | Return whether the provided KeyEvent matches a particular Keycode
isKeycode :: Keycode -> KeyPred
isKeycode c = (== c) . view keycode
-- | Returth whether the provided KeyEvent matches the release of the Keycode
isReleaseOf :: Keycode -> KeyPred
isReleaseOf = (==) . mkRelease
-- | Return whether the provided KeyEvent matches the press of the Keycode
isPressOf :: Keycode -> KeyPred
isPressOf = (==) . mkPress
--------------------------------------------------------------------------------
-- $lmap
--
-- Type aliases for specifying stacked-layer mappings
-- | Layers are identified by a tag that is simply a 'Text' value.
type LayerTag = Text
-- | 'LMap's are mappings from 'LayerTag'd maps from 'Keycode' to things.
type LMap a = Ls.LayerStack LayerTag Keycode a