all repos — xmonad-config @ d3e64416f57c1f0e0a3451303dbd708e3889305d

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        , ("M-S-e", spawn "emacsclient -c")
327    -- Kill windows
328        , ("M-S-c", kill1)    -- Kill the currently focused client
329        , ("M-S-a", killAll)  -- Kill all windows on current workspace
330
331    -- Workspaces
332        , ("M-.", nextScreen) -- Switch focus to next monitor
333        , ("M-,", prevScreen) -- Switch focus to prev monitor
334        -- Shifts focused window to next ws
335        , ("M-S-<KP_Add>", shiftTo Next nonNSP >> moveTo Next nonNSP)
336        -- Shifts focused window to prev ws
337        , ("M-S-<KP_Subtract>", shiftTo Prev nonNSP >> moveTo Prev nonNSP)
338
339    -- Floating windows
340        , ("M-f", sendMessage (T.Toggle "floats")) -- Toggles my 'floats' layout
341        , ("M-t", withFocused $ windows . W.sink)  -- Push floating window back to tile
342        , ("M-S-t", sinkAll)                       -- Push ALL floating windows to tile
343
344    -- Increase/decrease spacing (gaps)
345        , ("C-M1-j", decWindowSpacing 4) -- Decrease window spacing
346        , ("C-M1-k", incWindowSpacing 4) -- Increase window spacing
347        , ("C-M1-h", decScreenSpacing 4) -- Decrease screen spacing
348        , ("C-M1-l", incScreenSpacing 4) -- Increase screen spacing
349
350    -- Grid Select (MOD-g followed by a key)
351        , ("M-g g", spawnSelected' myAppGrid)                 -- grid select favorite apps
352        , ("M-g t", goToSelected $ myGridConfig myColorizer)  -- goto selected window
353        , ("M-g b", bringSelected $ myGridConfig myColorizer) -- bring selected window
354
355    -- Windows navigation
356        , ("M-m", windows W.focusMaster)  -- Move focus to the master window
357        , ("M-j", BW.focusDown)           -- Move focus to the next window
358        , ("M1-<Tab>", BW.focusDown)      -- legacy keybinding
359        , ("M-k", BW.focusUp)             -- Move focus to the prev window
360        , ("M-S-m", windows W.swapMaster) -- Swap the focused window and the master window
361        , ("M-S-j", windows W.swapDown)   -- Swap focused window with next window
362        , ("M-S-k", windows W.swapUp)     -- Swap focused window with prev window
363        , ("M-<Backspace>", promote)      -- Moves focused window to master, others maintain order
364        , ("M-S-<Tab>", rotSlavesDown)    -- Rotate all windows except master and keep focus in place
365        , ("M-C-<Tab>", rotAllDown)       -- Rotate all the windows in the current stack
366
367    -- Layouts
368        , ("M-<Tab>", sendMessage NextLayout)           -- Switch to next layout
369        , ("M-b", sendMessage (MT.Toggle NBFULL))
370        , ("M-<Space>", sendMessage (MT.Toggle NBFULL) >> sendMessage ToggleStruts) -- Toggles noborder/full
371
372    -- Increase/decrease windows in the master pane or the stack
373        , ("M-S-<Up>", sendMessage (IncMasterN 1))      -- Increase # of clients master pane
374        , ("M-S-<Down>", sendMessage (IncMasterN (-1))) -- Decrease # of clients master pane
375        , ("M-C-<Up>", increaseLimit)                   -- Increase # of windows
376        , ("M-C-<Down>", decreaseLimit)                 -- Decrease # of windows
377
378    -- Window resizing
379        , ("M-h", sendMessage Shrink)                   -- Shrink horiz window width
380        , ("M-l", sendMessage Expand)                   -- Expand horiz window width
381        , ("M-M1-j", sendMessage MirrorShrink)          -- Shrink vert window width
382        , ("M-M1-k", sendMessage MirrorExpand)          -- Expand vert window width
383
384    -- Sublayouts
385    -- This is used to push windows to tabbed sublayouts, or pull them out of it.
386        , ("M-C-h", sendMessage $ pullGroup L)
387        , ("M-C-l", sendMessage $ pullGroup R)
388        , ("M-C-k", sendMessage $ pullGroup U)
389        , ("M-C-j", sendMessage $ pullGroup D)
390        , ("M-C-m", withFocused (sendMessage . MergeAll))
391        , ("M-C-u", withFocused (sendMessage . UnMerge))
392        , ("M-C-/", withFocused (sendMessage . UnMergeAll))
393        , ("M-C-<Space>", toSubl NextLayout)
394        , ("M-C-.", onGroup W.focusUp')   -- Switch focus to next tab
395        , ("M-C-,", onGroup W.focusDown') -- Switch focus to prev tab
396
397    -- Scratchpads
398    -- Toggle show/hide these programs.  They run on a hidden workspace.
399    -- When you toggle them to show, it brings them to your current workspace.
400    -- Toggle them to hide and it sends them back to hidden workspace (NSP).
401        , ("M-s t", namedScratchpadAction myScratchPads "terminal")
402        , ("M-s m", namedScratchpadAction myScratchPads "mocp")
403        , ("M-s c", namedScratchpadAction myScratchPads "calculator")
404        , ("M-s v", namedScratchpadAction myScratchPads "mpvfloat" )
405
406    -- Set wallpaper with 'feh'. Type 'SUPER+F1' to launch sxiv in the wallpapers directory.
407    -- Then in sxiv, type 'C-x w' to set the wallpaper that you choose.
408        , ("M-<F1>", spawn "sxiv -r -q -t -o ~/Pictures/wallpapers/*")
409        , ("M-<F2>", spawn "/bin/ls ~/Pictures/wallpapers | shuf -n 1 \
410            \| xargs xwallpaper --stretch")
411
412    -- pana e nimi sewi
413         , ("M-<F7>", spawn "nimi_sewi")
414
415    -- Controls for mocp music player (SUPER-u followed by a key)
416        , ("M-u p", spawn (myMocp ++ " --play"))
417        , ("M-u l", spawn (myMocp ++ " --next"))
418        , ("M-u h", spawn (myMocp ++ " --previous"))
419        , ("M-u <Space>", spawn (myMocp ++ " --toggle-pause"))
420
421    -- Multimedia Keys
422        , ("<XF86AudioPlay>", spawn (myMocp ++ " --toggle-pause"))
423        , ("<XF86AudioPrev>", spawn (myMocp ++ " --previous"))
424        , ("<XF86AudioNext>", spawn (myMocp ++ " --next"))
425        , ("<XF86AudioMute>", spawn (myMocp ++ " -v 0"))
426        , ("<XF86AudioLowerVolume>", spawn (myMocp ++ " -v -1"))
427        , ("<XF86AudioRaiseVolume>", spawn (myMocp ++ " -v +1"))
428        , ("<XF86HomePage>", spawn "brave https://aaoth.xyz")
429        , ("<XF86Search>", spawn "dm-websearch")
430        , ("<XF86Mail>", runOrRaise "geary" (resource =? "geary"))
431        , ("<XF86Calculator>", namedScratchpadAction myScratchPads "calculator")
432        , ("<XF86Sleep>", spawn "dm-logout")
433        ]
434    -- the following lines are needed for named scratchpads.
435        where nonNSP          = WSIs (return (\ws -> W.tag ws /= "NSP"))
436              nonEmptyNonNSP  = WSIs (return (\ws -> isJust (W.stack ws)
437                                      && W.tag ws /= "NSP"))
438
439
440main :: IO ()
441main = do
442    xmproc <- spawnPipe "xmobar ~/.xmonad/xmobar/xmobarrc"
443    -- the xmonad, ya know...what the wm is named after!
444    xmonad $ ewmh def
445        { manageHook         = myManageHook <+> manageDocks
446        , handleEventHook    = docksEventHook
447        , modMask            = myModMask
448        , terminal           = myTerminal
449        , startupHook        = myStartupHook
450        , layoutHook         = showWName' myShowWNameTheme $ myLayoutHook
451        , workspaces         = myWorkspaces
452        , borderWidth        = myBorderWidth
453        , normalBorderColor  = myNormColor
454        , focusedBorderColor = myFocusColor
455        , logHook = dynamicLogWithPP
456                    $ namedScratchpadFilterOutWorkspacePP
457                    $ xmobarPP
458              { ppOutput  = hPutStrLn xmproc
459              , ppCurrent = xmobarColor (myColor "green-bright") ""
460                            . wrap "<fn=3>" "</fn>" -- toki pona
461                            . wrap "[" "]"
462                            -- . wrap " " " " -- normal
463              , ppVisible = xmobarColor (myColor "green-bright") "" . clickable
464              , ppHidden  = xmobarColor (myColor "blue-bright") ""
465                            . wrap "" "'"
466                            . clickable
467              , ppHiddenNoWindows = xmobarColor (myColor "gray2") "" . clickable
468              --, ppHiddenNoWindows = myHiddenNoWindows
469              , ppTitle   = xmobarColor (myColor "gray4") "" . shorten 60
470              , ppSep     = xmobarColor (myColor "gray3") "" " | "
471              , ppWsSep   = "  "
472              , ppUrgent  = xmobarColor (myColor "yellow") "" . wrap "!" "!"
473              , ppExtras  = [myWindowCountLogger]
474              , ppOrder   = \(ws:l:t:ex) -> [ws,l]++ex++[t]
475              }
476        } `additionalKeysP` myKeys
477