all repos — xmonad-config @ 06dc0307fb49ff82b51de1f631304338a2a2b344

personal xmonad config

xmonad.hs (view raw)

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