import XMonad import XMonad.Actions.CopyWindow import XMonad.Actions.DynamicProjects import XMonad.Actions.Navigation2D import XMonad.Actions.SpawnOn import XMonad.Hooks.DynamicLog import XMonad.Hooks.EwmhDesktops import XMonad.Hooks.StatusBar import XMonad.Layout.Decoration import XMonad.Layout.Hidden import XMonad.Layout.Spacing import XMonad.Layout.Spiral import XMonad.Layout.ThreeColumns import XMonad.Prompt import XMonad.Util.EZConfig import XMonad.Util.Loggers import XMonad.Util.SpawnOnce ---------- -- Init -- ---------- main :: IO () main = xmonad -- ewmhFullscreen and ewmh don't commute, they MUST be in this order . dynamicProjects projects . ewmhFullscreen . ewmh . withNavigation2DConfig myNav2DConf . (`additionalKeysP` myKeybinds) . withEasySB (statusBarProp "polybar" (pure myPolybarPP)) defToggleStrutsKey $ myConfig -- myConfig :: XConfig (Choose (ModifiedLayout Spacing Tall) (Choose (Mirror (ModifiedLayout Spacing Tall)) Full)) myConfig = def { borderWidth = 1, clickJustFocuses = False, focusFollowsMouse = False, focusedBorderColor = myFocusedBorderColor, layoutHook = myLayout, modMask = mod4Mask, startupHook = myStartupHook, normalBorderColor = myNormalBorderColor, workspaces = myWorkspaces } myStartupHook :: X () myStartupHook = do spawnOnce "feh --bg-fill ~/Documents/images/Posters/StonehengeSun_alexander_4200.jpg --bg-fill ~/Documents/images/Posters/CradleMountain.jpg --bg-fill ~/Documents/images/Posters/Pleiades_WiseAntonucci_5000.jpg" spawnOnce myScreenLockCmd ------------ -- polybar -- ------------ myPolybarPP :: PP myPolybarPP = def { ppCurrent = wrap "" "" . xmobarBorder "Top" blue 2, ppExtras = [logTitles formatFocused formatUnfocused], ppHidden = xmobarBase0 . wrap "[" "]", ppHiddenNoWindows = const "", ppOrder = \[ws, l, _, wins] -> [" " ++ ws, l], -- and wins to [ws, l] to get window names ppSep = xmobarMagenta " • ", ppTitleSanitize = xmobarStrip, ppUrgent = xmobarRed . wrap (xmobarYellow "!") (xmobarYellow "!") } where formatFocused :: String -> String formatFocused = wrap (xmobarBase0 "[") (xmobarBase0 "]") . xmobarBlue . ppWindow formatUnfocused :: String -> String formatUnfocused = wrap (xmobarBase0 "[") (xmobarBase0 "]") . xmobarBase0 . ppWindow ppWindow :: String -> String ppWindow = xmobarRaw . (\w -> if null w then "untitled" else w) . shorten 30 xmobarBase0, xmobarBase2, xmobarYellow, xmobarRed, xmobarMagenta, xmobarBlue :: String -> String xmobarBase0 = xmobarColor base0 "" xmobarBase2 = xmobarColor base2 "" xmobarYellow = xmobarColor yellow "" xmobarRed = xmobarColor red "" xmobarMagenta = xmobarColor magenta "" xmobarBlue = xmobarColor blue "" ---------------- -- Workspaces -- ---------------- myWorkspaces :: [String] myWorkspaces = [wsSIG, wsIOG, wsMIO, wsDOT, wsLOG, wsMUS, wsREC, wsVID, wsADA] wsIOG, wsDOT, wsSIG, wsMIO, wsLOG, wsMUS, wsREC, wsVID, wsADA :: String wsIOG = "iog" wsDOT = "dot" wsSIG = "sig" wsMIO = "mio" wsLOG = "log" wsMUS = "mus" wsREC = "rec" wsVID = "vid" wsADA = "ada" -------------- -- Projects -- -------------- projects :: [Project] projects = [ Project { projectName = wsIOG, projectDirectory = "~/", projectStartHook = Just $ do spawnOn wsIOG iogBrowser spawnOn wsIOG slack }, Project { projectName = wsDOT, projectDirectory = "~/.dotfiles", projectStartHook = Just $ do spawnOn wsDOT myTerminal }, Project { projectName = wsSIG, projectDirectory = "~/", projectStartHook = Just $ do spawnOn wsSIG signal }, Project { projectName = wsMIO, projectDirectory = "~/", projectStartHook = Just $ do spawnOn wsMIO browser }, Project { projectName = wsLOG, projectDirectory = "~/", projectStartHook = Just $ do spawnOn wsIOG myTerminal }, Project { projectName = wsMUS, projectDirectory = "~/", projectStartHook = Just $ do spawnOn wsMUS musicPlayer }, Project { projectName = wsREC, projectDirectory = "~/Videos/obs-recordings", projectStartHook = Just $ do spawnOn wsREC obs }, Project { projectName = wsVID, projectDirectory = "~/", projectStartHook = Nothing }, Project { projectName = wsADA, projectDirectory = "~/", projectStartHook = Just $ do spawnOn wsADA daedalus } ] promptTheme :: XPConfig promptTheme = def { bgColor = base03, bgHLight = base02, fgColor = base0, fgHLight = base1, height = 31, position = Top, promptBorderWidth = 0 } ------------------ -- Applications -- ------------------ brightnessDown, brightnessUp, browser, discord, editor, element, hibernate, incognitoBrowser, iogBrowser, launcher, logseq, musicPlayer, obs, screenshot, signal, slack, myTerminal, volumeDown, volumeMute, volumeUp :: String brightnessDown = "light -U 5" brightnessUp = "light -A 5" browser = "brave" daedalus = "daedalus" discord = "discord" editor = "codium" element = "element-desktop" enableEDP1 = "xrandr --output eDP-1 --primary --auto --output HDMI-1 --off" enableHDMI1 = "xrandr --output eDP-1 --off --output HDMI-1 --primary --mode 3840x2160" hibernate = "sudo systemctl hibernate" incognitoBrowser = "brave -incognito" iogBrowser = "google-chrome-stable" launcher = "rofi -show drun" logseq = "logseq" musicPlayer = "spotify" obs = "obs" screenshot = "flameshot gui" signal = "signal-desktop" slack = "slack" myTerminal = "termonad" myScreenLockCmd = "xscreensaver --no-splash" myScreenLock = "xscreensaver-command -lock" volumeDown = "amixer set Master 2%-" volumeMute = "amixer set Master toggle" volumeUp = "amixer set Master 2%+" -------------- -- Keybinds -- -------------- myKeybinds :: [(String, X ())] myKeybinds = [ -- Spawn/kill ("M-b", spawn browser), ("M-i", spawn incognitoBrowser), ("M-f", spawn screenshot), ("M-p", spawn launcher), ("M-S-e", spawn enableEDP1), ("M-S-h", spawn enableHDMI1), ("M-S-", spawn myTerminal), ("M-", kill1), -- Layout control ("M-z", sendMessage Expand), ("M-d", sendMessage NextLayout), ("M-v", sendMessage Shrink), ("M-C-S-l", spawn myScreenLock), ("M-C-d", setLayout $ Layout (layoutHook myConfig)), ("M-C-w", shiftToProjectPrompt promptTheme), ("M-w", switchProjectPrompt promptTheme), -- Environment controls ("", spawn volumeDown), ("", spawn volumeMute), ("", spawn volumeUp), ("", spawn brightnessDown), ("", spawn brightnessUp), ("", spawn hibernate) ] -- Navigation ++ zipWith (makeKeybindZipper "M-" windowGo) htnsKeys dirs ++ zipWith (makeKeybindZipper "M-" windowSwap) gcrlKeys dirs ++ zipWith (makeKeybindZipper "M-C-" screenGo) htnsKeys dirs ++ zipWith (makeKeybindZipper "M-C-" windowToScreen) gcrlKeys dirs where makeKeybindZipper :: String -> (direction2D -> Bool -> xUnit) -> String -> direction2D -> (String, xUnit) makeKeybindZipper startOfCmd func restOfCmd dir = (startOfCmd ++ restOfCmd, func dir True) dirs :: [Direction2D] dirs = [L, D, U, R] gcrlKeys :: [String] gcrlKeys = ["g", "c", "r", "l"] htnsKeys :: [String] htnsKeys = ["h", "t", "n", "s"] ------------ -- Layout -- ------------ -- myLayout :: Choose (ModifiedLayout Spacing Tall) (Choose (Mirror (ModifiedLayout Spacing Tall)) Full) a myLayout = spacedThreeColMid ||| spacedSpiral ||| tiled ||| Mirror tiled ||| Full where tiled = spacing 3 $ Tall nmaster delta ratio spacedSpiral = spacing 3 $ spiral (6/7) spacedThreeColMid = spacing 3 $ ThreeColMid nmaster delta ratio nmaster = 1 ratio = 1 / 2 delta = 3 / 100 ---------------- -- Navigation -- ---------------- myNav2DConf :: Navigation2DConfig myNav2DConf = def {defaultTiledNavigation = sideNavigation} ------------- -- Palette -- ------------- -- solarized base03, base02, base01, base00, base0, base1, base2, base3, yellow, orange, red, magenta, violet, blue, cyan, green :: String base03 = "#002b36" base02 = "#073642" base01 = "#586e75" base00 = "#657b83" base0 = "#839496" base1 = "#93a1a1" base2 = "#eee8d5" base3 = "#fdf6e3" yellow = "#b58900" orange = "#cb4b16" red = "#dc322f" magenta = "#d33682" violet = "#6c71c4" blue = "#268bd2" cyan = "#2aa198" green = "#859900" -- uses of palette myNormalBorderColor :: String myNormalBorderColor = violet myFocusedBorderColor :: String myFocusedBorderColor = red