{-# OPTIONS_GHC -Wno-missing-signatures #-} {-# OPTIONS_GHC -Wno-orphans #-} {-# LANGUAGE BlockArguments #-} {-# LANGUAGE ImportQualifiedPost #-} {-# LANGUAGE InstanceSigs #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE MultiWayIf #-} {-# LANGUAGE PostfixOperators #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} -- Imports import XMonad import Data.Monoid import System.Exit import XMonad.Util.Run import XMonad.Util.SpawnOnce import XMonad.Hooks.DynamicLog import XMonad.Hooks.ManageDocks import XMonad.Layout.Spacing import XMonad.Layout.ThreeColumns import XMonad.Layout.LayoutModifier import XMonad.Layout.Renamed import XMonad.Hooks.SetWMName import XMonad.Util.Cursor import XMonad.Layout.NoBorders import XMonad.Layout.PerWorkspace import XMonad.Hooks.EwmhDesktops import XMonad.Util.EZConfig import XMonad.Util.NamedScratchpad import XMonad.Actions.TopicSpace import XMonad.Prompt import XMonad.Prompt.FuzzyMatch import XMonad.Prompt.Shell import XMonad.Prompt.Workspace import XMonad.Hooks.WorkspaceHistory (workspaceHistoryHook) import XMonad.Hooks.OnPropertyChange import qualified XMonad.StackSet as W import qualified Data.Map as M import Text.Regex.Posix import XMonad.Util.WorkspaceCompare ( getSortByIndex, filterOutWs ) import Data.Maybe (fromMaybe) import qualified XMonad.Actions.Search as S import qualified XMonad.Prompt as P -- colours white :: String = "#dcdccc" yellow :: String = "#efef8f" orange :: String = "#ffcfaf" red :: String = "#dca3a3" blue :: String = "#8cd0d3" darkBlue :: String = "#8c8cbc" green :: String = "#7f9f7f" grey :: String = "#3f3f3f" darkGrey :: String = "#262626" -- variables myTerminal = "alacritty" myBorderWidth = 1 myModMask = mod4Mask -- scratchpads myScratchpads :: [NamedScratchpad] myScratchpads = [ NS "keepassxc" "keepassxc ~/dokumente/Database.kdbx" (title =? "Database.kdbx - KeePassXC" <||> title =? "Database.kdbx [Gesperrt] - KeePassXC") defaultFloating , NS "nnn" "alacritty -t nnn -e run_in_bash n" (title =? "nnn") (customFloating $ W.RationalRect (1/4) (1/6) (2/4) (4/6)) , NS "vimwiki" "alacritty -t vimwiki -e run_in_bash vw" (title =? "vimwiki") (customFloating $ W.RationalRect (1/6) (1/6) (2/3) (2/3)) , NS "pavucontrol" "pavucontrol" (title =? "Lautstärkeregler") (customFloating $ W.RationalRect (1/6) (1/6) (2/3) (2/3)) , NS "cmus" "alacritty -n cmus -e cmus" (resource =? "cmus") (customFloating $ W.RationalRect (1/6) (1/6) (4/6) (4/6)) , NS "qalculate" "qalculate-gtk" (title =? "Qalculate!") (customFloating $ W.RationalRect (3/6) (1/6) (1/6) (1/6)) ] -- Topic Space topicItems :: [TopicItem] topicItems = [ noAction "1" "~/" , noAction "2" "~/" , noAction "3" "~/" , noAction "4" "~/" , noAction "5" "~/" , TI "alkaa" "~/projekte/alkaa" (switchToLayout "Programming" *> spawnShell *> spawnEditor) ] myTopicConfig :: TopicConfig myTopicConfig = def { topicDirs = tiDirs topicItems , topicActions = tiActions topicItems , defaultTopicAction = const (pure ()) -- by default, do nothing , defaultTopic = "1" -- fallback } spawnShell :: X () spawnShell = proc $ termInDir >-$ currentTopicDir myTopicConfig spawnEditor :: X () spawnEditor = proc $ (termInDir >-$ currentTopicDir myTopicConfig) >-> execute "nvim" switchToLayout :: String -> X () switchToLayout = sendMessage . JumpToLayout spawnShellAndExecute :: String -> X () spawnShellAndExecute cmd = proc $ (termInDir >-$ currentTopicDir myTopicConfig) >-> execute cmd toggleTopic :: X () toggleTopic = switchNthLastFocusedByScreen myTopicConfig 1 myWorkSpacePrompt :: XPConfig -> (String -> X ()) -> X () myWorkSpacePrompt c job = do ws <- gets (W.workspaces . windowset) sort <- getSortByIndex let filter = filterOutWs ["1", "2", "3", "4", "5", "NSP"] let ts = map W.tag $ filter ws mkXPrompt (Wor "") c (mkComplFunFromList' c ts) job topicPrompt :: XPConfig topicPrompt = def { historySize = 0 -- No history in the prompt. , fgColor = white , fgHLight = "#3f3f3f" , bgHLight = red , alwaysHighlight = True -- Current best match , height = 25 , position = CenteredAt 0.45 0.3 , promptBorderWidth = myBorderWidth -- Fit in with rest of config , borderColor = red , maxComplRows = Just 10 -- Max rows to show in completion window , maxComplColumns = Just 1 , searchPredicate = fuzzyMatch , sorter = fuzzySort } searx :: S.SearchEngine searx = S.searchEngine "searx" "https://search.tfld.de/search?q=" wiktionary :: S.SearchEngine wiktionary = S.searchEngine "wiktionary" "https://wiktionary.org/w/index.php?search=" searchList :: [(String, S.SearchEngine)] searchList = [ ("o", S.openstreetmap) , ("h", S.hackage) , ("w", S.wikipedia) , ("y", S.youtube) , ("s", searx) , ("t", wiktionary) ] -- custom keybinds myAdditionalKeys :: [(String, X ())] myAdditionalKeys = -- xmonad specific [ ("M-q", spawn "xmonad --recompile; xmonad --restart") , ("M-S-c", kill) , ("M-j", windows W.focusDown) , ("M-k", windows W.focusUp) , ("M-S-j", windows W.swapDown) , ("M-S-k", windows W.swapUp) , ("M-h", sendMessage Shrink) , ("M-l", sendMessage Expand) , ("M-,", sendMessage (IncMasterN 1)) , ("M-S-,", sendMessage (IncMasterN (-1))) , ("M-.", sendMessage ToggleStruts) -- dmenu prompts , ("M-", spawn "dmenu_run") , ("M-p s", spawn "dmenu_screenshot") , ("M-p k", spawn "dmenu_kill") -- scratchpads , ("M-n", namedScratchpadAction myScratchpads "nnn") , ("M-S-a", namedScratchpadAction myScratchpads "keepassxc") , ("M-s v", namedScratchpadAction myScratchpads "vimwiki") , ("M-s a", namedScratchpadAction myScratchpads "pavucontrol") , ("M-s c", namedScratchpadAction myScratchpads "cmus") , ("M-s q", namedScratchpadAction myScratchpads "qalculate") , ("M-s g", spawnShellAndExecute "lazygit") -- open terminal , ("M-S-", spawnShell) , ("M-b", spawn "librewolf") -- layout , ("M-t t", switchToLayout "Tall") , ("M-t p", switchToLayout "Programming") , ("M-t f", switchToLayout "Full") , ("M-S-f", withFocused $ windows . W.sink) -- media keys , ("", spawn "pamixer -t" *> spawn "brightnessctl -q -d platform::mute s $((1-$(brightnessctl -d platform::mute g)))") , ("", spawn "pamixer -d 5") , ("", spawn "pamixer -i 5") , ("", spawn "pamixer --default-source -t" *> spawn "brightnessctl -q -d platform::micmute s $((1-$(brightnessctl -d platform::micmute g)))") , ("", spawn "brightnessctl -q -- s '-10%'") , ("", spawn "brightnessctl -q -- s '+10%'") -- lock screen , ("M-S-l", spawn "slock") -- workspace switching , ("M-", toggleTopic) , ("M-", myWorkSpacePrompt topicPrompt (switchTopic myTopicConfig)) , ("M-S-", myWorkSpacePrompt topicPrompt (windows . W.shift)) ] ++ [ ("M-" ++ m ++ k, f i) | (i, k) <- zip (topicNames topicItems) (map show [1 .. 5 :: Int]) , (f, m) <- [(switchTopic myTopicConfig, ""), (windows . W.shift, "S-")] ] -- Search commands ++ [("M-d " ++ k, S.promptSearch topicPrompt f) | (k,f) <- searchList ] ++ [("M-S-d " ++ k, S.selectSearch f) | (k,f) <- searchList ] -- Layouts 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 myLayout = avoidStruts $ tiling ||| hacking ||| full where tiling = renamed [Replace "Tall"] $ smartBorders $ mySpacing 6 $ Tall 1 (3/100) (1/2) hacking = renamed [Replace "Programming"] $ smartBorders $ mySpacing 6 $ Tall 1 (3/100) (5/8) full = noBorders Full -- Regex lifted up to use in manageHook (*!?) :: Functor f => f String -> String -> f Bool q *!? x = fmap (=~ x) q -- window rules myManageHook = composeAll . concat $ [ [ resource =? "desktop_window" --> doIgnore ] , [ resource =? "kdesktop" --> doIgnore ] , [ ( className =? "LibreWolf" <&&> role =? "Organizer" ) --> doFloat ] -- float specific classes , [ className =? c --> doFloat | c <- myFloatingClasses ] -- scratchpads , [ namedScratchpadManageHook myScratchpads ] ] where role = stringProperty "WM_WINDOW_ROLE" myFloatingClasses = ["Gimp", "Origin"] ------------------------------------------------------------------------ -- Event handling -- * EwmhDesktops users should change this to ewmhDesktopsEventHook -- -- Defines a custom handler function for X Events. The function should -- return (All True) if the default handler is to be run afterwards. To -- combine event hooks use mappend or mconcat from Data.Monoid. -- myEventHook = onXPropertyChange "WM_NAME" (title =? "Database.kdbx - KeePassXC" <||> title =? "Database.kdbx [Gesperrt] - KeePassXC" --> floating) where floating = customFloating $ W.RationalRect (1/8) (1/8) (3/4) (3/4) ------------------------------------------------------------------------ -- Status bars and logging -- Perform an arbitrary action on each internal state change or X event. -- See the 'XMonad.Hooks.DynamicLog' extension for examples. -- -- myLogHook = return () -- Startup hook myStartupHook = do setWMName "LG3D" setDefaultCursor xC_left_ptr spawnOnce "redshift -l 51.33:12.40" spawnOnce "safeeyes -e" spawnOnce "/usr/bin/dunst" spawnOnce "feh --bg-fill ~/bilder/bg.jpg ~/bilder/bg.jpg" -- Main main = do xmproc0 <- spawnPipe "xmobar -x 0 /home/max/.config/xmobar/xmobarrc" xmproc1 <- spawnPipe "xmobar -x 1 /home/max/.config/xmobar/xmobarrc" xmonad $ ewmh . spawnExternalProcess def $ docks def { -- simple stuff terminal = myTerminal, borderWidth = myBorderWidth, modMask = myModMask, workspaces = topicNames topicItems, normalBorderColor = white, focusedBorderColor = red, keys = mempty, -- hooks, layouts layoutHook = myLayout, manageHook = myManageHook, handleEventHook = myEventHook, logHook = workspaceHistoryHook >> (dynamicLogWithPP $ filterOutWsPP ["NSP"] $ xmobarPP { ppCurrent = xmobarColor "#dca3a3" "" . wrap "[ " " ]", ppHidden = xmobarColor "#8cd0d3" "", ppLayout = xmobarColor "#8c8cbc" "", ppTitle = xmobarColor "#ffcfaf" "" . shorten 100, ppSep = " | ", ppOutput = \x -> hPutStrLn xmproc0 x >> hPutStrLn xmproc1 x }), startupHook = myStartupHook } `additionalKeysP` myAdditionalKeys