diff options
Diffstat (limited to 'src/Rahm/Desktop')
| -rw-r--r-- | src/Rahm/Desktop/Keys.hs | 53 | ||||
| -rw-r--r-- | src/Rahm/Desktop/Keys/Dsl2.hs | 109 |
2 files changed, 115 insertions, 47 deletions
diff --git a/src/Rahm/Desktop/Keys.hs b/src/Rahm/Desktop/Keys.hs index 412d8f5..8945201 100644 --- a/src/Rahm/Desktop/Keys.hs +++ b/src/Rahm/Desktop/Keys.hs @@ -306,33 +306,26 @@ bindings = do doc "Move XMobar to another screen." $ spawnX "pkill -SIGUSR1 xmobar" - -- bind xK_F1 $ do - -- justMod $ - -- doc - -- "Print this documentation" - -- ( safeSpawn - -- "gxmessage" - -- [ "-fn", - -- "Source Code Pro", - -- "Key Bindings\n\n" - -- ++ documentation (keymap config) - -- ++ "\n\nButton Bindings\n\n" - -- ++ buttonDocumentation (mouseMap config) - -- ] :: - -- X () - -- ) - - -- bind xK_F7 $ do - -- justMod $ - -- doc - -- "Print this documentation to stdout (at LogLevel Info)" - -- ( logs - -- Info - -- "KeyBindings\n\n%s\n\nButtonBindings\n\n%s" - -- (documentation (keymap config)) - -- (buttonDocumentation (mouseMap config)) :: - -- X () - -- ) + let getDoc :: X String + getDoc = do + config <- asks config + return $ + "Key and Mouse Bindings:\n\n" + ++ documentation config bindings + + bind xK_F1 $ do + justMod + $ doc + "Print this documentation" + $ do + doc <- getDoc + safeSpawn "gxmessage" ["-fn", "Source Code Pro", doc] + + bind xK_F7 $ do + justMod $ + doc + "Print this documentation to stdout (at LogLevel Info)" + (logs Info "%s" =<< getDoc) bind xK_F10 $ do justMod playPauseDoc @@ -846,6 +839,12 @@ bindings = do noMod mediaNextDoc rawMask shiftMask mediaSeekFDoc + bindOtherKeys $ \(_, _, s) -> + logs Info "Unhandled key pressed: %s" s + + bindOtherButtons $ \(_, b) -> + logs Info "Unhandled button press: %s" (show b) + -- Centers the current focused window. i.e. toggles the Zoom layout -- modifier. shiftMod $ diff --git a/src/Rahm/Desktop/Keys/Dsl2.hs b/src/Rahm/Desktop/Keys/Dsl2.hs index 3debc48..b59152e 100644 --- a/src/Rahm/Desktop/Keys/Dsl2.hs +++ b/src/Rahm/Desktop/Keys/Dsl2.hs @@ -1,13 +1,15 @@ module Rahm.Desktop.Keys.Dsl2 where import Control.Monad.Fix (fix) -import Control.Monad.RWS (MonadTrans (lift), MonadWriter, forM_) +import Control.Monad.RWS (MonadTrans (lift), MonadWriter, forM_, when) import Control.Monad.Reader (Reader, ask, runReader) import Control.Monad.State (MonadTrans, StateT (StateT)) import Control.Monad.Trans.Maybe (MaybeT (..)) -import Control.Monad.Trans.Writer (Writer, WriterT, execWriter, execWriterT) +import Control.Monad.Trans.Writer (Writer, WriterT, execWriter, execWriterT, runWriter) import Control.Monad.Writer.Class (tell) +import Data.Bits ((.&.)) import Data.Functor.Identity (Identity) +import Data.List (intercalate) import Data.Map (Map) import qualified Data.Map as Map import Data.Maybe (fromMaybe) @@ -26,6 +28,7 @@ data Documented t = Documented type family Action t where Action KeySym = X () Action Button = Window -> X () + Action () = () data XConfigH where XConfigH :: forall l. XConfig l -> XConfigH @@ -55,8 +58,12 @@ newtype MaskBinder k a = MaskBinder ) instance Semigroup BindingsMap where - (BindingsMap mk1 mb1 _ _) <> (BindingsMap mk2 mb2 fk fb) = - BindingsMap (mk1 <> mk2) (mb1 <> mb2) fk fb + (BindingsMap mk1 mb1 fk1 fb1) <> (BindingsMap mk2 mb2 fk2 fb2) = + BindingsMap + (mk1 <> mk2) + (mb1 <> mb2) + (\a -> fk1 a >> fk2 a) + (\a b -> fb1 a b >> fb2 a b) instance Monoid BindingsMap where mempty = BindingsMap mempty mempty (\_ -> return ()) (\_ _ -> return ()) @@ -158,7 +165,6 @@ resolveBindings (BindingsMap keyBindings buttonBindings _ _) = \c -> Map.mapWithKey (\k -> pushB k (bindingToWinX c) . undocument) buttonBindings ) where - pushB :: (ButtonMask, Button) -> (Binding Button -> Window -> X ()) -> Binding Button -> Window -> X () pushB (_, b) fn binding win = if isRepeatOrSubmap binding then pushPendingBuffer ("b" ++ show b ++ " ") $ fn binding win @@ -186,37 +192,36 @@ resolveBindings (BindingsMap keyBindings buttonBindings _ _) = Repeat a sm -> bindingToWinX conf a win >> fix (doSubmap conf (sm conf)) doSubmap :: forall l. XConfig l -> BindingsMap -> X () -> X () - doSubmap conf (BindingsMap kbind bbind _ _) after = runMaybeT_ $ do + doSubmap conf (BindingsMap kbind bbind catk catb) after = do nextPressEvent $ \case (ButtonPress m b) -> do - binding <- hoist $ Map.lookup (m, b) bbind - lift $ do - win <- pointerWindow - bindingToWinX conf (undocument binding) win - after + win <- pointerWindow + case Map.lookup (m, b) bbind of + (Just binding) -> do + bindingToWinX conf (undocument binding) win + after + Nothing -> catb (m, b) win (KeyPress m k s) -> do - binding <- hoist $ Map.lookup (m, k) kbind - lift $ do - bindingToX conf (undocument binding) - after + case Map.lookup (m, k) kbind of + (Just binding) -> do + bindingToX conf (undocument binding) + after + Nothing -> catk (m, k, s) isRepeatOrSubmap = \case Repeat {} -> True Submap {} -> True _ -> False - nextPressEvent fn = do + nextPressEvent fn = runMaybeT_ $ do ev <- nextButtonOrKeyEvent let str = case ev of ButtonPress m b -> "b" ++ show b KeyPress _ _ s -> s lift $ pushAddPendingBuffer (str ++ " ") $ - runMaybeT_ $ - fn ev - - hoist = MaybeT . return + fn ev subbind :: Binder () -> Binding t subbind (Binder b) = @@ -252,3 +257,67 @@ withBindings b config = { keys = keyBinds, mouseBindings = buttonBinds } + +documentation :: XConfig l -> Binder () -> String +documentation conf binder = + documentation' $ runBinder conf binder + where + documentation' :: BindingsMap -> String + documentation' (BindingsMap kmap bmap _ _) = execWriter $ do + forM_ + ( Map.toList $ + invert $ + Map.union + (Map.map documentBinding (Map.mapKeys keyToStr kmap)) + (Map.map documentBinding (Map.mapKeys buttonToStr bmap)) + ) + $ \(doc, keys) -> + when (doc /= "") $ do + when (length keys > 1) (tell "\n") + tell (intercalate ",\n" keys) + tell " -> " + tell (tindent doc) + when (length keys > 1) (tell "\n") + + documentBinding :: Documented (Binding r) -> String + documentBinding = \case + (Documented s (Action _)) -> s + (Documented s (Submap mp)) -> + s ++ "\n" ++ indent (documentation' (mp conf)) + (Documented s (Repeat _ mp)) -> + s ++ " (repeatable)\n" ++ indent (documentation' (mp conf)) + _ -> "" + + indent = unlines . map (" " ++) . lines + tindent (lines -> (h : t)) = unlines (h : map (" " ++) t) + tindent x = x + + keyToStr (m, k) = showMask m ++ keysymToString k + showMask mask = + let masks = + [ (shiftMask, "S"), + (mod1Mask, "A"), + (mod3Mask, "H"), + (mod4Mask, "M"), + (controlMask, "C") + ] + in concatMap ((++ "-") . snd) $ filter ((/= 0) . (.&. mask) . fst) masks + + invert :: (Ord a, Ord b) => Map a b -> Map b [a] + invert = Map.fromListWith (++) . map (\(a, b) -> (b, [a])) . Map.toList + + buttonToStr (m, b) = showMask m ++ buttonNumToStr b + buttonNumToStr = \case + 1 -> "Left Click" + 2 -> "Middle Click" + 3 -> "Right Click" + 4 -> "Wheel Up" + 5 -> "Wheel Down" + 6 -> "Wheel Left" + 7 -> "Wheel Right" + 8 -> "Browser Back" + 9 -> "Browser Forward" + 13 -> "Thumb Target" + 14 -> "Index Forward" + 15 -> "Index Back" + b -> "Button " ++ show b |