hbro-1.2.0.0: library/Hbro/Keys.hs
{-# LANGUAGE TemplateHaskell, TupleSections, ViewPatterns #-}
-- | Key bindings model.
-- Designed to be imported as @qualified@.
module Hbro.Keys (
-- * Modifiers
Modifier(..)
, _Alt
, _Control
, _Shift
, modifier
-- * Mode
, Mode(..)
-- * Bindings implementation
, KeyStroke
, keyStroke
, Bindings
, Status
, Hooks
, statusL
, onKeyPressedL
-- * Interface
, HasHooks(..)
, initializeHooks
, Hbro.Keys.set
) where
-- {{{ Imports
import Hbro.Gdk.KeyVal
import Hbro.Keys.Model ((.|), modifiersL, keyL)
import qualified Hbro.Keys.Model as Model
import Hbro.Prelude
import Control.Lens.Getter
import Control.Lens.Lens
import Control.Lens.Setter
import Control.Lens.TH
import Control.Monad.Reader hiding(forM_, guard, mapM_)
import Data.List.NonEmpty (NonEmpty(..))
import qualified Data.Set as Set
import qualified Graphics.UI.Gtk.Gdk.EventM as Gdk
import Text.Parsec
import Text.Parsec.Text
-- }}}
-- {{{ Modifiers
newtype Modifier = Modifier Gdk.Modifier deriving(Eq)
instance Describable Modifier where
describe (Modifier Gdk.Control) = "C-"
describe (Modifier Gdk.Shift) = "S-"
describe (Modifier Gdk.Alt) = "M-"
describe (Modifier _) = ""
instance Ord Modifier where compare = comparing describe
instance ToSet Modifier Modifier where toSet = Set.singleton
_Alt, _Control, _Shift :: Modifier
_Alt = Modifier Gdk.Alt
_Control = Modifier Gdk.Control
_Shift = Modifier Gdk.Shift
modifier :: Parser Modifier
modifier = spaces *> choice [ string "C-" >> return _Control
, string "M-" >> return _Alt
-- , string "S-" >> return _Shift
]
-- }}}
-- {{{ Key mode (à la vi)
data Mode = Normal | Insert deriving(Eq, Ord)
instance Default Mode where def = Normal
-- }}}
-- {{{ Bindings implementation
type KeyStroke = Model.KeyStroke Modifier KeyVal
instance Describable KeyStroke where
describe s = foldr (++) "" (map describe . Set.toList $ s^.modifiersL) ++ describe (s^.keyL)
instance ToNonEmpty KeyStroke KeyStroke where
toNonEmpty x = x :| []
instance ToNonEmpty KeyStroke KeyVal where
toNonEmpty x = ((Set.empty .| x) :| [])
keyStroke :: Parser KeyStroke
keyStroke = do
spaces
m <- maybe Set.empty Set.singleton <$> optionMaybe modifier
k <- keyVal
return $ Model.KeyStroke m k
-- type Binding m = Model.Binding Hbro.Keys.Stroke (m ())
type Bindings m = Model.Bindings KeyStroke (m ())
type Status m = Model.Status KeyStroke Mode (m ())
data Hooks m = Hooks
{ _status :: TVar (Status m)
, _onKeyPressed :: TMVar ([KeyStroke] -> m ())
}
makeLensesWith ?? ''Hooks $ lensRules
& lensField .~ (\name -> Just (tail name ++ "L"))
class HasHooks m t | t -> m where _hooks :: Lens' t (Hooks m)
instance HasHooks m (Hooks m) where _hooks = id
initializeHooks :: IO (Hooks m)
initializeHooks = Hooks <$> newTVarIO def <*> newEmptyTMVarIO
set :: (BaseIO m, MonadReader r m, HasHooks n r) => Lens' (Hooks n) (TMVar a) -> a -> m ()
set l v = atomically . (`writeTMVar` v) =<< askL (_hooks.l)
-- }}}
{-instance Monoid KeyMap where
mempty = KeyBindings M.empty
mappend (KeyBindings a) (KeyBindings b) = KeyBindings (mappend a b)-}