diff --git a/flake.nix b/flake.nix index 3e2fa9b..c562b86 100644 --- a/flake.nix +++ b/flake.nix @@ -27,7 +27,11 @@ in { default = pkgs.mkShell { - packages = with pkgs; [ git-crypt stylua ]; + packages = with pkgs; [ + git-crypt + stylua # lua formatter + ormolu # haskell formatter + ]; }; }; }; diff --git a/home/ui/xmonad/config.hs b/home/ui/xmonad/config.hs index ecaef36..0468fff 100644 --- a/home/ui/xmonad/config.hs +++ b/home/ui/xmonad/config.hs @@ -7,40 +7,46 @@ -- Normally, you'd only override those defaults you care about. -- -import Data.Monoid -import System.Exit -import XMonad -import XMonad.Actions.CycleSelectedLayouts (cycleThroughLayouts) -import XMonad.Actions.EasyMotion (ChordKeys (..), - EasyMotionConfig (..), - selectWindow) -import XMonad.Hooks.DynamicLog -import XMonad.Hooks.EwmhDesktops -import XMonad.Hooks.ManageDocks -import XMonad.Hooks.StatusBar -import XMonad.Hooks.StatusBar.PP -import XMonad.Layout.BoringWindows (boringWindows) -import XMonad.Layout.Gaps (gaps) -import XMonad.Layout.Grid -import XMonad.Layout.LimitWindows (limitWindows) -import XMonad.Layout.NoBorders (smartBorders) -import XMonad.Layout.Spacing (spacing) -import XMonad.Layout.ThreeColumns (ThreeCol (..)) -import XMonad.Util.EZConfig -import XMonad.Util.Run - -import qualified Data.Map as M -import qualified XMonad.StackSet as W - -- Imports for Polybar -import qualified Codec.Binary.UTF8.String as UTF8 -import qualified DBus as D -import qualified DBus.Client as D +import qualified Codec.Binary.UTF8.String as UTF8 +import qualified DBus as D +import qualified DBus.Client as D +import qualified Data.Map as M +import Data.Monoid +import System.Exit +import XMonad +import XMonad.Actions.CycleSelectedLayouts (cycleThroughLayouts) +import XMonad.Actions.EasyMotion + ( ChordKeys (..), + EasyMotionConfig (..), + selectWindow, + ) +import XMonad.Hooks.DynamicLog +import XMonad.Hooks.EwmhDesktops +import XMonad.Hooks.ManageDocks +import XMonad.Hooks.ManageHelpers + ( composeOne, + doCenterFloat, + isDialog, + (-?>), + ) +import XMonad.Hooks.StatusBar +import XMonad.Hooks.StatusBar.PP +import XMonad.Layout.BoringWindows (boringWindows) +import XMonad.Layout.Gaps (gaps) +import XMonad.Layout.Grid +import XMonad.Layout.LimitWindows (limitWindows) +import XMonad.Layout.NoBorders (smartBorders) +import XMonad.Layout.Spacing (spacing) +import XMonad.Layout.ThreeColumns (ThreeCol (..)) +import qualified XMonad.StackSet as W +import XMonad.Util.EZConfig +import XMonad.Util.Run -- The preferred terminal program, which is used in a binding below and by -- certain contrib modules. -- -myTerminal = "alacritty" +myTerminal = "alacritty" -- Whether focus follows the mouse pointer. myFocusFollowsMouse :: Bool @@ -52,59 +58,73 @@ myClickJustFocuses = False -- Width of the window border in pixels. -- -myBorderWidth = 2 +myBorderWidth = 2 -- modMask lets you specify which modkey you want to use. The default -- is mod1Mask ("left alt"). You may also consider using mod3Mask -- ("right alt"), which does not conflict with emacs keybindings. The -- "windows key" is usually mod4Mask. -- -myModMask = mod1Mask +myModMask = mod1Mask + +-- Workspaces webWs = "web" + finWs = "fin" + sysWs = "sys" + comWs = "com" + devWs = ["dev", "dev2", "dev3"] + myWorkspaces = [webWs] <> devWs <> [finWs, sysWs, comWs] +-- Colors + +blue = "#2E9AFE" + +gray = "#7F7F7F" -blue = "#2E9AFE" -gray = "#7F7F7F" orange = "#ea4300" + purple = "#9058c7" -red = "#722222" + +red = "#722222" + -- Border colors for unfocused and focused windows, respectively. -- -myNormalBorderColor = gray +myNormalBorderColor = gray + myFocusedBorderColor = blue main :: IO () main = mkDbusClient >>= main' - main' :: D.Client -> IO () -main' dbus = xmonad . docks . ewmhFullscreen . ewmh $ def - -- simple stuff - { terminal = myTerminal - , focusFollowsMouse = myFocusFollowsMouse - , clickJustFocuses = myClickJustFocuses - , borderWidth = myBorderWidth - , modMask = myModMask - , workspaces = myWorkspaces - , normalBorderColor = myNormalBorderColor - , focusedBorderColor = myFocusedBorderColor - -- key bindings - , keys = myKeys - , mouseBindings = myMouseBindings - -- hooks, layouts - , layoutHook = myLayout - , manageHook = myManageHook - , handleEventHook = myEventHook - , logHook = myPolybarLogHook dbus - , startupHook = myStartupHook - } - +main' dbus = + xmonad . docks . ewmhFullscreen . ewmh $ + def + { -- simple stuff + terminal = myTerminal, + focusFollowsMouse = myFocusFollowsMouse, + clickJustFocuses = myClickJustFocuses, + borderWidth = myBorderWidth, + modMask = myModMask, + workspaces = myWorkspaces, + normalBorderColor = myNormalBorderColor, + focusedBorderColor = myFocusedBorderColor, + -- key bindings + keys = myKeys, + mouseBindings = myMouseBindings, + -- hooks, layouts + layoutHook = myLayout, + manageHook = myManageHook, + handleEventHook = myEventHook, + logHook = myPolybarLogHook dbus, + startupHook = myStartupHook + } ------------------------------------------------------------------------ -- Polybar settings (needs DBus client). @@ -114,30 +134,31 @@ mkDbusClient = do dbus <- D.connectSession D.requestName dbus (D.busName_ "org.xmonad.log") opts return dbus - where - opts = [D.nameAllowReplacement, D.nameReplaceExisting, D.nameDoNotQueue] + where + opts = [D.nameAllowReplacement, D.nameReplaceExisting, D.nameDoNotQueue] -- Emit a DBus signal on log updates dbusOutput :: D.Client -> String -> IO () dbusOutput dbus str = - let opath = D.objectPath_ "/org/xmonad/Log" - iname = D.interfaceName_ "org.xmonad.Log" - mname = D.memberName_ "Update" + let opath = D.objectPath_ "/org/xmonad/Log" + iname = D.interfaceName_ "org.xmonad.Log" + mname = D.memberName_ "Update" signal = D.signal opath iname mname - body = [D.toVariant $ UTF8.decodeString str] - in D.emit dbus $ signal { D.signalBody = body } + body = [D.toVariant $ UTF8.decodeString str] + in D.emit dbus $ signal {D.signalBody = body} polybarHook :: D.Client -> PP polybarHook dbus = let wrapper c = wrap ("%{F" <> c <> "}") "%{F-}" - in def { ppOutput = dbusOutput dbus - , ppCurrent = wrapper blue - , ppVisible = wrapper purple - , ppUrgent = wrapper orange - , ppHidden = wrapper gray - , ppHiddenNoWindows = wrapper red - , ppTitle = wrapper purple . shorten 90 - } + in def + { ppOutput = dbusOutput dbus, + ppCurrent = wrapper blue, + ppVisible = wrapper purple, + ppUrgent = wrapper orange, + ppHidden = wrapper gray, + ppHiddenNoWindows = wrapper red, + ppTitle = wrapper purple . shorten 90 + } myPolybarLogHook dbus = myLogHook <+> dynamicLogWithPP (polybarHook dbus) @@ -159,8 +180,8 @@ myLayout = avoidStruts . smartBorders $ (Mirror tiled ||| tiled ||| column3 ||| column3 = gapSpaced 5 $ ThreeColMid nmaster incRatio ratio nmaster = 1 - incRatio = (3/100) - ratio = (1/2) + incRatio = (3 / 100) + ratio = (1 / 2) gapSpaced g = spacing g . myGaps g myGaps gap = gaps [(U, gap), (D, gap), (L, gap), (R, gap)] @@ -187,6 +208,7 @@ myLogHook = return () -- 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 @@ -209,124 +231,112 @@ myEventHook = mempty -- To match on the WM_NAME, you can use 'title' in the same way that -- 'className' and 'resource' are used below. -- -myManageHook = composeAll - [ resource =? "desktop_window" --> doIgnore - , resource =? "kdesktop" --> doIgnore - -- apps - , className =? "Gimp" --> doFloat - , className =? "Gnome-calculator" --> doFloat - , className =? "Gnome-font-viewer" --> doFloat - , className =? "Org.gnome.Nautilus" --> doFloat - , className =? "KotatogramDesktop" --> doShift comWs - -- my libs - , resource =? "hwt" --> doFloat - ] - +myManageHook = manageApps + where + isRole = stringProperty "WM_WINDOW_ROLE" + isPopup = isRole =? "pop-up" + manageApps = + composeOne + [ resource =? "desktop_window" -?> doIgnore, + resource =? "kdesktop" -?> doIgnore, + -- general + isPopup -?> doCenterFloat, + isDialog -?> doCenterFloat, + -- apps + className =? "Gimp" -?> doFloat, + className =? "nheko" -?> doShift comWs, + className =? "KotatogramDesktop" -?> doShift comWs, + className =? "gnome-calculator" -?> doCenterFloat + ] ------------------------------------------------------------------------ -- Key bindings. Add, modify or remove key bindings here. -- -myKeys conf = mkKeymap conf $ - - -- launch a terminal - [ ("M-S-", spawn $ XMonad.terminal conf) - - -- launch a 'flameshot' to screenshot - , ("M-S-s", safeSpawn "flameshot" ["gui"]) - - -- launch 'librewolf' browser - , ("M-S-b", spawn "librewolf") - - -- launch 'dmenu_run' to choose applications - , ("M-p", spawn "dmenu_run") - - -- close focused window - , ("M4-S-c", kill) - - -- Rotate through the available layout algorithms - , ("M-", cycleThroughLayouts ["Full", "Mirror Spacing Tall"]) - , ("M-", cycleThroughLayouts ["Spacing ThreeCol", "Spacing Tall", "Mirror Spacing Tall"]) - - -- Reset the layouts on the current workspace to default - , ("M-S-", setLayout $ XMonad.layoutHook conf) - - -- Resize viewed windows to the correct size - , ("M-n", refresh) - - -- Easy moution to focus windows - , ("M-s", selectWindow def{sKeys = AnyKeys [xK_a, xK_o, xK_e, xK_u, xK_h, xK_t, xK_n, xK_s]} >>= (`whenJust` windows . W.focusWindow)) - -- Move focus to the next window - , ("M-j", windows W.focusDown) - -- Move focus to the previous window - , ("M-k", windows W.focusUp) - -- Move focus to the master window - , ("M-m", windows W.focusMaster) - - -- Swap the focused window and the master window - , ("M-", windows W.swapMaster) - -- Swap the focused window with the next window - , ("M-S-j", windows W.swapDown) - -- Swap the focused window with the previous window - , ("M-S-k", windows W.swapUp) - - -- Shrink the master area - , ("M-h", sendMessage Shrink) - -- Expand the master area - , ("M-l", sendMessage Expand) - - -- Push window back into tiling - , ("M-t", withFocused $ windows . W.sink) - - -- Increment the number of windows in the master area - , ("M-,", sendMessage $ IncMasterN 1) - -- Deincrement the number of windows in the master area - , ("M-.", sendMessage $ IncMasterN (-1)) - - -- Toggle the status bar gap - -- Use this binding with avoidStruts from Hooks.ManageDocks. - -- See also the statusBar function from Hooks.DynamicLog. - -- - -- , ("M-b", sendMessage ToggleStruts) - - - -- Lock screen - , ("M4-l", spawn "betterlockscreen --lock --display 1 -- -e") - - -- Change volume - , ("", spawn "amixer -q sset Master toggle") - , ("", spawn "amixer -q sset Master 5%+") - , ("", spawn "amixer -q sset Master 5%-") - - -- Keyboard apps - , ("", spawn "gnome-calculator") - - -- Quit xmonad - , ("M4-S-q", io exitSuccess) - - ] - ++ - - -- - -- mod-[1..9], Switch to workspace N - -- mod-shift-[1..9], Move client to workspace N - -- - [("M-" ++ m ++ show k, windows $ f i) - | (i, k) <- zip (XMonad.workspaces conf) [1..9] - , (f, m) <- [(W.greedyView, ""), (W.shift, "S-")]] +myKeys conf = + mkKeymap conf $ + -- launch a terminal + [ ("M-S-", spawn $ XMonad.terminal conf), + -- launch a 'flameshot' to screenshot + ("M-S-s", safeSpawn "flameshot" ["gui"]), + -- launch 'librewolf' browser + ("M-S-b", spawn "librewolf"), + -- launch 'dmenu_run' to choose applications + ("M-p", spawn "dmenu_run"), + -- close focused window + ("M4-S-c", kill), + -- Rotate through the available layout algorithms + ("M-", cycleThroughLayouts ["Full", "Mirror Spacing Tall"]), + ("M-", cycleThroughLayouts ["Spacing ThreeCol", "Spacing Tall", "Mirror Spacing Tall"]), + -- Reset the layouts on the current workspace to default + ("M-S-", setLayout $ XMonad.layoutHook conf), + -- Resize viewed windows to the correct size + ("M-n", refresh), + -- Easy moution to focus windows + ("M-s", selectWindow easyMotionConfig >>= (`whenJust` windows . W.focusWindow)), + -- Move focus to the next window + ("M-j", windows W.focusDown), + -- Move focus to the previous window + ("M-k", windows W.focusUp), + -- Move focus to the master window + ("M-m", windows W.focusMaster), + -- Swap the focused window and the master window + ("M-", windows W.swapMaster), + -- Swap the focused window with the next window + ("M-S-j", windows W.swapDown), + -- Swap the focused window with the previous window + ("M-S-k", windows W.swapUp), + -- Shrink the master area + ("M-h", sendMessage Shrink), + -- Expand the master area + ("M-l", sendMessage Expand), + -- Push window back into tiling + ("M-t", withFocused $ windows . W.sink), + -- Increment the number of windows in the master area + ("M-,", sendMessage $ IncMasterN 1), + -- Deincrement the number of windows in the master area + ("M-.", sendMessage $ IncMasterN (-1)), + -- Toggle the status bar gap + -- Use this binding with avoidStruts from Hooks.ManageDocks. + -- See also the statusBar function from Hooks.DynamicLog. + -- + -- , ("M-b", sendMessage ToggleStruts) + -- Lock screen + ("M4-l", spawn "betterlockscreen --lock --display 1 -- -e"), + -- Change volume + ("", spawn "amixer -q sset Master toggle"), + ("", spawn "amixer -q sset Master 5%+"), + ("", spawn "amixer -q sset Master 5%-"), + -- Keyboard apps + ("", spawn "gnome-calculator"), + -- Quit xmonad + ("M4-S-q", io exitSuccess) + ] + ++ + -- + -- mod-[1..9], Switch to workspace N + -- mod-shift-[1..9], Move client to workspace N + -- + [ ("M-" ++ m ++ show k, windows $ f i) + | (i, k) <- zip (XMonad.workspaces conf) [1 .. 9], + (f, m) <- [(W.greedyView, ""), (W.shift, "S-")] + ] + where + easyMotionConfig = + def + { sKeys = AnyKeys [xK_a, xK_o, xK_e, xK_u, xK_h, xK_t, xK_n, xK_s] + } ------------------------------------------------------------------------ -- Mouse bindings: default actions bound to mouse events -- -myMouseBindings (XConfig {XMonad.modMask = modm}) = M.fromList +myMouseBindings (XConfig {XMonad.modMask = modm}) = + M.fromList -- mod-button1, Set the window to floating mode and move by dragging - [ ((modm, button1), \w -> focus w >> mouseMoveWindow w >> windows W.shiftMaster) - - -- mod-button2, Raise the window to the top of the stack - , ((modm, button2), \w -> focus w >> windows W.shiftMaster) - - -- mod-button3, Set the window to floating mode and resize by dragging - , ((modm, button3), \w -> focus w >> mouseResizeWindow w >> windows W.shiftMaster) - - -- you may also bind events to the mouse scroll wheel (button4 and button5) + [ ((modm, button1), \w -> focus w >> mouseMoveWindow w >> windows W.shiftMaster), + -- mod-button2, Raise the window to the top of the stack + ((modm, button2), \w -> focus w >> windows W.shiftMaster), + -- mod-button3, Set the window to floating mode and resize by dragging + ((modm, button3), \w -> focus w >> mouseResizeWindow w >> windows W.shiftMaster) + -- you may also bind events to the mouse scroll wheel (button4 and button5) ]