module KMonad.App.Keymap
( Keymap
, mkKeymap
, layerOp
, lookupKey
)
where
import KMonad.Prelude
import KMonad.Action hiding (layerOp)
import KMonad.Button
import KMonad.Keyboard
import KMonad.App.BEnv
import qualified Data.LayerStack as Ls
data Keymap = Keymap
{ _stack :: IORef (LMap BEnv)
, _baseL :: IORef LayerTag
}
makeClassy ''Keymap
mkKeymap' :: MonadUnliftIO m
=> LayerTag
-> LMap Button
-> m Keymap
mkKeymap' n m = do
envs <- m & Ls.items . itraversed %%@~ \(_, c) b -> initBEnv b c
Keymap <$> newIORef envs <*> newIORef n
mkKeymap :: MonadUnliftIO m => LayerTag -> LMap Button -> ContT r m Keymap
mkKeymap n = lift . mkKeymap' n
debugReport :: HasLogFunc e => Keymap -> Utf8Builder -> RIO e ()
debugReport h hdr = do
st <- view Ls.stack <$> (readIORef $ h^.stack)
let ub = foldMap (\(i, n) -> " " <> display i
<> ". " <> display n <> "\n")
(zip ([1..] :: [Int]) st)
ls <- readIORef (h^.baseL)
logDebug $ hdr <> "\n" <> ub <> "Base-layer: " <> display ls <> "\n"
layerOp :: (HasLogFunc e)
=> Keymap
-> LayerOp
-> RIO e ()
layerOp h o = let km = h^.stack in case o of
(PushLayer n) -> do
Ls.pushLayer n <$> readIORef km >>= \case
Left e -> throwIO e
Right m' -> writeIORef km m'
debugReport h $ "Pushed layer to stack: " <> display n
(PopLayer n) -> do
Ls.popLayer n <$> readIORef km >>= \case
Left e -> throwIO e
Right m' -> writeIORef km m'
debugReport h $ "Popped layer from stack: " <> display n
(SetBaseLayer n) -> do
(n `elem`) . view Ls.maps <$> (readIORef km) >>= \case
True -> writeIORef (h^.baseL) n
False -> throwIO $ Ls.LayerDoesNotExist n
debugReport h $ "Set base layer to: " <> display n
lookupKey :: MonadIO m
=> Keymap
-> Keycode
-> m (Maybe BEnv)
lookupKey h c = do
m <- readIORef $ h^.stack
f <- readIORef $ h^.baseL
pure $ case m ^? Ls.atKey c of
Nothing -> m ^? Ls.inLayer f c
benv -> benv