From 4dd8618f5d32e33afb36ec26d80c5d374051d0fe Mon Sep 17 00:00:00 2001 From: frosty Date: Tue, 16 Jul 2024 05:00:36 -0400 Subject: [PATCH] init --- .gitignore | 1 + xmobar-bottom.hs | 24 ++++ xmobar-top.hs | 24 ++++ xmonad-frosty.cabal | 43 +++++++ xmonad.hs | 271 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 363 insertions(+) create mode 100644 .gitignore create mode 100644 xmobar-bottom.hs create mode 100644 xmobar-top.hs create mode 100644 xmonad-frosty.cabal create mode 100644 xmonad.hs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/build diff --git a/xmobar-bottom.hs b/xmobar-bottom.hs new file mode 100644 index 0000000..9ad0fee --- /dev/null +++ b/xmobar-bottom.hs @@ -0,0 +1,24 @@ +import Xmobar + +config :: Config +config = + defaultConfig + { font = "Terminus 8", + textOffset = 0, + bgColor = "#121212", + fgColor = "#cccccc", + position = Bottom, + template = " %disk-root% %disk-home% | %local-ip% | %ssid% }{ %now-playing% | %volume% ", + commands = + [ Run XMonadLog, + Run $ Com "monitors" ["local_ip"] "local-ip" 6000, + Run $ Com "monitors" ["ssid"] "ssid" 6000, + Run $ Com "monitors" ["disk", "/"] "disk-root" 6000, + Run $ Com "monitors" ["disk", "/home"] "disk-home" 6000, + Run $ PipeReader "/tmp/pipe-volume" "volume", + Run $ PipeReader "/tmp/pipe-now-playing" "now-playing" + ] + } + +main :: IO () +main = xmobar config diff --git a/xmobar-top.hs b/xmobar-top.hs new file mode 100644 index 0000000..4be84e5 --- /dev/null +++ b/xmobar-top.hs @@ -0,0 +1,24 @@ +import Xmobar + +config :: Config +config = + defaultConfig + { font = "Terminus 8", + textOffset = 0, + bgColor = "#121212", + fgColor = "#cccccc", + position = Top, + template = " %XMonadLog% }{ \57958 %cpu% | \61381 %memory% | %load% | %battery% | %date% ", + commands = + [ Run XMonadLog, + Run $ PipeReader "/tmp/pipe-volume" "volume", + Run $ Com "monitors" ["battery"] "battery" 600, + Run $ Com "monitors" ["cpu"] "cpu" 50, + Run $ Com "monitors" ["memory"] "memory" 50, + Run $ Com "monitors" ["load"] "load" 100, + Run $ Date "%m/%d/%Y %H:%M:%S" "date" 10 + ] + } + +main :: IO () +main = xmobar config diff --git a/xmonad-frosty.cabal b/xmonad-frosty.cabal new file mode 100644 index 0000000..5a3b5e9 --- /dev/null +++ b/xmonad-frosty.cabal @@ -0,0 +1,43 @@ +cabal-version: 3.0 +name: xmonad-frosty +version: 0.1.0.0 +build-type: Simple + +executable xmonad + main-is: xmonad.hs + ghc-options: -Wall -rtsopts -threaded -with-rtsopts=-N + build-depends: + , base + , containers + , X11 + , xmonad >=0.18 + , xmonad-contrib >=0.18 + + default-language: GHC2021 + default-extensions: ImportQualifiedPost + +executable xmobar-top + main-is: xmobar-top.hs + ghc-options: + -O2 -Wall -Wcompat -Wincomplete-record-updates + -Wredundant-constraints -rtsopts -threaded -with-rtsopts=-N + + build-depends: + , base + , xmobar >=0.48 + + default-language: GHC2021 + default-extensions: ImportQualifiedPost + +executable xmobar-bottom + main-is: xmobar-bottom.hs + ghc-options: + -O2 -Wall -Wcompat -Wincomplete-record-updates + -Wredundant-constraints -rtsopts -threaded -with-rtsopts=-N + + build-depends: + , base + , xmobar >=0.48 + + default-language: GHC2021 + default-extensions: ImportQualifiedPost diff --git a/xmonad.hs b/xmonad.hs new file mode 100644 index 0000000..0523a87 --- /dev/null +++ b/xmonad.hs @@ -0,0 +1,271 @@ +{-# OPTIONS_GHC -Wno-missing-signatures #-} + +import Data.Map qualified as M +import Data.Monoid +import Graphics.X11.ExtraTypes.XF86 +import System.Exit +import Text.Printf +import XMonad +import XMonad.Actions.CycleWS +import XMonad.Actions.Submap +import XMonad.Actions.ToggleFullFloat +import XMonad.Hooks.DynamicLog +import XMonad.Hooks.EwmhDesktops +import XMonad.Hooks.InsertPosition +import XMonad.Hooks.ManageDocks (ToggleStruts (..), avoidStruts, manageDocks) +import XMonad.Hooks.Place +import XMonad.Hooks.StatusBar +import XMonad.Hooks.WindowSwallowing +import XMonad.Layout.Grid +import XMonad.Layout.NoBorders +import XMonad.Layout.Renamed (named) +import XMonad.Layout.Spacing +import XMonad.StackSet qualified as W +import XMonad.Util.NamedScratchpad + +myTerminal, myEditor :: String +myTerminal = "st" +myEditor = "nvim" + +myWorkspaces :: [String] +myWorkspaces = ["1:term", "2:www", "3:mus", "4:chat", "5:file", "6:dev", "7:vol", "8:sys", "9"] + +myBorderWidth :: Dimension +myBorderWidth = 1 + +myNormalBorderColor, myFocusedBorderColor :: String +myNormalBorderColor = "#222222" +myFocusedBorderColor = "#80b7ff" + +floatClasses, swallowClasses :: [String] +floatClasses = ["Arandr", "Nsxiv"] +swallowClasses = ["St", "XTerm"] + +myKeys :: XConfig Layout -> M.Map (KeyMask, KeySym) (X ()) +myKeys (XConfig {XMonad.modMask = modMask, XMonad.workspaces = workspaces}) = + M.fromList $ + [ -- Common programs + ((modMask, xK_Return), spawn myTerminal), + ((modMask, xK_p), spawnDmenu "dmenu_run"), + ((modMask, xK_w), spawn "firefox"), + ((modMask .|. controlMask, xK_q), spawn "qutebrowser"), + ((modMask, xK_e), spawnTerminal myEditor), + ((modMask, xK_f), spawnTerminal "lf"), + ((modMask, xK_t), spawnTerminal "ncmpcpp"), + ((modMask .|. controlMask, xK_e), spawnTerminal "ncspot"), + ((modMask, xK_v), spawnTerminal "pulsemixer"), + ((modMask .|. controlMask, xK_y), spawn "pavucontrol"), + ((modMask .|. controlMask, xK_semicolon), spawn "simplescreenrecorder"), + ((modMask .|. controlMask, xK_apostrophe), spawn "obs"), + ((modMask .|. controlMask, xK_o), spawnTerminal "cava"), + ((modMask .|. controlMask, xK_d), spawn "arandr"), + ((modMask .|. controlMask, xK_v), spawn "screenlayouts-open"), + ((modMask .|. controlMask, xK_w), spawn "wallpapers-open"), + ((modMask .|. controlMask, xK_bracketright), spawn "find ~/pictures/screenshots -type f | sort -r | nsxiv -ti"), + -- Screenshotting + ((0, xK_Print), spawn "epicshot -cs select"), + ((controlMask, xK_Print), spawn "epicshot -cs full"), + ((modMask, xK_Print), spawn "epicshot -so select"), + ((modMask .|. controlMask, xK_r), spawn "epicshot -cs select"), + ((modMask .|. controlMask, xK_t), spawn "epicshot -cs full"), + ((modMask .|. controlMask, xK_g), spawn "epicshot -so select"), + -- Faux function row + ((modMask .|. controlMask, xK_F5), spawn "mpc prev"), + ((modMask .|. controlMask, xK_F6), spawn "mpc next"), + ((modMask .|. controlMask, xK_F7), spawn "mpc toggle"), + ((modMask .|. controlMask, xK_F8), spawn "mpc stop"), + ((modMask .|. controlMask, xK_F9), spawn "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle && pipe_volume"), + ((modMask .|. controlMask, xK_F10), spawn "wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%- && pipe_volume"), + ((modMask .|. controlMask, xK_F11), spawn "wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+ && pipe_volume"), + ((modMask .|. controlMask, xK_F12), spawn "run-i3lock"), + -- Special keys + ((0, xF86XK_Explorer), spawnTerminal "nnn"), + ((0, xF86XK_Search), spawnDmenu "dmenu_run"), + ((0, xF86XK_Calculator), spawnTerminal "bc -i"), + ((0, xF86XK_Tools), spawnTerminal "ncmpcpp"), + ((0, xF86XK_AudioPrev), spawn "mpc prev"), + ((0, xF86XK_AudioNext), spawn "mpc next"), + ((0, xF86XK_AudioPlay), spawn "mpc toggle"), + ((0, xF86XK_AudioStop), spawn "mpc stop"), + ((0, xF86XK_AudioMute), spawn "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle && pipe_volume"), + ((0, xF86XK_AudioLowerVolume), spawn "wpctl set-mute @DEFAULT_AUDIO_SINK@ 5%- && pipe_volume"), + ((0, xF86XK_AudioRaiseVolume), spawn "wpctl set-mute @DEFAULT_AUDIO_SINK@ 5%+ && pipe_volume"), + -- Layout switching + ( (modMask, xK_a), + submap . M.fromList $ + [ ((modMask, xK_t), sendMessage $ JumpToLayout "Tall"), + ((modMask, xK_y), sendMessage $ JumpToLayout "Wide"), + ((modMask, xK_g), sendMessage $ JumpToLayout "Grid"), + ((modMask, xK_f), sendMessage $ JumpToLayout "Full"), + ((modMask, xK_s), sendMessage $ JumpToLayout "Spiral"), + ((modMask, xK_a), sendMessage NextLayout) + ] + ), + ((modMask, xK_b), sendMessage ToggleStruts), + -- Basic window management + ((modMask, xK_j), windows W.focusDown), + ((modMask, xK_k), windows W.focusUp), + ((modMask .|. shiftMask, xK_j), windows W.swapDown), + ((modMask .|. shiftMask, xK_k), windows W.swapUp), + -- Master control + ((modMask, xK_h), sendMessage Shrink), + ((modMask, xK_l), sendMessage Expand), + ((modMask, xK_i), sendMessage $ IncMasterN 1), + ((modMask, xK_d), sendMessage $ IncMasterN $ -1), + ((modMask, xK_s), windows W.focusMaster), + ((modMask .|. shiftMask, xK_s), windows W.swapMaster), + -- Window actions + ((modMask .|. shiftMask, xK_c), kill), + ((modMask .|. shiftMask, xK_f), withFocused toggleFullFloat), + ((modMask .|. shiftMask, xK_space), withFocused toggleFloat), + -- Scratchpads + ((modMask .|. controlMask, xK_Return), namedScratchpadAction myScratchPads "terminal"), + ((modMask .|. controlMask, xK_c), namedScratchpadAction myScratchPads "ncmpcpp"), + -- Session + ((modMask .|. controlMask, xK_l), spawn "xscreensaver-command -lock"), + ((modMask .|. controlMask, xK_s), spawn "xmonad --restart && notify-send 'xmonad' 'Successfully recompiled and restarted.'"), + ((modMask .|. controlMask, xK_Delete), io exitSuccess) + ] + -- Workspace viewing and shifting + ++ [ ((modMask .|. m, k), windows $ f i) + | (k, i) <- zip [xK_1 .. xK_9] workspaces, + (m, f) <- [(0, W.view), (shiftMask, W.shift)] + ] + where + toggleFloat :: Window -> X () + toggleFloat w = do + isFloating <- gets (M.member w . W.floating . windowset) + if isFloating + then windows $ W.sink w + else withFocused float + + spawnTerminal :: String -> X () + spawnTerminal x = do + spawn $ printf "%s -e %s" myTerminal x + + spawnDmenu :: String -> X () + spawnDmenu x = do + spawn $ printf "%s -h %s -fn %s -nb '%s' -nf '%s' -sb '%s' -sf '%s'" x "17" "Terminus-8" "#1d2021" "#ebdbb2" "#fabd2f" "#282828" + +myMouseBindings :: XConfig Layout -> M.Map (KeyMask, Button) (Window -> X ()) +myMouseBindings (XConfig {XMonad.modMask = modMask}) = + M.fromList + [ -- Float and move window + ((modMask, button1), \w -> focus w >> mouseMoveWindow w >> windows W.shiftMaster), + -- Shift window to master + ((modMask, button2), \w -> focus w >> windows W.shiftMaster), + -- Float and resize window + ((modMask, button3), \w -> focus w >> mouseResizeWindow w >> windows W.shiftMaster), + -- Go to previous workspace + ((modMask, button4), const prevWS), + -- Go to next workspace + ((modMask, button5), const nextWS), + -- Shift window to previous workspace + ((modMask .|. shiftMask, button4), \_ -> shiftToPrev >> prevWS), + -- Shift window to next workspace + ((modMask .|. shiftMask, button5), \_ -> shiftToNext >> nextWS) + ] + +myLayoutHook = + lessBorders OnlyScreenFloat $ + spacing 8 $ + avoidStruts $ + tall ||| wide ||| grid ||| full + where + tall = + named "Tall" $ + Tall 1 (3 / 100) (1 / 2) + wide = + named "Wide" $ + Mirror tall + grid = + named + "Grid" + Grid + full = + named + "Full" + Full + +-- SCRATCHPADS --------------------------------------------------------- + +myScratchPads :: [NamedScratchpad] +myScratchPads = + [ constructScratchpad "terminal" "scTerminal" Nothing, + constructScratchpad "ncmpcpp" "scNcmpcpp" (Just "ncmpcpp") + ] + where + constructScratchpad :: String -> String -> Maybe String -> NamedScratchpad + constructScratchpad name cls maybeExec = + NS + name + ( case maybeExec of + Just exec -> printf "%s -c %s -e %s" myTerminal cls exec + Nothing -> printf "%s -c %s" myTerminal cls + ) + (className =? cls) + (customFloating $ W.RationalRect (3 / 5) (4 / 6) (1 / 5) (1 / 6)) + +-- HOOKS --------------------------------------------------------------- + +myManageHook :: ManageHook +myManageHook = + composeAll + [ placeHook simpleSmart, + manageDocks, + namedScratchpadManageHook myScratchPads, + insertPosition End Newer, + composeAll [className =? c --> doFloat | c <- floatClasses] + ] + +myEventHook :: Event -> X All +myEventHook = + swallowEventHook (foldr1 (<||>) $ map (className =?) swallowClasses) (return True) + +myStartupHook :: X () +myStartupHook = do + spawn "initialize_pipes" + +-- XMOBAR -------------------------------------------------------------- + +myPP :: PP +myPP = + def + { ppSep = sep " | ", + ppCurrent = current . wrap "" "*", + ppHidden = noScratchPad, + ppHiddenNoWindows = const "" + } + where + noScratchPad :: String -> String + noScratchPad ws = if ws == "NSP" then "" else ws + + sep, current :: String -> String + sep = xmobarColor "#777777" "" + current = xmobarColor "#6eadff" "" + +-- MAIN ---------------------------------------------------------------- + +main :: IO () +main = + xmonad + . withSB (statusBarProp "xmobar-top" $ pure myPP) + . withSB (statusBarProp "xmobar-bottom" $ pure myPP) + . toggleFullFloatEwmhFullscreen + . ewmhFullscreen + . ewmh + $ def + { borderWidth = myBorderWidth, + normalBorderColor = myNormalBorderColor, + focusedBorderColor = myFocusedBorderColor, + layoutHook = myLayoutHook, + workspaces = myWorkspaces, + manageHook = myManageHook, + handleEventHook = myEventHook, + startupHook = myStartupHook, + mouseBindings = myMouseBindings, + keys = myKeys, + focusFollowsMouse = True, + clickJustFocuses = False, + modMask = mod4Mask + }