{-# LANGUAGE FlexibleContexts #-} import qualified Data.Map as M import System.Environment (lookupEnv) import XMonad hiding ( (|||) ) import XMonad.Actions.FloatKeys (keysMoveWindow, keysResizeWindow) import XMonad.Actions.WindowGo (raise, runOrRaise) import qualified XMonad.Actions.GridSelect as GS import XMonad.Actions.PerWindowKeys (bindAll, bindFirst) import XMonad.Hooks.ManageHelpers ((-?>)) import qualified XMonad.Hooks.ManageDocks as MD import qualified XMonad.Hooks.ManageHelpers as MH import qualified XMonad.Hooks.ServerMode as SM import qualified XMonad.Hooks.EwmhDesktops as Ewm import qualified XMonad.Layout.NoBorders as NB import XMonad.Layout.IM (withIM, Property(ClassName)) import XMonad.Layout.LayoutCombinators ((|||)) import qualified XMonad.Layout.LayoutCombinators as LJ import qualified XMonad.Layout.Renamed as LR import qualified XMonad.Layout.Spacing as SP import qualified XMonad.Layout.Reflect as Refl import qualified XMonad.Prompt as P import qualified XMonad.Prompt.Shell as PS import qualified XMonad.Prompt.XMonad as XmP import qualified XMonad.StackSet as W import qualified XMonad.Util.EZConfig as EZ import qualified XMonad.Util.Hacks as UH import qualified XMonad.Util.NamedScratchpad as NS import XMonad.Util.Paste (sendKey) import qualified XMonad.Util.WindowProperties as WP jaoscript scrpt = "/home/jao/etc/config/bin/" ++ scrpt defFace = "Hack-10" promptKeys = M.fromList [((controlMask, xK_a), P.startOfLine) ,((controlMask, xK_b), P.moveCursor P.Prev) ,((mod1Mask, xK_b), P.moveWord P.Prev) ,((controlMask, xK_d), P.deleteString P.Next) ,((mod1Mask, xK_d), P.killWord P.Next) ,((controlMask, xK_e), P.endOfLine) ,((controlMask, xK_f), P.moveCursor P.Next) ,((mod1Mask, xK_f), P.moveWord P.Next) ,((controlMask, xK_g), P.quit) ,((controlMask, xK_k), P.killAfter) ,((controlMask, xK_n), P.moveHistory W.focusUp') ,((mod1Mask, xK_n), P.moveHistory W.focusUp') ,((controlMask, xK_p), P.moveHistory W.focusDown') ,((mod1Mask, xK_p), P.moveHistory W.focusDown') ,((controlMask, xK_y), P.pasteString) ,((mod1Mask, xK_d), P.killWord P.Next) ] promptKM = M.union promptKeys P.defaultXPKeymap popConfig = P.def { P.font = "xft:" ++ defFace , P.promptKeymap = promptKM , P.position = P.Bottom , P.height = 25 , P.promptBorderWidth = 1 } darkPopConfig = popConfig { P.fgColor = "grey60" , P.bgColor = "grey10" , P.fgHLight = "lightgoldenrod2" , P.bgHLight = "grey20" , P.borderColor = "grey30" } lightPopConfig = popConfig { P.fgColor = "grey10" , P.bgColor = "#efebe7" , P.fgHLight = "sienna" , P.bgHLight = "lightyellow" , P.borderColor = "grey70" } defWorkspaces = ["X"] isEmacs = className =? "Emacs" <||> className =? "Pemacs" <||> className =? "Gemacs" isntEmacs = not `fmap` isEmacs raiseEmacs = raise isEmacs runOrRaiseEmacs = do emacs <- liftIO $ lookupEnv "emacs" runOrRaise (case emacs of Just e -> e; _ -> "emacs") isEmacs runOrRaiseFirefox = runOrRaise "firefox" (className =? "Firefox") toggleEmacs other = do ems <- mapM (WP.focusedHasProperty . WP.ClassName) ["Emacs", "Pemacs", "Gemacs"] if or ems then other else runOrRaiseEmacs keyDefs conf = [ ("", backlight "5%+") , ("", backlight "5%-") , ("", backlight "5%+") , ("", backlight "5%-") , ("", spawn "amixer sset Master 10%+") , ("", spawn "amixer sset Master 10%-") , ("", spawn "amixer sset Master toggle") , ("", emacsclient "message \"audio play\"") , ("", spawn "import -window root ~/screenshot.png") , ("M-", move (10,0)) , ("M-", move (-10,0)) , ("M-", move (0,-10)) , ("M-", move (0,10)) , ("M-0", emacsAfio "scratch") , ("M-1", emacsAfio "main") , ("M-2", emacsAfio "mail") , ("M-3", emacsAfio "www") , ("M-4", emacsAfio "docs") , ("M-5", jumpToL "F" >> raise (className =? "Firefox")) , ("M-C-", resize (10,0) (0,0)) , ("M-C-", resize (-10,0) (0,1)) , ("M-C-", resize (0,-10) (0,0)) , ("M-C-", resize (0,10) (0,0)) , ("M-b", sendMessage $ MD.ToggleStruts) , ("M-d", NS.namedScratchpadAction scratchpads "deezer") , ("M-e", toggleEmacs runOrRaiseFirefox) , ("M-m", raiseEmacs >> emacsclient "jao-transient-media") , ("M-S-r", PS.shellPrompt $ conf {P.position = P.Top}) , ("M-C-r", PS.shellPrompt $ conf {P.position = P.Top}) , ("M-s", raiseEmacs >> emacsclient "jao-transient-streaming") , ("M-S-s", withFocused $ windows . W.sink) , ("M-t", emacsAfio "main" >> emacsclient "vterm") , ("M-S-t", spawn (jaoscript "term")) , ("M-w", raiseEmacs >> emacsclient "jao-transient-utils") , ("M-x 1", emacsAfio "main") , ("M-x k", kill) , ("M-x M-f", withFocused float) , ("M-x s", withFocused $ windows . W.sink) , ("M-x g", GS.goToSelected GS.def) , ("M-x f", jumpToL "F") , ("M-x l", jumpToLE "L") , ("M-x r", jumpToLE "R") , ("M-x t", jumpToLE "T") , ("M-x n", sendMessage NextLayout) , ("M-S-x", XmP.xmonadPrompt $ conf {P.position = P.Top}) , ("M-z l", xdgscr "activate") , ("M-z u", spawn "toggle-screensaver.sh") , ("M-z z", zzCmd "suspend") , ("M-z h", zzCmd "hibernate") , ("M-z b", zzCmd "hybrid") , ("M-z l", i3lock) ] where emacsclient x = spawn $ "emacsclient -e '(" ++ x ++ ")'" jumpToL x = sendMessage (LJ.JumpToLayout x) >> return () withEmacs x = jumpToL "F" >> raiseEmacs >> emacsclient x emacsAfio f = withEmacs $ "jao-afio--goto-" ++ f sendCtrlC = sendKey controlMask xK_c jumpToLE x = emacsAfio "scratch-1" >> jumpToL x backlight x = spawn $ "brightnessctl -q s " ++ x i3lock = spawn "i3lock -e -i ~/.lockimage" xdgscr = spawn . ("xdg-screensaver " ++) zzCmd = spawn . ("sudo systemctl " ++) move r = withFocused $ keysMoveWindow r resize a b = withFocused $ keysResizeWindow a b spacing n = SP.spacingRaw False (SP.Border n 0 n 0) True (SP.Border 0 n 0 n) True namedLyt n = LR.renamed [LR.Replace n] lytFull = namedLyt "F" Full lytTall = namedLyt "T" $ spacing 1 (Tall 1 (1/100) (1/2)) lytLeft = namedLyt "L" $ withIM (9/26) (ClassName "Emacs") Full lytRight = namedLyt "R" $ Refl.reflectHoriz lytLeft scratchpads = [ NS.NS "deezer" "deezer-desktop" (className =? "Deezer") (centerFloat (3/4) (7/8)) ] scratchpad = NS.namedScratchpadManageHook scratchpads centerFloat width height = NS.customFloating $ W.RationalRect marginLeft marginTop width height where marginLeft = (1 - width) / 2 marginTop = (1 - height) / 2 mHook = MH.composeOne dlgs <+> composeAll cl where dlgs = [MH.isDialog -?> MH.doCenterFloat] cfs = ["Display", "Gitk", "MPlayer", "Vlc", "xli", "Blueman-services", "Blueman-manager", "Pavucontrol", "Pavumeter", "Xmessage", "XLogo", "mpv", "Mpv"] cl = [className =? x --> MH.doCenterFloat | x <- cfs] main = do scheme <- lookupEnv "JAO_COLOR_SCHEME" let dark = Just "dark" == scheme popCfg = if dark then darkPopConfig else lightPopConfig defBorder = if dark then "grey80" else "grey70" defFBorder = if dark then "grey85" else "grey20" ehook = SM.serverModeEventHook <+> UH.trayerPaddingXmobarEventHook lyt = NB.smartBorders $ lytFull ||| lytRight ||| lytLeft ||| lytTall localStartupHook = spawn "xmobars.sh" >> runOrRaiseEmacs xmonad $ MD.docks $ Ewm.ewmhFullscreen $ Ewm.ewmh def { manageHook = scratchpad <+> mHook <+> manageHook def , handleEventHook = ehook , layoutHook = MD.avoidStruts lyt , startupHook = localStartupHook , modMask = mod4Mask , borderWidth = 1 , focusedBorderColor = defFBorder , normalBorderColor = defBorder , terminal = (jaoscript "term") , workspaces = defWorkspaces , focusFollowsMouse = False } `EZ.removeKeysP` ["M-j", "M-n", "M-w", "M-m", "M-r", "M-p", "M-"] `EZ.additionalKeysP` (keyDefs popCfg)