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 "xmobar" (pure myXmobarPP)) 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 ------------ -- xmobar -- ------------ myXmobarPP :: PP myXmobarPP = 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 = [wsGEN, wsCOM, wsINT] wsCOM, wsDOT, wsGEN, wsINT, wsLOG, wsMUS, wsREC, wsVID :: String wsCOM = "com" wsDOT = "dot" wsGEN = "gen" wsINT = "int" wsLOG = "log" wsMUS = "mus" wsREC = "rec" wsVID = "vid" -------------- -- Projects -- -------------- projects :: [Project] projects = [ Project { projectName = wsCOM, projectDirectory = "~/", projectStartHook = Just $ do spawnOn wsCOM element }, Project { projectName = wsDOT, projectDirectory = "~/.dotfiles", projectStartHook = Just $ do spawnOn wsDOT $ editor ++ " ." }, Project { projectName = wsGEN, projectDirectory = "~/", projectStartHook = Nothing }, Project { projectName = wsINT, projectDirectory = "~/", projectStartHook = Just $ do spawnOn wsINT browser }, Project { projectName = wsLOG, projectDirectory = "~/", projectStartHook = Just $ do spawnOn wsLOG logseq }, 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 } ] promptTheme :: XPConfig promptTheme = def { bgColor = base03, bgHLight = base02, fgColor = base0, fgHLight = base1, height = 31, position = Top, promptBorderWidth = 0 } ------------------ -- Applications -- ------------------ browser, discord, editor, element, incognitoBrowser, launcher, logseq, musicPlayer, obs, screenshot, terminal :: String browser = "brave" 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" incognitoBrowser = "brave -incognito" launcher = "rofi -show drun" logseq = "logseq" musicPlayer = "spotify" obs = "obs" screenshot = "flameshot gui" terminal = "termonad" myScreenLockCmd = "xscreensaver --no-splash" myScreenLock = "xscreensaver-command -lock" -------------- -- 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 Main.terminal), ("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) ] -- 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 = ThreeColMid 1 (3/100) (1/2) ||| spiral (6/7) ||| tiled ||| Mirror tiled ||| Full where tiled = spacingWithEdge 5 $ Tall nmaster delta ratio nmaster = 1 ratio = 1 / 2 delta = 3 / 100 ---------------- -- Navigation --L ---------------- 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