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.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 ~/.dotfiles/media/backgrounds/forest-1.jpg --bg-fill ~/.dotfiles/media/backgrounds/forest-2.jpg --bg-fill ~/.dotfiles/media/backgrounds/forest-3.jpg" ------------ -- 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" incognitoBrowser = "brave -incognito" launcher = "rofi -show drun -m DisplayPort-1" logseq = "logseq" musicPlayer = "spotify" obs = "obs" screenshot = "flameshot gui" terminal = "termonad" -------------- -- Keybinds -- -------------- myKeybinds :: [(String, X ())] myKeybinds = [ -- Spawn/kill ("M-b", spawn browser), ("M-i", spawn incognitoBrowser), ("M-f", spawn screenshot), ("M-", spawn launcher), ("M-S-", spawn Main.terminal), ("M-", kill1), -- Layout control ("M-z", sendMessage Expand), ("M-d", sendMessage NextLayout), ("M-v", sendMessage Shrink), ("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 = 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