dots/.xmonad/xmonad.hs

288 lines
9.2 KiB
Haskell

-- {{{ Imports
import Control.Monad (liftM2)
import XMonad
import XMonad.Actions.CopyWindow (copyToAll, killAllOtherCopies)
import XMonad.Actions.FloatSnap
import XMonad.Hooks.EwmhDesktops
import XMonad.Hooks.ManageDocks
import XMonad.Hooks.ManageHelpers
import XMonad.Hooks.OnPropertyChange (onXPropertyChange)
import XMonad.Hooks.StatusBar
import XMonad.Hooks.StatusBar.PP
import XMonad.Layout.CenteredIfSingle
import XMonad.Layout.IndependentScreens
import XMonad.Layout.PerScreen
import XMonad.Layout.Renamed
import XMonad.Layout.ShowWName
import XMonad.Layout.ThreeColumns
import XMonad.Util.EZConfig
import XMonad.Util.Loggers
import XMonad.Util.Paste
import qualified XMonad.StackSet as W
import qualified XMonad.Util.Hacks as Hacks
-- }}}
-- Statusbar {{{
pp' :: ScreenId -> PP -> PP
pp' s pp = (marshallPP s pp) { ppSort = ppSort pp }
pp :: PP
pp =
def
{ ppSep = tertiaryColor " ",
ppCurrent = brackitify,
ppHidden = secondaryColor,
ppHiddenNoWindows = tertiaryColor,
ppUrgent = red . wrap (yellow "!") (yellow "!"),
ppLayout = id,
ppTitle = shorten 80,
ppTitleSanitize = xmobarStrip,
ppOrder = \[workspaces, layout, windows, _] -> [workspaces, layout, windows],
ppExtras = [logTitles formatFocused formatUnfocused]
}
where
brackitify = wrap "" ""
formatFocused = secondaryColor . ppWindow
formatUnfocused = tertiaryColor . ppWindow
ppWindow = xmobarRaw . (\w -> if null w then "Untitled" else w) . shorten 16
primaryColor = xmobarColor "#000000" ""
secondaryColor = xmobarColor "#333333" ""
tertiaryColor = xmobarColor "#555555" ""
yellow = xmobarColor "#ff0" ""
red = xmobarColor "#ff5555" ""
-- }}}
-- Workspaces & screens {{{
-- Shift to workspace and view workspace
shiftAndView = doF . liftM2 (.) W.greedyView W.shift
-- }}}
-- Hooks {{{
-- startupHook
myStartupHook =
do
spawn "killall polybar && polybar -r"
-- manageHook
myManageHook :: ManageHook
myManageHook =
composeAll
[ isDialog --> doCenterFloat,
className =? "Zathura" --> doShift "1_info",
className =? "firefox" --> shiftAndView "1_www",
className =? "firefoxdeveloperedition" --> shiftAndView "1_www",
className =? "Anki" --> shiftAndView "1_etc",
className =? "Obsidian" --> shiftAndView "1_etc",
className =? "Launcher" --> doRectFloat (W.RationalRect 0.05 0.4 0.9 0.5),
className =? "Zettelkasten" --> doRectFloat (W.RationalRect 0.05 0.4 0.9 0.5),
className =? "Calculator" --> doCenterFloat,
className =? "feh" --> doCenterFloat,
-- Center matplotlib and prevent focus stealing
-- className =? "matplotlib" --> doRectFloat (W.RationalRect 0.5 0.5 0.5 0.5),
className =? "matplotlib" --> doCenterFloat,
className =? "Matplotlib" --> doCenterFloat,
className =? "Xournalpp" --> doRectFloat (W.RationalRect 0.5 0.5 0.5 0.5),
className =? "KeePassXC" --> doRectFloat (W.RationalRect 0.1 0.1 0.8 0.8),
className =? "flameshot" --> doRectFloat (W.RationalRect 0.1 0.1 0.8 0.8)
]
myDynamicManageHook :: ManageHook
myDynamicManageHook =
composeAll
[
title =? "Zettelkasten — Firefox Developer Edition" --> doShift "1_sh"
]
-- TODO: Replace showWName by dunst notification
myShowWNameConfig :: SWNConfig
myShowWNameConfig =
def
{ swn_font = "xft:Iosevka Term SS08:size=16",
swn_fade = 0.3,
swn_color = "#111111",
swn_bgcolor = "#cccccc"
}
-- layoutHook
myLayoutHook =
showWName' myShowWNameConfig $
ifWider smallWidth (
t ||| -- Tiled layouts
c3 ||| -- Column layouts
c3m ||| --
f -- Monocle layouts
) (
t ||| -- Tiled layouts
f -- Monocle layouts
)
where
smallWidth = 1920
t = renamed [Replace "[]+"] $ ifWider smallWidth (centeredIfSingle 0.8 0.9 $ Tall nmaster delta ratio)
(Tall nmaster delta ratio)
c3 = renamed [Replace "|||"] $ ThreeCol nmaster delta ratio
c3m = renamed [Replace "[|]"] $ ThreeColMid nmaster delta ratio
f = renamed [Replace "[+]"] Full
nmaster = 1
ratio = 1 / 2
delta = 4 / 100
-- }}}
-- Main config {{{
myWorkspaces = [ "sh", "www", "dev", "info", "etc" ]
myWorkspaceKeys = [ "a", "s", "d", "f", "g" ]
mySharedWorkspaces = [ "shared" ]
mySharedWorkspaceKeys = [ "1" ]
-- Use Win key instead of Alt
myModMask = mod4Mask
myConfig =
def
{ terminal = "alacritty",
modMask = myModMask,
workspaces = withScreen 1 myWorkspaces ++ withScreen 2 mySharedWorkspaces,
-- Styling
focusedBorderColor = "#000",
normalBorderColor = "#0000",
borderWidth = 4,
-- Hooks
startupHook = myStartupHook,
manageHook = myManageHook <+> manageHook def,
layoutHook = avoidStruts myLayoutHook,
handleEventHook = onXPropertyChange "WM_NAME" myDynamicManageHook <> handleEventHook def <> Hacks.windowedFullscreenFixEventHook
}
`removeKeysP` myRemoveKeys
`additionalKeysP` myKeys
`additionalMouseBindings` myMouseBindings
-- }}}
-- Keybindings {{{
-- Keybindings to be added/overridden
myKeys :: [(String, X ())]
myKeys =
[ ("M-<Space> s", unfloatFocusedW),
("M-<Space> <Space>", nextLayout), -- Cycle through layouts
("M-<Space> S-<Space>", defaultLayout), --
("M-<Space> M-<Space>", nextLayout), -- ..fat finger
("M-<Space> M-S-<Space>", defaultLayout), --
("<F8>", spawnKeepassXC),
("M-z", spawnZettelkasten),
("M-p", spawnLauncher),
("<Insert>", pasteSelection),
("<Print>", printScreen),
("<XF86AudioRaiseVolume>", raiseVol), -- Audio volume & playback
("<XF86AudioLowerVolume>", lowerVol), --
("<XF86AudioMute>", mute), --
("M-<Right>", nextTrack), --
("M-<Left>", prevTrack), --
("M-<Up>", play), --
("M-<Down>", pause), --
("<XF86MonBrightnessUp>", brighten), -- Brightness & hue controls
("<XF86MonBrightnessDown>", dim), --
("S-<XF86MonBrightnessUp>", warm), --
("S-<XF86MonBrightnessDown>", cool), --
("M-S-<XF86MonBrightnessUp>", resetTemp), --
("M-S-<XF86MonBrightnessDown>", resetTemp), --
("M-S-b", fullscreenBrowser),
("<XF86Calculator>", spawnCalculator),
("<XF86PowerOff>", spawn "systemctl suspend"), --TODO: Only enable this on laptop
("M-c", windows copyToAll),
("M-S-c", killAllOtherCopies),
("M-S-<Delete>", kill)
] ++
[ (m ++ k, windows $ f w) |
(m, f) <- zip ["M-", "M-S-"]
[W.greedyView, W.shift],
(k, w) <- zip myWorkspaceKeys
(withScreen 1 myWorkspaces)
++ zip mySharedWorkspaceKeys
(withScreen 2 mySharedWorkspaces)
]
zipKeyPrefixes :: [String] -> [String] -> [String]
zipKeyPrefixes prefixes keys = [prefix ++ key | prefix <- prefixes, key <- keys]
-- Keybindings to be removed
myRemoveKeys :: [String]
myRemoveKeys = "M-S-q" : zipKeyPrefixes ["M-", "M-S-"] (map show [ 1..5 ])
myMouseBindings =
[
((mod4Mask, button1), (\w -> focus w >> mouseMoveWindow w >> afterDrag (snapMagicMove (Just 50) (Just 50) w)))
, ((mod4Mask .|. shiftMask, button1), (\w -> focus w >> mouseMoveWindow w >> afterDrag (snapMagicResize [L,R,U,D] (Just 50) (Just 50) w)))
, ((mod4Mask, button3), (\w -> focus w >> mouseResizeWindow w >> afterDrag (snapMagicResize [R,D] (Just 50) (Just 50) w)))
]
unfloatFocusedW :: X ()
unfloatFocusedW = withFocused $ windows . W.sink
myStartupHook :: X ()
nextLayout = sendMessage NextLayout
defaultLayout :: X ()
defaultLayout = setLayout $ Layout myLayoutHook
spawnZettelkasten :: X ()
spawnZettelkasten = spawn "alacritty --class Zettelkasten,Zettelkasten -e nvim $(cat ~/.zk/current-zettel.txt)"
spawnKeepassXC :: X ()
spawnKeepassXC = spawn "keepassxc"
fullscreenBrowser :: X ()
fullscreenBrowser = spawn "firefox --fullscreen"
spawnLauncher, spawnClipManager, spawnCalculator :: X ()
spawnLauncher = spawn "rofi -show drun -show-icons"
spawnClipManager = spawn "rofi -modi 'clipboard:greenclip print' -show clipboard -run-command '{cmd}'"
spawnCalculator = spawn "alacritty --class 'Calculator' -e ipython -i /home/h/.bin/calc.py"
printScreen :: X ()
printScreen = spawn "flameshot gui"
raiseVol, lowerVol, mute :: X ()
raiseVol = spawn "pactl set-sink-volume @DEFAULT_SINK@ +5%"
lowerVol = spawn "pactl set-sink-volume @DEFAULT_SINK@ -5%"
mute = spawn "pactl set-sink-mute @DEFAULT_SINK@ toggle"
nextTrack, prevTrack, play, pause :: X ()
nextTrack = spawn "playerctl next"
prevTrack = spawn "playerctl previous"
play = spawn "playerctl play"
pause = spawn "playerctl pause"
brighten, dim, warm, cool, resetTemp :: X ()
brighten = spawn "brightnessctl set 20+"
dim = spawn "brightnessctl set 20-"
warm = spawn "screen-temperature +50"
cool = spawn "screen-temperature -50"
resetTemp = spawn "screen-temperature 3000"
-- }}}
-- Main {{{
main :: IO ()
main =
do { xmonad } $
ewmh $
withEasySB
(sb1 <> sb2)
defToggleStrutsKey
myConfig
where
[sb1, sb2] = [statusBarProp "polybar" $ pure (pp' (S i) pp) | i <- [0 .. 1]]
-- }}}