content:   -- Base
  import XMonad
  import System.IO (hPutStrLn)
  import System.Exit (exitSuccess)
  import qualified XMonad.StackSet as W
  
      -- Actions
  import XMonad.Actions.CopyWindow (kill1, killAllOtherCopies)
  import XMonad.Actions.CycleWS (moveTo, shiftTo, WSType(..), nextScreen, prevScreen)
  import XMonad.Actions.GridSelect
  import XMonad.Actions.MouseResize
  import XMonad.Actions.Promote
  import XMonad.Actions.RotSlaves (rotSlavesDown, rotAllDown)
  import qualified XMonad.Actions.TreeSelect as TS
  import XMonad.Actions.WindowGo (runOrRaise)
  import XMonad.Actions.WithAll (sinkAll, killAll)
  import qualified XMonad.Actions.Search as S
  
      -- Data
  import Data.Char (isSpace, toUpper)
  import Data.Monoid
  import Data.Maybe (isJust)
  import Data.Tree
  import qualified Data.Map as M
  
      -- Hooks
  import XMonad.Hooks.DynamicLog (dynamicLogWithPP, wrap, xmobarPP, xmobarColor, shorten, PP(..))
  import XMonad.Hooks.EwmhDesktops  -- for some fullscreen events, also for xcomposite in obs.
  import XMonad.Hooks.FadeInactive
  import XMonad.Hooks.ManageDocks (avoidStruts, docksEventHook, manageDocks, ToggleStruts(..))
  import XMonad.Hooks.ManageHelpers (isFullscreen, doFullFloat)
  import XMonad.Hooks.ServerMode
  import XMonad.Hooks.SetWMName
  import XMonad.Hooks.WorkspaceHistory
  
      -- Layouts
  import XMonad.Layout.GridVariants (Grid(Grid))
  import XMonad.Layout.SimplestFloat
  import XMonad.Layout.Spiral
  import XMonad.Layout.ResizableTile
  import XMonad.Layout.Tabbed
  import XMonad.Layout.ThreeColumns
  
      -- Layouts modifiers
  import XMonad.Layout.LayoutModifier
  import XMonad.Layout.LimitWindows (limitWindows, increaseLimit, decreaseLimit)
  import XMonad.Layout.Magnifier
  import XMonad.Layout.MultiToggle (mkToggle, single, EOT(EOT), (??))
  import XMonad.Layout.MultiToggle.Instances (StdTransformers(NBFULL, MIRROR, NOBORDERS))
  import XMonad.Layout.NoBorders
  import XMonad.Layout.Renamed
  import XMonad.Layout.ShowWName
  import XMonad.Layout.Simplest
  import XMonad.Layout.Spacing
  import XMonad.Layout.SubLayouts
  import XMonad.Layout.WindowNavigation
  import XMonad.Layout.WindowArranger (windowArrange, WindowArrangerMsg(..))
  import qualified XMonad.Layout.ToggleLayouts as T (toggleLayouts, ToggleLayout(Toggle))
  import qualified XMonad.Layout.MultiToggle as MT (Toggle(..))
  
      -- Prompt
  import XMonad.Prompt
  import XMonad.Prompt.Input
  import XMonad.Prompt.FuzzyMatch
  import XMonad.Prompt.Man
  import XMonad.Prompt.Pass
  import XMonad.Prompt.Shell
  import XMonad.Prompt.Ssh
  import XMonad.Prompt.XMonad
  import Control.Arrow (first)
  
     -- Utilities
  import XMonad.Util.EZConfig (additionalKeysP)
  import XMonad.Util.NamedScratchpad
  import XMonad.Util.Run (runProcessWithInput, safeSpawn, spawnPipe)
  import XMonad.Util.SpawnOnce
  
  myFont :: String
  myFont = "xft:Sarasa UI SC:bold:size=8:antialias=true:hinting=true"
  
  myFm :: String
  myFm = "thunar"
  
  myModMask :: KeyMask
  myModMask = mod4Mask       -- Sets modkey to super/windows key
  
  myTerminal :: String
  myTerminal = "kitty -c ~/.config/kitty/kitty.conf"   -- Sets default terminal
  
  myBrowser :: String
  myBrowser = "firefox-nightly"               -- Sets qutebrowser as browser for tree select
  -- myBrowser = myTerminal ++ " -e lynx " -- Sets lynx as browser for tree select
  
  myEditor :: String
  myEditor = "emacs"  -- Sets emacs as editor for tree select
  -- myEditor = myTerminal ++ " -e vim "    -- Sets vim as editor for tree select
  
  myBorderWidth :: Dimension
  myBorderWidth = 2          -- Sets border width for windows
  
  myNormColor :: String
  myNormColor   = "#2E3440"  -- Border color of normal windows
  
  myFocusColor :: String
  myFocusColor  = "#5E81AC"  -- Border color of focused windows
  
  altMask :: KeyMask
  altMask = mod1Mask         -- Setting this for use in xprompts
  
  windowCount :: X (Maybe String)
  windowCount = gets $ Just . show . length . W.integrate' . W.stack . W.workspace . W.current . windowset
  
  myStartupHook :: X ()
  myStartupHook = do
            spawnOnce "emacs --daemon &"
            spawnOnce "sh ~/.fehbg"
            spawnOnce "dunst &"
            spawnOnce "redshift-gtk &"
            spawnOnce "xfce4-power-manager &"
            spawnOnce "xsetroot -cursor_name left_ptr"
            spawnOnce "qv2ray &"
            spawnOnce "nutstore &"
            spawnOnce "copyq &"
            spawnOnce "xdman &"
            spawnOnce "picom -b"
            spawnOnce "fcitx5 &"
            -- spawnOnce "nohup trayer --edge top --align right --widthtype request --padding 6 --SetDockType true --SetPartialStrut true --expand true --transparent true --alpha 0 --tint 0xd8dee9  --height 22 &"
            setWMName "LG3D"
  
  myColorizer :: Window -> Bool -> X (String, String)
  myColorizer = colorRangeFromClassName
                    (0x28,0x2c,0x34) -- lowest inactive bg
                    (0x28,0x2c,0x34) -- highest inactive bg
                    (0xc7,0x92,0xea) -- active bg
                    (0xc0,0xa7,0x9a) -- inactive fg
                    (0x28,0x2c,0x34) -- active fg
  
  -- gridSelect menu layout
  mygridConfig :: p -> GSConfig Window
  mygridConfig colorizer = (buildDefaultGSConfig myColorizer)
      { gs_cellheight   = 40
      , gs_cellwidth    = 200
      , gs_cellpadding  = 6
      , gs_originFractX = 0.5
      , gs_originFractY = 0.5
      , gs_font         = myFont
      }
  
  spawnSelected' :: [(String, String)] -> X ()
  spawnSelected' lst = gridselect conf lst >>= flip whenJust spawn
      where conf = def
                     { gs_cellheight   = 40
                     , gs_cellwidth    = 200
                     , gs_cellpadding  = 6
                     , gs_originFractX = 0.5
                     , gs_originFractY = 0.5
                     , gs_font         = myFont
                     }
  
  myAppGrid = [ ("Thunar", "thunar")
                   , ("Deadbeef", "deadbeef")
                   , ("WPS", "wps")
                   , ("Chromium", "chromium")
                   , ("VSCode", "code")
                   , ("Thunderbird", "thunderbird")
                   , ("Sublime", "subl3")
                   , ("Nitrogen", "nitrogen")
                   , ("NetEaseMusic", "netease-cloud-music")
                   , ("Steam", "steam-native")
                   , ("Windows", "VBoxManage startvm 'WinDev2008Eval' --type gui")
                   , ("QQMusic", "qqmusic")
                   ]
  
  myIDEGrid = [ ("Goland", "goland")
              , ("Idea", "idea")
              , ("Clion", "clion")
              , ("Pycharm", "pycharm")
              , ("Webstorm", "webstorm")
              , ("Datagrip", "datagrip")
              ]
  
  -- A list of all of the standard Xmonad prompts and a key press assigned to them.
  -- These are used in conjunction with keybinding I set later in the config.
  
  myScratchPads :: [NamedScratchpad]
  myScratchPads = [ NS "terminal" spawnTerm findTerm manageTerm
                  , NS "mocp" spawnMocp findMocp manageMocp
                  ]
    where
      spawnTerm  = myTerminal ++ " -n scratchpad"
      findTerm   = resource =? "scratchpad"
      manageTerm = customFloating $ W.RationalRect l t w h
                 where
                   h = 0.9
                   w = 0.9
                   t = 0.95 -h
                   l = 0.95 -w
      spawnMocp  = myTerminal ++ " -n mocp 'mocp'"
      findMocp   = resource =? "mocp"
      manageMocp = customFloating $ W.RationalRect l t w h
                 where
                   h = 0.9
                   w = 0.9
                   t = 0.95 -h
                   l = 0.95 -w
  
  mySpacing :: Integer -> l a -> XMonad.Layout.LayoutModifier.ModifiedLayout Spacing l a
  mySpacing i = spacingRaw False (Border i i i i) True (Border i i i i) True
  
  -- Below is a variation of the above except no borders are applied
  -- if fewer than two windows. So a single window has no gaps.
  mySpacing' :: Integer -> l a -> XMonad.Layout.LayoutModifier.ModifiedLayout Spacing l a
  mySpacing' i = spacingRaw True (Border i i i i) True (Border i i i i) True
  
  -- Defining a bunch of layouts, many that I don't use.
  tall     = renamed [Replace "tall"]
             $ windowNavigation
             $ addTabs shrinkText myTabTheme
             $ subLayout [] (smartBorders Simplest)
             $ limitWindows 12
             $ mySpacing 8
             $ ResizableTall 1 (3/100) (1/2) []
  magnify  = renamed [Replace "magnify"]
             $ windowNavigation
             $ addTabs shrinkText myTabTheme
             $ subLayout [] (smartBorders Simplest)
             $ magnifier
             $ limitWindows 12
             $ mySpacing 8
             $ ResizableTall 1 (3/100) (1/2) []
  monocle  = renamed [Replace "monocle"]
             $ windowNavigation
             $ addTabs shrinkText myTabTheme
             $ subLayout [] (smartBorders Simplest)
             $ limitWindows 20 Full
  floats   = renamed [Replace "floats"]
             $ windowNavigation
             $ addTabs shrinkText myTabTheme
             $ subLayout [] (smartBorders Simplest)
             $ limitWindows 20 simplestFloat
  grid     = renamed [Replace "grid"]
             $ windowNavigation
             $ addTabs shrinkText myTabTheme
             $ subLayout [] (smartBorders Simplest)
             $ limitWindows 12
             $ mySpacing 8
             $ mkToggle (single MIRROR)
             $ Grid (16/10)
  spirals  = renamed [Replace "spirals"]
             $ windowNavigation
             $ addTabs shrinkText myTabTheme
             $ subLayout [] (smartBorders Simplest)
             $ mySpacing' 8
             $ spiral (6/7)
  threeCol = renamed [Replace "threeCol"]
             $ windowNavigation
             $ addTabs shrinkText myTabTheme
             $ subLayout [] (smartBorders Simplest)
             $ limitWindows 7
             $ mySpacing' 4
             $ ThreeCol 1 (3/100) (1/2)
  threeRow = renamed [Replace "threeRow"]
             $ windowNavigation
             $ addTabs shrinkText myTabTheme
             $ subLayout [] (smartBorders Simplest)
             $ limitWindows 7
             $ mySpacing' 4
             -- Mirror takes a layout and rotates it by 90 degrees.
             -- So we are applying Mirror to the ThreeCol layout.
             $ Mirror
             $ ThreeCol 1 (3/100) (1/2)
  tabs     = renamed [Replace "tabs"]
             -- I cannot add spacing to this layout because it will
             -- add spacing between window and tabs which looks bad.
             $ tabbed shrinkText myTabTheme
  
  myTabTheme = def { fontName            = myFont
                   , activeColor         = "#ECEFF4"
                   , inactiveColor       = "#4C566A"
                   , activeBorderColor   = "#5E81AC"
                   , inactiveBorderColor = "#2E3440"
                   , activeTextColor     = "#2E3440"
                   , inactiveTextColor   = "#d0d0d0"
                   }
  
  
  -- The layout hook
  myLayoutHook = avoidStruts $ mouseResize $ windowArrange $ T.toggleLayouts floats
                 $ mkToggle (NBFULL ?? NOBORDERS ?? EOT) myDefaultLayout
               where
                 -- I've commented out the layouts I don't use.
                 myDefaultLayout =     tall
                                   ||| grid
                                   ||| noBorders tabs
                                   ||| floats
                                   ||| noBorders monocle
                                   ||| magnify
                                   ||| spirals
                                   ||| threeCol
                                   ||| threeRow
  
  
  xmobarEscape :: String -> String
  xmobarEscape = concatMap doubleLts
    where
          doubleLts '<' = "<<"
          doubleLts x   = [x]
  
  myWorkspaces :: [String]
  myWorkspaces = clickable . (map xmobarEscape)
                 -- $ [" 1 ", " 2 ", " 3 ", " 4 ", " 5 ", " 6 ", " 7 ", " 8 ", " 9 "]
                 $ [" dev ", " stu ", " www ", " mus ", " game ", " vbox ", " sys ", " chat ", " gfx "]
    where
          clickable l = [ "<action=xdotool key super+" ++ show (n) ++ ">" ++ ws ++ "</action>" |
                        (i,ws) <- zip [1..9] l,
                        let n = i ]
  
  
  myManageHook :: XMonad.Query (Data.Monoid.Endo WindowSet)
  myManageHook = composeAll
       -- using 'doShift ( myWorkspaces !! 7)' sends program to workspace 8!
       -- I'm doing it this way because otherwise I would have to write out the full
       -- name of my workspaces, and the names would very long if using clickable workspaces.
       [ title =? "Mozilla Firefox"        --> doShift ( myWorkspaces !! 2 )
       , className =? "TelegramDesktop"    --> doShift ( myWorkspaces !! 7 )
       , className =? "Qq"                 --> doShift ( myWorkspaces !! 7 )
       , className =? "qv2ray"             --> doShift ( myWorkspaces !! 8 )
       , className =? "Deadbeef"           --> doShift ( myWorkspaces !! 3 )
       , className =? "netease-cloud-music" --> doShift ( myWorkspaces !! 3 )
       , className =? "qqmusic"            --> doShift ( myWorkspaces !! 3 )
       , className =? "xdman-Main"         --> doShift ( myWorkspaces !! 8 )
       , className =? "VirtualBox Manager" --> doShift ( myWorkspaces !! 5 )
       , className =? "xdman-Main"                   --> doFloat
       , className =? "Qq"                           --> doFloat
       , className =? "jetbrains-toolbox"            --> doFloat
       , title =? "Oracle VM VirtualBox Manager"     --> doFloat
       , (className =? "firefox" <&&> resource =? "Dialog") --> doFloat  -- Float Firefox Dialog
       ] <+> namedScratchpadManageHook myScratchPads
  
  myLogHook :: X ()
  myLogHook = fadeInactiveLogHook fadeAmount
      where fadeAmount = 1.0
  
  myKeys :: [(String, X ())]
  myKeys =
      -- Xmonad
          [ ("M-C-r", spawn "xmonad --recompile") -- Recompiles xmonad
          , ("M-S-r", spawn "xmonad --restart")   -- Restarts xmonad
          , ("M-S-<Escape>", io exitSuccess)      -- Quits xmonad
  
          
          -- Useful programs to have a keybinding for launch
          , ("M-<Return>", spawn (myTerminal ++ " -e fish"))
          , ("M-d", spawn ("rofi -show drun"))
          , ("M-c", spawn (myBrowser))
          , ("M1-c", spawn ("code"))
          , ("M-n", spawn ("nmd"))
          , ("M-z", spawn ("zathura"))
  
          , ("M-S-h", spawn (myTerminal ++ " -e htop"))
          , ("M-S-e", spawn (myEditor))
          , ("M-S-n", spawn (myFm))
          , ("M-S-s", spawn ("flameshot gui"))
          , ("M-S-v", spawn ("VBoxManage startvm 'WinDev2008Eval' --type gui"))
          
          , ("M1-C-<Delete>", spawn ("betterlockscreen -l"))
          , ("M-C-p", spawn ("sh ~/.local/bin/switch 'l' 'xmonad'"))
          , ("M-C-n", spawn ("sh ~/.local/bin/switch 'n' 'xmonad'"))
          , ("M1-C-p", spawn ("mpc toggle"))
          , ("M1-C-Right", spawn ("mpc next"))
          , ("M1-C-Left", spawn ("mpc prev"))
  
      -- Kill windows
          , ("M-q", kill1)                         -- Kill the currently focused client
          , ("M-S-a", killAll)                       -- Kill all windows on current workspace
          , ("M-S-q", spawn ("xkill"))
  
      -- Workspaces
          , ("M-.", nextScreen)  -- Switch focus to next monitor
          , ("M-,", prevScreen)  -- Switch focus to prev monitor
          , ("M-S-<KP_Add>", shiftTo Next nonNSP >> moveTo Next nonNSP)       -- Shifts focused window to next ws
          , ("M-S-<KP_Subtract>", shiftTo Prev nonNSP >> moveTo Prev nonNSP)  -- Shifts focused window to prev ws
  
      -- Floating windows
          , ("M-f", sendMessage (T.Toggle "floats")) -- Toggles my 'floats' layout
          , ("M-t", withFocused $ windows . W.sink)  -- Push floating window back to tile
          , ("M-S-t", sinkAll)                       -- Push ALL floating windows to tile
  
      -- Increase/decrease spacing (gaps)
          , ("M-o", decWindowSpacing 4)           -- Decrease window spacing
          , ("M-i", incWindowSpacing 4)           -- Increase window spacing
          , ("M-S-o", decScreenSpacing 4)         -- Decrease screen spacing
          , ("M-S-i", incScreenSpacing 4)         -- Increase screen spacing
  
      -- Grid Select (CTR-g followed by a key)
          , ("C-g C-g", spawnSelected' myAppGrid)                 -- grid select favorite apps
          , ("C-g C-t", goToSelected $ mygridConfig myColorizer)  -- goto selected window
          , ("C-g C-b", bringSelected $ mygridConfig myColorizer) -- bring selected window
          , ("C-i C-i", spawnSelected' myIDEGrid)
  
      -- Windows navigation
          , ("M-m", windows W.focusMaster)  -- Move focus to the master window
          , ("M-j", windows W.focusDown)    -- Move focus to the next window
          , ("M-k", windows W.focusUp)      -- Move focus to the prev window
          , ("M-S-m", windows W.swapMaster) -- Swap the focused window and the master window
          , ("M-S-j", windows W.swapDown)   -- Swap focused window with next window
          , ("M-S-k", windows W.swapUp)     -- Swap focused window with prev window
          , ("M-<Backspace>", promote)      -- Moves focused window to master, others maintain order
          , ("M-S-<Tab>", rotSlavesDown)    -- Rotate all windows except master and keep focus in place
          , ("M-C-<Tab>", rotAllDown)       -- Rotate all the windows in the current stack
  
      -- Layouts
          , ("M-<Space>", sendMessage NextLayout)           -- Switch to next layout
          , ("M-C-M1-<Up>", sendMessage Arrange)
          , ("M-C-M1-<Down>", sendMessage DeArrange)
          , ("M-w", sendMessage (MT.Toggle NBFULL) >> sendMessage ToggleStruts) -- Toggles noborder/full
          , ("M-S-w", sendMessage ToggleStruts)     -- Toggles struts
          , ("M-S-b", sendMessage $ MT.Toggle NOBORDERS)  -- Toggles noborder
  
      -- Increase/decrease windows in the master pane or the stack
          , ("M-S-<Up>", sendMessage (IncMasterN 1))      -- Increase number of clients in master pane
          , ("M-S-<Down>", sendMessage (IncMasterN (-1))) -- Decrease number of clients in master pane
          , ("M-C-<Up>", increaseLimit)                   -- Increase number of windows
          , ("M-C-<Down>", decreaseLimit)                 -- Decrease number of windows
  
      -- Window resizing
          , ("M-h", sendMessage Shrink)                   -- Shrink horiz window width
          , ("M-l", sendMessage Expand)                   -- Expand horiz window width
          , ("M-M1-j", sendMessage MirrorShrink)          -- Shrink vert window width
          , ("M-M1-k", sendMessage MirrorExpand)          -- Exoand vert window width
  
      -- Sublayouts
      -- This is used to push windows to tabbed sublayouts, or pull them out of it.
          , ("M-C-h", sendMessage $ pullGroup L)
          , ("M-C-l", sendMessage $ pullGroup R)
          , ("M-C-k", sendMessage $ pullGroup U)
          , ("M-C-j", sendMessage $ pullGroup D)
          , ("M-C-m", withFocused (sendMessage . MergeAll))
          , ("M-C-u", withFocused (sendMessage . UnMerge))
          , ("M-C-/", withFocused (sendMessage . UnMergeAll))
          , ("M-C-,", onGroup W.focusUp')    -- Switch focus to next tab
          , ("M-C-.", onGroup W.focusDown')  -- Switch focus to prev tab
  
      -- Scratchpads
          , ("M-C-<Return>", namedScratchpadAction myScratchPads "terminal")
          , ("M-C-c", namedScratchpadAction myScratchPads "mocp")
  
      -- Controls for mocp music player (SUPER-u followed by a key)
          , ("M-u p", spawn "mocp --play")
          , ("M-u l", spawn "mocp --next")
          , ("M-u h", spawn "mocp --previous")
          , ("M-u <Space>", spawn "mocp --toggle-pause")
  
      -- Emacs (CTRL-e followed by a key)
          , ("C-e e", spawn "emacsclient -c -a 'emacs'")                            -- start emacs
          , ("C-e b", spawn "emacsclient -c -a 'emacs' --eval '(ibuffer)'")         -- list emacs buffers
          , ("C-e d", spawn "emacsclient -c -a 'emacs' --eval '(dired nil)'")       -- dired emacs file manager
          , ("C-e i", spawn "emacsclient -c -a 'emacs' --eval '(erc)'")             -- erc emacs irc client
          , ("C-e m", spawn "emacsclient -c -a 'emacs' --eval '(mu4e)'")            -- mu4e emacs email client
          , ("C-e n", spawn "emacsclient -c -a 'emacs' --eval '(elfeed)'")          -- elfeed emacs rss client
          , ("C-e s", spawn "emacsclient -c -a 'emacs' --eval '(eshell)'")          -- eshell within emacs
          , ("C-e t", spawn "emacsclient -c -a 'emacs' --eval '(mastodon)'")        -- mastodon within emacs
          , ("C-e v", spawn "emacsclient -c -a 'emacs' --eval '(+vterm/here nil)'") -- vterm within emacs
          -- emms is an emacs audio player. I set it to auto start playing in a specific directory.
          , ("C-e a", spawn "emacsclient -c -a 'emacs' --eval '(emms)' --eval '(emms-play-directory-tree \"~/Music/Non-Classical/70s-80s/\")'")
  
      -- Multimedia Keys
          , ("<XF86AudioPlay>", spawn (myTerminal ++ "mocp --play"))
          , ("<XF86AudioPrev>", spawn (myTerminal ++ "mocp --previous"))
          , ("<XF86AudioNext>", spawn (myTerminal ++ "mocp --next"))
          -- , ("<XF86AudioMute>",   spawn "amixer set Master toggle")  -- Bug prevents it from toggling correctly in 12.04.
          , ("<XF86AudioLowerVolume>", spawn "amixer set Master 5%- unmute")
          , ("<XF86AudioRaiseVolume>", spawn "amixer set Master 5%+ unmute")
          , ("<XF86HomePage>", spawn "chromium")
          , ("<XF86Search>", safeSpawn "chromium" ["https://www.duckduckgo.com/"])
          , ("<XF86Mail>", runOrRaise "geary" (resource =? "thunderbird"))
          , ("<XF86Calculator>", runOrRaise "gcalctool" (resource =? "gcalctool"))
          , ("<XF86Eject>", spawn "toggleeject")
          , ("<Print>", spawn "scrotd 0")
          ]
      -- Appending some extra xprompts to keybindings list.
      -- Look at "xprompt settings" section this of config for values for "k".
      -- The following lines are needed for named scratchpads.
            where nonNSP          = WSIs (return (\ws -> W.tag ws /= "nsp"))
                  nonEmptyNonNSP  = WSIs (return (\ws -> isJust (W.stack ws) && W.tag ws /= "nsp"))
  
  main :: IO ()
  main = do
      -- Launching three instances of xmobar on their monitors.
      xmproc0 <- spawnPipe "xmobar -x 0 $HOME/.config/xmobar/xmobarrc0"
      -- the xmonad, ya know...what the WM is named after!
      xmonad $ ewmh def
          { manageHook = ( isFullscreen --> doFullFloat ) <+> myManageHook <+> manageDocks
          -- Run xmonad commands from command line with "xmonadctl command". Commands include:
          -- shrink, expand, next-layout, default-layout, restart-wm, xterm, kill, refresh, run,
          -- focus-up, focus-down, swap-up, swap-down, swap-master, sink, quit-wm. You can run
          -- "xmonadctl 0" to generate full list of commands written to ~/.xsession-errors.
          -- To compile xmonadctl: ghc -dynamic xmonadctl.hs
          , handleEventHook    = serverModeEventHookCmd
                                 <+> serverModeEventHook
                                 <+> serverModeEventHookF "XMONAD_PRINT" (io . putStrLn)
                                 <+> docksEventHook
          , modMask            = myModMask
          , terminal           = myTerminal
          , startupHook        = myStartupHook
          , layoutHook         = myLayoutHook
          , workspaces         = myWorkspaces
          , borderWidth        = myBorderWidth
          , normalBorderColor  = myNormColor
          , focusedBorderColor = myFocusColor
          , logHook = workspaceHistoryHook <+> myLogHook <+> dynamicLogWithPP xmobarPP
                          { ppOutput = \x -> hPutStrLn xmproc0 x  
                          , ppCurrent = xmobarColor "#98be65" "" . wrap "[" "]" -- Current workspace in xmobar
                          , ppVisible = xmobarColor "#98be65" ""                -- Visible but not current workspace
                          , ppHidden = xmobarColor "#82AAFF" "" . wrap "*" ""   -- Hidden workspaces in xmobar
                          , ppHiddenNoWindows = xmobarColor "#c792ea" ""        -- Hidden workspaces (no windows)
                          , ppTitle = xmobarColor "#2E3440" "" . shorten 60     -- Title of active window in xmobar
                          , ppSep =  "<fc=#666666> <fn=2>|</fn> </fc>"          -- Separators in xmobar
                          , ppUrgent = xmobarColor "#D08770" "" . wrap "!" "!"  -- Urgent workspace
                          , ppExtras  = [windowCount]                           -- # of windows current workspace
                          , ppOrder  = \(ws:l:t:ex) -> [ws,l]++ex++[t]
                          }
          } `additionalKeysP` myKeys
  