all repos — xmonad-config @ 8f6cff418aa2130e460a6625f639fc1a5e85b328

personal xmonad config

xmonad.hs (view raw)

  1{-# OPTIONS_HADDOCK prune #-}
  2----------------------------------------------------------------------
  3-- |
  4-- Description  :   la-ninpre xmobar config
  5-- Maintainer   :   la-ninpre
  6--
  7-- personal xmobar config. based heavily on distrotube's config.
  8-- i've added some stuff and toki pona fonts
  9--
 10----------------------------------------------------------------------
 11
 12module Main where
 13
 14import System.Directory
 15import System.IO (hPutStrLn)
 16import System.Exit (exitSuccess)
 17
 18import Data.Char (isSpace, toUpper)
 19import Data.Maybe (fromJust)
 20import Data.Monoid
 21import Data.Maybe (isJust)
 22import Data.Tree
 23import Data.List
 24import qualified Data.Map as M
 25
 26import XMonad
 27import qualified XMonad.StackSet as W
 28
 29import XMonad.Actions.CopyWindow (kill1)
 30import XMonad.Actions.CycleWS ( Direction1D(..)
 31                              , moveTo
 32                              , shiftTo
 33                              , WSType(..)
 34                              , nextScreen
 35                              , prevScreen
 36                              )
 37import XMonad.Actions.GridSelect
 38import XMonad.Actions.MouseResize
 39import XMonad.Actions.Promote
 40import XMonad.Actions.RotSlaves (rotSlavesDown, rotAllDown)
 41import XMonad.Actions.WindowGo (runOrRaise)
 42import XMonad.Actions.WithAll (sinkAll, killAll)
 43import qualified XMonad.Actions.Search as S
 44
 45import XMonad.Hooks.DynamicLog 
 46import XMonad.Hooks.EwmhDesktops
 47import XMonad.Hooks.ManageDocks ( avoidStruts
 48                                , docksEventHook
 49                                , manageDocks
 50                                , ToggleStruts(..))
 51import XMonad.Hooks.ManageHelpers (isFullscreen, doFullFloat)
 52import XMonad.Hooks.ServerMode
 53import XMonad.Hooks.SetWMName
 54import XMonad.Hooks.WorkspaceHistory
 55
 56import XMonad.Layout.SimplestFloat
 57import XMonad.Layout.ResizableTile
 58import XMonad.Layout.Tabbed
 59import XMonad.Layout.ThreeColumns
 60import XMonad.Layout.Accordion
 61import XMonad.Layout.LayoutModifier
 62import XMonad.Layout.LimitWindows (limitWindows, increaseLimit, decreaseLimit)
 63import XMonad.Layout.Magnifier
 64import XMonad.Layout.MultiToggle (mkToggle, single, EOT(EOT), (??))
 65import XMonad.Layout.MultiToggle.Instances (StdTransformers( NBFULL
 66                                                           , MIRROR
 67                                                           , NOBORDERS
 68                                                           ))
 69import XMonad.Layout.NoBorders
 70import XMonad.Layout.Renamed
 71import XMonad.Layout.ShowWName
 72import XMonad.Layout.Simplest
 73import XMonad.Layout.Spacing
 74import XMonad.Layout.SubLayouts
 75import XMonad.Layout.WindowNavigation
 76import qualified XMonad.Layout.BoringWindows as BW
 77import XMonad.Layout.WindowArranger (windowArrange, WindowArrangerMsg(..))
 78import qualified XMonad.Layout.ToggleLayouts as T ( toggleLayouts
 79                                                  , ToggleLayout(Toggle)
 80                                                  )
 81import qualified XMonad.Layout.MultiToggle as MT (Toggle(..))
 82
 83import XMonad.Util.Dmenu
 84import XMonad.Util.Loggers
 85import XMonad.Util.EZConfig (additionalKeysP)
 86import XMonad.Util.NamedScratchpad
 87import XMonad.Util.Run (runProcessWithInput, safeSpawn, spawnPipe)
 88import XMonad.Util.SpawnOnce
 89import XMonad.Util.WorkspaceCompare
 90
 91import LaNinpreConfig
 92
 93-- * misc functions
 94--
 95-- | hides workspaces that have no windows
 96myHiddenNoWindows :: WorkspaceId -> String
 97myHiddenNoWindows = const ""
 98
 99mySuperscript :: Int -> String
100mySuperscript n = map ss $ show n
101                where ss c | c == '0' = '⁰'
102                           | c == '1' = '¹'
103                           | c == '2' = '²'
104                           | c == '3' = '³'
105                           | c == '4' = '⁴'
106                           | c == '5' = '⁵'
107                           | c == '6' = '⁶'
108                           | c == '7' = '⁷'
109                           | c == '8' = '⁸'
110                           | c == '9' = '⁹'
111                           | otherwise = c
112
113
114-- | window count logger
115-- 
116--   gets number of windows on current workspace
117myWindowCountLogger :: Logger
118myWindowCountLogger = gets $ Just . show . length . W.integrate' . W.stack
119                           . W.workspace . W.current . windowset
120
121myTestLogger :: Logger
122myTestLogger = gets $ Just . xmobarColor (myColor "yellow") "" . intercalate "  "
123                    . \s -> ( let w = windowset $ s
124                                  ws = map W.workspace (W.current w : W.visible w) ++ W.hidden w
125                                  t = map (wrap "<fn=3>" "</fn>") . map W.tag $ ws
126                                  l = map length 
127                                    . map W.integrate'
128                                    . map W.stack $ ws
129                              in zipWith (++) t $ map mySuperscript l
130                            )
131
132
133-- * grid select
134--
135-- $gridSelect
136--
137-- this section provides theming of @GridSelect@ stuff.
138--
139-- here, @GridSelect@ is used for following things:
140--
141--      * spawning some frequently used programs
142--
143--      * moving to desired window
144--
145--      * bringing the desired window to the current workspace
146
147-- | custom colorizer that colors windows based on their class
148myColorizer :: Window -> Bool -> X (String, String)
149myColorizer = colorRangeFromClassName
150                  (0x00,0x00,0x00) -- lowest inactive bg
151                  (0xbd,0x9c,0xf9) -- highest inactive bg
152                  (0xc7,0x92,0xea) -- active bg
153                  (0xc0,0xa7,0x9a) -- inactive fg
154                  (0x28,0x2c,0x34) -- active fg
155
156-- | gridSelect config
157myGridConfig :: p -> GSConfig Window
158myGridConfig colorizer = (buildDefaultGSConfig myColorizer)
159    { gs_cellheight   = 40
160    , gs_cellwidth    = 200
161    , gs_cellpadding  = 6
162    , gs_originFractX = 0.5
163    , gs_originFractY = 0.5
164    , gs_font         = (myFonts !! 0)
165    }
166
167-- | spawn selected programs with grid select
168spawnSelected' :: [(String, String)] -> X ()
169spawnSelected' lst = gridselect conf lst >>= flip whenJust spawn
170    where conf = def
171                   { gs_cellheight   = 40
172                   , gs_cellwidth    = 200
173                   , gs_cellpadding  = 6
174                   , gs_originFractX = 0.5
175                   , gs_originFractY = 0.5
176                   , gs_font         = (myFonts !! 0)
177                   }
178
179-- * layouts
180--
181-- ** spacing raw helper functions
182--
183-- $spacingHelpers
184--
185-- theese are making calls to spacingRaw simpler to write
186
187-- | for many windows
188mySpacing :: Integer -> l a -> XMonad.Layout.LayoutModifier.ModifiedLayout Spacing l a
189mySpacing i = spacingRaw False (Border i i i i) True (Border i i i i) True
190
191-- | for fewer than two windows
192mySpacing' :: Integer -> l a -> XMonad.Layout.LayoutModifier.ModifiedLayout Spacing l a
193mySpacing' i = spacingRaw True (Border i i i i) True (Border i i i i) True
194
195-- ** actually layouts
196--
197-- $layouts
198--
199-- currently there are:
200--
201--      *   tall
202--
203--      *   floats
204--
205--      *   threeCol
206
207tall     = renamed [Replace "tall"]
208           $ smartBorders
209           $ addTabs shrinkText myTabTheme
210           $ subLayout [] (smartBorders Simplest ||| Accordion)
211           $ limitWindows 12
212           $ mySpacing 4
213           $ ResizableTall 1 (5/100) (1/2) []
214
215floats   = renamed [Replace "floats"]
216           $ smartBorders
217           $ limitWindows 20
218           $ simplestFloat
219
220threeCol = renamed [Replace "threeCol"]
221           $ smartBorders
222           $ addTabs shrinkText myTabTheme
223           $ subLayout [] (smartBorders Simplest ||| Accordion)
224           $ limitWindows 7
225           $ mySpacing 4
226           $ ThreeColMid 1 (3/100) (1/2)
227
228-- | setting colors for tabs layout and tabs sublayout.
229myTabTheme = def
230               { fontName            = (myFonts !! 0)
231               , activeColor         = myColor "gray4"
232               , inactiveColor       = myColor "gray0"
233               , activeBorderColor   = myColor "gray4"
234               , inactiveBorderColor = myColor "gray0"
235               , activeTextColor     = myColor "bg"
236               , inactiveTextColor   = myColor "fg"
237               }
238
239-- ** layout hook
240
241-- $layoutHook
242--
243-- putting it all together with some stuff
244myLayoutHook = avoidStruts
245               $ mouseResize
246               $ BW.boringWindows
247               $ windowNavigation
248               $ windowArrange
249               $ T.toggleLayouts floats
250               $ mkToggle (NBFULL ?? NOBORDERS ?? EOT) myDefaultLayout
251               where
252               myDefaultLayout = withBorder myBorderWidth tall
253                                 ||| withBorder myBorderWidth threeCol
254
255-- * show wm name hook
256
257-- | theme for showWName which prints current workspace
258--   when you change workspaces.
259myShowWNameTheme :: SWNConfig
260myShowWNameTheme = def
261    { swn_font    = (myFonts !! 1)
262    , swn_fade    = 0.7
263    , swn_bgcolor = myColor "bg"
264    , swn_color   = myColor "fg"
265    }
266
267-- * workspaces
268--
269-- $workspaces
270--
271-- here are some helper functions to deal with workspaces.
272--
273-- actual workspace list is in "LaNinpreConfig".
274
275-- | workspace indices to use with hotkeys
276myWorkspaceIndices = M.fromList $ zipWith (,) myWorkspaces [1..]
277
278-- ** clickable workspace wrapper
279--
280-- $clickable
281--
282-- normal variant
283--
284-- > clickable ws = "<action=xdotool key super+"++show i++">"++ws++"</action>"
285-- >     where i = fromJust $ M.lookup ws myWorkspaceIndices
286
287-- | provides option to click workspaces to switch to them.
288--   this is handled by @UnsafeStdinReader@ in xmobar config.
289clickable ws = "<fn=3><action=xdotool key super+"++show i++">"++ws++"</action></fn>"
290    where i = fromJust $ M.lookup ws myWorkspaceIndices
291
292-- * keybindings
293
294-- | keybindings list
295--
296--   there's no way to document it using haddock, i guess...
297myKeys :: [(String, X ())]
298myKeys =
299        [ ("M-C-r", spawn "xmonad --recompile") -- Recompiles xmonad
300        , ("M-S-r", spawn "xmonad --restart")   -- Restarts xmonad
301        , ("M-S-q", io exitSuccess)             -- Quits xmonad
302
303    -- Run Prompt
304        , ("M-r", spawn "dmenu_run -i -p \"Run: \"") -- Dmenu
305
306    -- Other Dmenu Prompts
307    -- In Xmonad and many tiling window managers, M-p is the default keybinding to
308    -- launch dmenu_run, so I've decided to use M-p plus KEY for these dmenu scripts.
309        , ("M-p p", spawn "passmenu")     -- passmenu
310        , ("M-p c", spawn "dm-colpick")   -- pick color from our scheme
311        , ("M-p e", spawn "dm-confedit")  -- edit config files
312        , ("M-p i", spawn "dm-maim")      -- screenshots (images)
313        , ("M-p k", spawn "dm-kill")      -- kill processes
314        , ("M-p m", spawn "dm-man")       -- manpages
315        , ("M-p q", spawn "dm-logout")    -- logout menu
316        , ("M-p s", spawn "dm-websearch") -- search various search engines
317        , ("M-p h", spawn "dm-hub")       -- hub of all scripts to choose one
318
319    -- Useful programs to have a keybinding for launch
320        , ("M-<Return>", spawn (myTerminal))
321        , ("M-e", spawn (myFileMgr))
322        , ("M-w", spawn (myBrowser))
323        , ("M-i", spawn (myTerminal
324                         ++ " --class alacritty,amfora -e "
325                         ++ myGeminiClient))
326    -- Kill windows
327        , ("M-S-c", kill1)    -- Kill the currently focused client
328        , ("M-S-a", killAll)  -- Kill all windows on current workspace
329
330    -- Workspaces
331        , ("M-.", nextScreen) -- Switch focus to next monitor
332        , ("M-,", prevScreen) -- Switch focus to prev monitor
333        -- Shifts focused window to next ws
334        , ("M-S-<KP_Add>", shiftTo Next nonNSP >> moveTo Next nonNSP)
335        -- Shifts focused window to prev ws
336        , ("M-S-<KP_Subtract>", shiftTo Prev nonNSP >> moveTo Prev nonNSP)
337
338    -- Floating windows
339        , ("M-f", sendMessage (T.Toggle "floats")) -- Toggles my 'floats' layout
340        , ("M-t", withFocused $ windows . W.sink)  -- Push floating window back to tile
341        , ("M-S-t", sinkAll)                       -- Push ALL floating windows to tile
342
343    -- Increase/decrease spacing (gaps)
344        , ("C-M1-j", decWindowSpacing 4) -- Decrease window spacing
345        , ("C-M1-k", incWindowSpacing 4) -- Increase window spacing
346        , ("C-M1-h", decScreenSpacing 4) -- Decrease screen spacing
347        , ("C-M1-l", incScreenSpacing 4) -- Increase screen spacing
348
349    -- Grid Select (MOD-g followed by a key)
350        , ("M-g g", spawnSelected' myAppGrid)                 -- grid select favorite apps
351        , ("M-g t", goToSelected $ myGridConfig myColorizer)  -- goto selected window
352        , ("M-g b", bringSelected $ myGridConfig myColorizer) -- bring selected window
353
354    -- Windows navigation
355        , ("M-m", windows W.focusMaster)  -- Move focus to the master window
356        , ("M-j", BW.focusDown)           -- Move focus to the next window
357        , ("M1-<Tab>", BW.focusDown)      -- legacy keybinding
358        , ("M-k", BW.focusUp)             -- Move focus to the prev window
359        , ("M-S-m", windows W.swapMaster) -- Swap the focused window and the master window
360        , ("M-S-j", windows W.swapDown)   -- Swap focused window with next window
361        , ("M-S-k", windows W.swapUp)     -- Swap focused window with prev window
362        , ("M-<Backspace>", promote)      -- Moves focused window to master, others maintain order
363        , ("M-S-<Tab>", rotSlavesDown)    -- Rotate all windows except master and keep focus in place
364        , ("M-C-<Tab>", rotAllDown)       -- Rotate all the windows in the current stack
365
366    -- Layouts
367        , ("M-<Tab>", sendMessage NextLayout)           -- Switch to next layout
368        , ("M-b", sendMessage (MT.Toggle NBFULL))
369        , ("M-<Space>", sendMessage (MT.Toggle NBFULL) >> sendMessage ToggleStruts) -- Toggles noborder/full
370
371    -- Increase/decrease windows in the master pane or the stack
372        , ("M-S-<Up>", sendMessage (IncMasterN 1))      -- Increase # of clients master pane
373        , ("M-S-<Down>", sendMessage (IncMasterN (-1))) -- Decrease # of clients master pane
374        , ("M-C-<Up>", increaseLimit)                   -- Increase # of windows
375        , ("M-C-<Down>", decreaseLimit)                 -- Decrease # of windows
376
377    -- Window resizing
378        , ("M-h", sendMessage Shrink)                   -- Shrink horiz window width
379        , ("M-l", sendMessage Expand)                   -- Expand horiz window width
380        , ("M-M1-j", sendMessage MirrorShrink)          -- Shrink vert window width
381        , ("M-M1-k", sendMessage MirrorExpand)          -- Expand vert window width
382
383    -- Sublayouts
384    -- This is used to push windows to tabbed sublayouts, or pull them out of it.
385        , ("M-C-h", sendMessage $ pullGroup L)
386        , ("M-C-l", sendMessage $ pullGroup R)
387        , ("M-C-k", sendMessage $ pullGroup U)
388        , ("M-C-j", sendMessage $ pullGroup D)
389        , ("M-C-m", withFocused (sendMessage . MergeAll))
390        , ("M-C-u", withFocused (sendMessage . UnMerge))
391        , ("M-C-/", withFocused (sendMessage . UnMergeAll))
392        , ("M-C-<Space>", toSubl NextLayout)
393        , ("M-C-.", onGroup W.focusUp')   -- Switch focus to next tab
394        , ("M-C-,", onGroup W.focusDown') -- Switch focus to prev tab
395
396    -- Scratchpads
397    -- Toggle show/hide these programs.  They run on a hidden workspace.
398    -- When you toggle them to show, it brings them to your current workspace.
399    -- Toggle them to hide and it sends them back to hidden workspace (NSP).
400        , ("M-s t", namedScratchpadAction myScratchPads "terminal")
401        , ("M-s m", namedScratchpadAction myScratchPads "mocp")
402        , ("M-s c", namedScratchpadAction myScratchPads "calculator")
403        , ("M-s v", namedScratchpadAction myScratchPads "mpvfloat" )
404
405    -- Set wallpaper with 'feh'. Type 'SUPER+F1' to launch sxiv in the wallpapers directory.
406    -- Then in sxiv, type 'C-x w' to set the wallpaper that you choose.
407        , ("M-<F1>", spawn "sxiv -r -q -t -o ~/Pictures/wallpapers/*")
408        , ("M-<F2>", spawn "/bin/ls ~/Pictures/wallpapers | shuf -n 1 \
409            \| xargs xwallpaper --stretch")
410
411    -- pana e nimi sewi
412         , ("M-<F7>", spawn "nimi_sewi")
413
414    -- Controls for mocp music player (SUPER-u followed by a key)
415        , ("M-u p", spawn (myMocp ++ " --play"))
416        , ("M-u l", spawn (myMocp ++ " --next"))
417        , ("M-u h", spawn (myMocp ++ " --previous"))
418        , ("M-u <Space>", spawn (myMocp ++ " --toggle-pause"))
419
420    -- Multimedia Keys
421        , ("<XF86AudioPlay>", spawn (myMocp ++ " --toggle-pause"))
422        , ("<XF86AudioPrev>", spawn (myMocp ++ " --previous"))
423        , ("<XF86AudioNext>", spawn (myMocp ++ " --next"))
424        , ("<XF86AudioMute>", spawn (myMocp ++ " -v 0"))
425        , ("<XF86AudioLowerVolume>", spawn (myMocp ++ " -v -1"))
426        , ("<XF86AudioRaiseVolume>", spawn (myMocp ++ " -v +1"))
427        , ("<XF86HomePage>", spawn "brave https://aaoth.xyz")
428        , ("<XF86Search>", spawn "dm-websearch")
429        , ("<XF86Mail>", runOrRaise "geary" (resource =? "geary"))
430        , ("<XF86Calculator>", namedScratchpadAction myScratchPads "calculator")
431        , ("<XF86Sleep>", spawn "dm-logout")
432        ]
433    -- the following lines are needed for named scratchpads.
434        where nonNSP          = WSIs (return (\ws -> W.tag ws /= "NSP"))
435              nonEmptyNonNSP  = WSIs (return (\ws -> isJust (W.stack ws)
436                                      && W.tag ws /= "NSP"))
437
438
439main :: IO ()
440main = do
441    xmproc <- spawnPipe "xmobar ~/.xmonad/xmobar/xmobarrc"
442    -- the xmonad, ya know...what the wm is named after!
443    xmonad $ ewmh def
444        { manageHook         = myManageHook <+> manageDocks
445        , handleEventHook    = docksEventHook
446        , modMask            = myModMask
447        , terminal           = myTerminal
448        , startupHook        = myStartupHook
449        , layoutHook         = showWName' myShowWNameTheme $ myLayoutHook
450        , workspaces         = myWorkspaces
451        , borderWidth        = myBorderWidth
452        , normalBorderColor  = myNormColor
453        , focusedBorderColor = myFocusColor
454        , logHook = dynamicLogWithPP
455                    $ namedScratchpadFilterOutWorkspacePP
456                    $ xmobarPP
457              { ppOutput  = hPutStrLn xmproc
458              , ppCurrent = xmobarColor (myColor "green-bright") ""
459                            . wrap "<fn=3>" "</fn>" -- toki pona
460                            . wrap "[" "]"
461                            -- . wrap " " " " -- normal
462              , ppVisible = xmobarColor (myColor "green-bright") "" . clickable
463              , ppHidden  = xmobarColor (myColor "blue-bright") ""
464                            . wrap "" "'"
465                            . clickable
466              , ppHiddenNoWindows = xmobarColor (myColor "gray2") "" . clickable
467              --, ppHiddenNoWindows = myHiddenNoWindows
468              , ppTitle   = xmobarColor (myColor "gray4") "" . shorten 60
469              , ppSep     = xmobarColor (myColor "gray3") "" " | "
470              , ppWsSep   = "  "
471              , ppUrgent  = xmobarColor (myColor "yellow") "" . wrap "!" "!"
472              , ppExtras  = [myWindowCountLogger]
473              , ppOrder   = \(ws:l:t:ex) -> [ws,l]++ex++[t]
474              }
475        } `additionalKeysP` myKeys
476