TreeSelect, GridSelect, unfocused windows opacity, workspace name on switch.

This commit is contained in:
Derek Taylor 2020-06-24 20:00:02 -05:00
parent 629e829a16
commit f6a97af56d
1 changed files with 434 additions and 271 deletions

View File

@ -1,18 +1,25 @@
-- The xmonad configuration of Derek Taylor (DistroTube)
-- Xmonad is a dynamically tiling X11 window manager that is written and
-- configured in Haskell. Official documentation: https://xmonad.org
-- This is the xmonad configuration of Derek Taylor (DistroTube)
-- My YouTube: http://www.youtube.com/c/DistroTube
-- My GitLab: http://www.gitlab.com/dwt1/
-- For more information on Xmonad, visit: https://xmonad.org
-- This config is massively long. It is purposely bloated with a ton of
-- examples of what you can do with xmonad. It is written more as a
-- study guide rather than a config that you should download and use.
------------------------------------------------------------------------
-- IMPORTS
------------------------------------------------------------------------
-- Base
import XMonad
import System.IO (hPutStrLn)
import System.IO (hPutStr, hPutStrLn)
import System.Exit (exitSuccess)
import qualified XMonad.StackSet as W
-- Actions
import XMonad.Actions.Commands (defaultCommands, screenCommands, workspaceCommands)
import XMonad.Actions.CopyWindow (kill1, killAllOtherCopies)
import XMonad.Actions.CycleWS (moveTo, shiftTo, WSType(..), nextScreen, prevScreen)
import XMonad.Actions.GridSelect
@ -30,15 +37,18 @@ import Data.List
import Data.Monoid
import Data.Maybe (isJust)
import Data.Tree
import qualified Data.Tuple.Extra as TE
import qualified Data.Map as M
-- Hooks
import XMonad.Hooks.DynamicLog (dynamicLogWithPP, wrap, xmobarPP, xmobarColor, shorten, PP(..))
import XMonad.Hooks.EwmhDesktops -- for some fullscreen events, also for xcomposite in obs.
import XMonad.Hooks.FadeInactive
import XMonad.Hooks.ManageDocks (avoidStruts, docksEventHook, manageDocks, ToggleStruts(..))
import XMonad.Hooks.ManageHelpers (isFullscreen, doFullFloat)
import XMonad.Hooks.ServerMode
import XMonad.Hooks.SetWMName
import XMonad.Hooks.WorkspaceHistory
-- Layouts
import XMonad.Layout.GridVariants (Grid(Grid))
@ -56,6 +66,7 @@ import XMonad.Layout.MultiToggle (mkToggle, single, EOT(EOT), (??))
import XMonad.Layout.MultiToggle.Instances (StdTransformers(NBFULL, MIRROR, NOBORDERS))
import XMonad.Layout.NoBorders
import XMonad.Layout.Renamed (renamed, Rename(Replace))
import XMonad.Layout.ShowWName
import XMonad.Layout.Spacing
import XMonad.Layout.WindowArranger (windowArrange, WindowArrangerMsg(..))
import qualified XMonad.Layout.ToggleLayouts as T (toggleLayouts, ToggleLayout(Toggle))
@ -64,6 +75,7 @@ import qualified XMonad.Layout.MultiToggle as MT (Toggle(..))
-- Prompt
import XMonad.Prompt
import XMonad.Prompt.Input
import XMonad.Prompt.FuzzyMatch
import XMonad.Prompt.Man
import XMonad.Prompt.Pass
import XMonad.Prompt.Shell (shellPrompt)
@ -80,8 +92,11 @@ import XMonad.Util.SpawnOnce
------------------------------------------------------------------------
-- VARIABLES
------------------------------------------------------------------------
-- It's nice to assign values to stuff that you will use more than once
-- in the config. Setting values for things like font, terminal and editor
-- means you only have to change the value here to make changes globally.
myFont :: String
myFont = "xft:Mononoki Nerd Font:bold:pixelsize=13"
myFont = "xft:Mononoki Nerd Font:bold:size=9"
myModMask :: KeyMask
myModMask = mod4Mask -- Sets modkey to super/windows key
@ -89,6 +104,12 @@ myModMask = mod4Mask -- Sets modkey to super/windows key
myTerminal :: String
myTerminal = "alacritty" -- Sets default terminal
myBrowser :: String
myBrowser = myTerminal ++ " -e lynx " -- Sets browser for tree select
myEditor :: String
myEditor = "emacsclient -c -a emacs " -- Sets editor for tree select
myBorderWidth :: Dimension
myBorderWidth = 2 -- Sets border width for windows
@ -109,7 +130,7 @@ windowCount = gets $ Just . show . length . W.integrate' . W.stack . W.workspace
------------------------------------------------------------------------
myStartupHook :: X ()
myStartupHook = do
spawnOnce "nitrogen --restore &"
spawnOnce "nitrogen --restore &"
spawnOnce "picom &"
spawnOnce "nm-applet &"
spawnOnce "volumeicon &"
@ -121,6 +142,8 @@ myStartupHook = do
------------------------------------------------------------------------
-- GRID SELECT
------------------------------------------------------------------------
-- GridSelect displays items (programs, open windows, etc.) in a 2D grid
-- and lets the user select from it with the cursor/hjkl keys or the mouse.
myColorizer :: Window -> Bool -> X (String, String)
myColorizer = colorRangeFromClassName
(0x29,0x2d,0x3e) -- lowest inactive bg
@ -128,13 +151,13 @@ myColorizer = colorRangeFromClassName
(0xc7,0x92,0xea) -- active bg
(0xc0,0xa7,0x9a) -- inactive fg
(0x29,0x2d,0x3e) -- active fg
-- gridSelect menu layout
mygridConfig :: p -> GSConfig Window
mygridConfig colorizer = (buildDefaultGSConfig myColorizer)
{ gs_cellheight = 40
, gs_cellwidth = 250
, gs_cellpadding = 8
, gs_cellwidth = 200
, gs_cellpadding = 6
, gs_originFractX = 0.5
, gs_originFractY = 0.5
, gs_font = myFont
@ -143,33 +166,171 @@ mygridConfig colorizer = (buildDefaultGSConfig myColorizer)
spawnSelected' :: [(String, String)] -> X ()
spawnSelected' lst = gridselect conf lst >>= flip whenJust spawn
where conf = def
{ gs_cellheight = 40
, gs_cellwidth = 200
, gs_cellpadding = 6
, gs_originFractX = 0.5
, gs_originFractY = 0.5
, gs_font = myFont
}
-- Set favorite apps for the spawnSelected'
myAppGrid :: [(String, String)]
myAppGrid = [ ("Audacity", "audacity")
, ("Deadbeef", "deadbeef")
, ("Emacs", "emacs")
, ("Firefox", "firefox")
, ("Geany", "geany")
, ("Geary", "geary")
, ("Gimp", "gimp")
, ("Kdenlive", "kdenlive")
, ("LibreOffice Impress", "loimpress")
, ("LibreOffice Writer", "lowriter")
, ("OBS", "obs")
, ("PCManFM", "pcmanfm")
, ("Simple Terminal", "st")
, ("Steam", "steam")
, ("Surf Browser", "surf suckless.org")
, ("Xonotic", "xonotic-glx")
-- The lists below are actually 3-tuples for use with gridSelect and treeSelect.
-- TreeSelect uses all three values in the 3-tuples but GridSelect only needs first
-- two values in each list (see myAppGrid, myBookmarkGrid and myConfigGrid below).
myApplications :: [([Char], [Char], [Char])]
myApplications = [ ("Audacity", "audacity", "Graphical cross-platform audio eidtor")
, ("Deadbeef", "deadbeef", "Lightweight GUI audio player")
, ("Emacs", "emacs", "Much more than a text editor")
, ("Firefox", "firefox", "The famous open source web browser")
, ("Geany", "geany", "A nice text editor")
, ("Geary", "geary", "Email client that is attractive")
, ("Gimp", "gimp", "Open source alternative to Photoshop")
, ("Kdenlive", "kdenlive", "A great open source video editor")
, ("LibreOffice Impress", "loimpress", "For making presentations")
, ("LibreOffice Writer", "lowriter", "A fully featured word processor")
, ("OBS", "obs", "Open broadcaster software")
, ("PCManFM", "pcmanfm", "Lightweight graphical file manager")
, ("Simple Terminal", "st", "Suckless simple terminal")
, ("Steam", "steam", "Proprietary gaming platform")
, ("Surf Browser", "surf suckless.org", "Suckless surf web browser")
, ("Xonotic", "xonotic-glx", "A fast-paced first person shooter")
]
myBookmarks :: [([Char], [Char], [Char])]
myBookmarks = [ ("Site Name", myBrowser ++ "https://www.distrotube.com", "Official website for DistroTube")
, ("Site Name", myBrowser ++ "https://www.distrotube.com", "Official website for DistroTube")
, ("Site Name", myBrowser ++ "https://www.distrotube.com", "Official website for DistroTube")
, ("Site Name", myBrowser ++ "https://www.distrotube.com", "Official website for DistroTube")
, ("Site Name", myBrowser ++ "https://www.distrotube.com", "Official website for DistroTube")
, ("Site Name", myBrowser ++ "https://www.distrotube.com", "Official website for DistroTube")
, ("Site Name", myBrowser ++ "https://www.distrotube.com", "Official website for DistroTube")
, ("Site Name", myBrowser ++ "https://www.distrotube.com", "Official website for DistroTube")
, ("Site Name", myBrowser ++ "https://www.distrotube.com", "Official website for DistroTube")
, ("Site Name", myBrowser ++ "https://www.distrotube.com", "Official website for DistroTube")
, ("Site Name", myBrowser ++ "https://www.distrotube.com", "Official website for DistroTube")
, ("Site Name", myBrowser ++ "https://www.distrotube.com", "Official website for DistroTube")
, ("Site Name", myBrowser ++ "https://www.distrotube.com", "Official website for DistroTube")
, ("Site Name", myBrowser ++ "https://www.distrotube.com", "Official website for DistroTube")
, ("Site Name", myBrowser ++ "https://www.distrotube.com", "Official website for DistroTube")
, ("Site Name", myBrowser ++ "https://www.distrotube.com", "Official website for DistroTube")
, ("Site Name", myBrowser ++ "https://www.distrotube.com", "Official website for DistroTube")
]
myConfigs :: [([Char], [Char], [Char])]
myConfigs = [ ("bashrc", myEditor ++ "/home/dt/.bashrc", "the bourne again shell")
, ("doom emacs config.el", myEditor ++ "/home/dt/.doom.d/config.el", "doom emacs config")
, ("doom emacs init.el", myEditor ++ "/home/dt/.doom.d/init.el", "doom emacs init")
, ("dwm", myEditor ++ "/home/dt/dwm-distrotube/config.h", "dwm config file")
, ("qtile", myEditor ++ "/home/dt/.config/qtile/config.py", "qtile config")
, ("xmonad.hs", myEditor ++ "/home/dt/.xmonad/xmonad.hs", "xmonad config")
, ("zshrc", myEditor ++ "/home/dt/.zshrc", "config for the z shell")
]
-- Three functions for pulling the first, second and third items
-- from each list in the above 3-tuple named myApplications.
-- getFst, getSnd, getThd ::[[Char]]
-- getFst = [TE.fst3 $ xs !! n | n <- [0..((length xs)-1)]]
-- getSnd = [TE.snd3 $ myApplications !! n | n <- [0..((length myApplications)-1)]]
-- getThd = [TE.thd3 $ myApplications !! n | n <- [0..((length myApplications)-1)]]
-- Creating two lists and then zipping them together in a 2-tuple so that
-- GridSelect can use them. myAppGrid is the same as myApplications above,
-- minus the third set of values (the app descriptions).
myAppGrid :: [([Char], [Char])]
myAppGrid = zip
[TE.fst3 $ xs !! n | n <- [0..(length xs - 1)]]
[TE.snd3 $ xs !! n | n <- [0..(length xs - 1)]]
where xs = myApplications
myBookmarkGrid :: [([Char], [Char])]
myBookmarkGrid = zip
[TE.fst3 $ xs !! n | n <- [0..(length xs - 1)]]
[TE.snd3 $ xs !! n | n <- [0..(length xs - 1)]]
where xs = myBookmarks
myConfigGrid :: [([Char], [Char])]
myConfigGrid = zip
[TE.fst3 $ xs !! n | n <- [0..(length xs - 1)]]
[TE.snd3 $ xs !! n | n <- [0..(length xs - 1)]]
where xs = myConfigs
------------------------------------------------------------------------
-- TREE SELECT
------------------------------------------------------------------------
-- TreeSelect displays your workspaces or actions in a Tree-like format.
-- You can select desired workspace/action with the cursor or hjkl keys.
treeselectAction :: TS.TSConfig (X ()) -> X ()
treeselectAction a = TS.treeselectAction a
[ Node (TS.TSNode "applications" "a list of programs I use often" (return ()))
[Node (TS.TSNode (TE.fst3 $ myApplications !! n)
(TE.thd3 $ myApplications !! n)
(spawn $ TE.snd3 $ myApplications !! n)
) [] | n <- [0..(length myApplications - 1)]
]
, Node (TS.TSNode "bookmarks" "a list of web bookmarks" (return ()))
[Node (TS.TSNode(TE.fst3 $ myBookmarks !! n)
(TE.thd3 $ myBookmarks !! n)
(spawn $ TE.snd3 $ myBookmarks !! n)
) [] | n <- [0..(length myBookmarks - 1)]
]
, Node (TS.TSNode "config files" "config files that edit often" (return ()))
[Node (TS.TSNode (TE.fst3 $ myConfigs !! n)
(TE.thd3 $ myConfigs !! n)
(spawn $ TE.snd3 $ myConfigs !! n)
) [] | n <- [0..(length myConfigs - 1)]
]
]
tsDefaultConfig :: TS.TSConfig a
tsDefaultConfig = TS.TSConfig { TS.ts_hidechildren = True
, TS.ts_background = 0xdd292d3e
, TS.ts_font = myFont
, TS.ts_node = (0xffd0d0d0, 0xff202331)
, TS.ts_nodealt = (0xffd0d0d0, 0xff292d3e)
, TS.ts_highlight = (0xffffffff, 0xff755999)
, TS.ts_extra = 0xffd0d0d0
, TS.ts_node_width = 200
, TS.ts_node_height = 20
, TS.ts_originX = 0
, TS.ts_originY = 0
, TS.ts_indent = 80
, TS.ts_navigate = myTreeNavigation
}
myTreeNavigation = M.fromList
[ ((0, xK_Escape), TS.cancel)
, ((0, xK_Return), TS.select)
, ((0, xK_space), TS.select)
, ((0, xK_Up), TS.movePrev)
, ((0, xK_Down), TS.moveNext)
, ((0, xK_Left), TS.moveParent)
, ((0, xK_Right), TS.moveChild)
, ((0, xK_k), TS.movePrev)
, ((0, xK_j), TS.moveNext)
, ((0, xK_h), TS.moveParent)
, ((0, xK_l), TS.moveChild)
, ((0, xK_o), TS.moveHistBack)
, ((0, xK_i), TS.moveHistForward)
, ((0, xK_b), TS.moveTo ["web", "browser"])
, ((0, xK_d), TS.moveTo ["dev"])
, ((0, xK_e), TS.moveTo ["dev", "emacs"])
, ((0, xK_f), TS.moveTo ["dev", "files"])
, ((0, xK_t), TS.moveTo ["dev", "terminal"])
, ((0, xK_g), TS.moveTo ["graphics"])
, ((0, xK_m), TS.moveTo ["music"])
, ((0, xK_p), TS.moveTo ["dev", "programming", "haskell"])
, ((0, xK_v), TS.moveTo ["video"])
, ((0, xK_1), TS.moveTo ["video", "video editor"])
, ((0, xK_w), TS.moveTo ["web"])
]
------------------------------------------------------------------------
-- XPROMPT SETTINGS
------------------------------------------------------------------------
dtXPConfig :: XPConfig
dtXPConfig = def
{ font = "xft:Mononoki Nerd Font:size=9"
{ font = myFont
, bgColor = "#292d3e"
, fgColor = "#d0d0d0"
, bgHLight = "#c792ea"
@ -185,7 +346,8 @@ dtXPConfig = def
, defaultText = []
, autoComplete = Just 100000 -- set Just 100000 for .1 sec
, showCompletionOnTab = False
, searchPredicate = isPrefixOf
-- , searchPredicate = isPrefixOf
, searchPredicate = fuzzyMatch
, alwaysHighlight = True
, maxComplRows = Nothing -- set to Just 5 for 5 rows
}
@ -194,10 +356,11 @@ dtXPConfig = def
-- certain Xprompts, like the search engine prompts.
dtXPConfig' :: XPConfig
dtXPConfig' = dtXPConfig
{ autoComplete = Nothing
{ autoComplete = Nothing
}
-- A list of all of the standard Xmonad prompts
-- A list of all of the standard Xmonad prompts and a key press assigned to them.
-- These are used in conjunction with keybinding I set later in the config.
promptList :: [(String, XPConfig -> X ())]
promptList = [ ("m", manPrompt) -- manpages prompt
, ("p", passPrompt) -- get passwords (requires 'pass')
@ -207,20 +370,21 @@ promptList = [ ("m", manPrompt) -- manpages prompt
, ("x", xmonadPrompt) -- xmonad prompt
]
-- A list of my custom prompts
-- Same as the above list except this is for my custom prompts.
promptList' :: [(String, XPConfig -> String -> X (), String)]
promptList' = [ ("c", calcPrompt, "qalc") -- requires qalculate-gtk
]
------------------------------------------------------------------------
-- CUSTOM PROMPTS
------------------------------------------------------------------------
-- calcPrompt requires a cli calculator called qalcualte-gtk.
-- You could use this as a template for other custom prompts that
-- You could use this as a template for other custom prompts that
-- use command line programs that return a single line of output.
calcPrompt :: XPConfig -> String -> X ()
calcPrompt :: XPConfig -> String -> X ()
calcPrompt c ans =
inputPrompt c (trim ans) ?+ \input ->
liftIO(runProcessWithInput "qalc" [input] "") >>= calcPrompt c
inputPrompt c (trim ans) ?+ \input ->
liftIO(runProcessWithInput "qalc" [input] "") >>= calcPrompt c
where
trim = f . f
where f = reverse . dropWhile isSpace
@ -232,7 +396,7 @@ dtXPKeymap :: M.Map (KeyMask,KeySym) (XP ())
dtXPKeymap = M.fromList $
map (first $ (,) controlMask) -- control + <key>
[ (xK_z, killBefore) -- kill line backwards
, (xK_k, killAfter) -- kill line fowards
, (xK_k, killAfter) -- kill line forwards
, (xK_a, startOfLine) -- move to the beginning of the line
, (xK_e, endOfLine) -- move to the end of the line
, (xK_m, deleteString Next) -- delete a character foward
@ -302,256 +466,103 @@ searchList = [ ("a", archwiki)
, ("z", S.amazon)
]
------------------------------------------------------------------------
-- TREE SELECT
------------------------------------------------------------------------
treeselectAction :: TS.TSConfig (X ()) -> X ()
treeselectAction a = TS.treeselectAction a
[ Node (TS.TSNode "hello" "displays hello" (spawn "xmessage hello!")) []
, Node (TS.TSNode "shutdown" "poweroff the system" (spawn "shutdown")) []
, Node (TS.TSNode "xmonad" "working with xmonad" (return ()))
[ Node (TS.TSNode "edit xmonad" "edit xmonad" (spawn (myTerminal ++ " -e vim ~/.xmonad/xmonad.hs"))) []
, Node (TS.TSNode "recompile xmonad" "recompile xmonad" (spawn "xmonad --recompile")) []
, Node (TS.TSNode "restart xmonad" "restart xmonad" (spawn "xmonad --restart")) []
]
, Node (TS.TSNode "brightness" "Sets screen brightness using xbacklight" (return ()))
[ Node (TS.TSNode "bright" "full power" (spawn "xbacklight -set 100")) []
, Node (TS.TSNode "normal" "normal brightness (50%)" (spawn "xbacklight -set 50")) []
, Node (TS.TSNode "dim" "quite dark" (spawn "xbacklight -set 10")) []
]
, Node (TS.TSNode "system monitors" "system monitoring applications" (return ()))
[ Node (TS.TSNode "htop" "a much better top" (spawn (myTerminal ++ " -e htop"))) []
, Node (TS.TSNode "glances" "an eye on your system" (spawn (myTerminal ++ " -e glances"))) []
, Node (TS.TSNode "gtop" "a more graphical top" (spawn (myTerminal ++ " -e gtop"))) []
, Node (TS.TSNode "nmon" "network monitor" (spawn (myTerminal ++ " -e nmon"))) []
, Node (TS.TSNode "s-tui" "stress your system" (spawn (myTerminal ++ " -e s-tui"))) []
]
]
tsDefaultConfig :: TS.TSConfig a
tsDefaultConfig = TS.TSConfig { TS.ts_hidechildren = True
, TS.ts_background = 0xdd292d3e
, TS.ts_font = "xft:Mononoki Nerd Font:bold:pixelsize=13"
, TS.ts_node = (0xffd0d0d0, 0xff202331)
, TS.ts_nodealt = (0xffd0d0d0, 0xff292d3e)
, TS.ts_highlight = (0xffffffff, 0xff755999)
, TS.ts_extra = 0xffd0d0d0
, TS.ts_node_width = 200
, TS.ts_node_height = 20
, TS.ts_originX = 0
, TS.ts_originY = 0
, TS.ts_indent = 80
, TS.ts_navigate = myTreeNavigation
}
myTreeNavigation = M.fromList
[ ((0, xK_Escape), TS.cancel)
, ((0, xK_Return), TS.select)
, ((0, xK_space), TS.select)
, ((0, xK_Up), TS.movePrev)
, ((0, xK_Down), TS.moveNext)
, ((0, xK_Left), TS.moveParent)
, ((0, xK_Right), TS.moveChild)
, ((0, xK_k), TS.movePrev)
, ((0, xK_j), TS.moveNext)
, ((0, xK_h), TS.moveParent)
, ((0, xK_l), TS.moveChild)
, ((0, xK_o), TS.moveHistBack)
, ((0, xK_i), TS.moveHistForward)
]
------------------------------------------------------------------------
-- KEYBINDINGS
------------------------------------------------------------------------
-- I am using the Xmonad.Util.EZConfig module which allows keybindings
-- to be written in simpler, emacs-like format.
myKeys :: [(String, X ())]
myKeys =
-- Xmonad
[ ("M-C-r", spawn "xmonad --recompile") -- Recompiles xmonad
, ("M-S-r", spawn "xmonad --restart") -- Restarts xmonad
, ("M-S-q", io exitSuccess) -- Quits xmonad
-- Open my preferred terminal
, ("M-<Return>", spawn (myTerminal))
-- Run Prompt
, ("M-S-<Return>", shellPrompt dtXPConfig) -- Shell Prompt
-- Windows
, ("M-S-c", kill1) -- Kill the currently focused client
, ("M-S-a", killAll) -- Kill all windows on current workspace
-- Floating windows
, ("M-f", sendMessage (T.Toggle "floats")) -- Toggles my 'floats' layout
, ("M-<Delete>", withFocused $ windows . W.sink) -- Push floating window back to tile
, ("M-S-<Delete>", sinkAll) -- Push ALL floating windows to tile
-- Grid Select
, ("C-g g", spawnSelected' myAppGrid) -- grid select favorite apps
, ("C-g t", goToSelected $ mygridConfig myColorizer) -- goto selected
, ("C-g b", bringSelected $ mygridConfig myColorizer) -- bring selected
-- Tree Select
, ("M-S-t", treeselectAction tsDefaultConfig) -- tree select actions menu
, ("C-t t", TS.treeselectWorkspace tsDefaultConfig myWorkspaces W.greedyView)
, ("C-t g", TS.treeselectWorkspace tsDefaultConfig myWorkspaces W.shift)
-- Windows navigation
, ("M-m", windows W.focusMaster) -- Move focus to the master window
, ("M-j", windows W.focusDown) -- Move focus to the next window
, ("M-k", windows W.focusUp) -- Move focus to the prev window
--, ("M-S-m", windows W.swapMaster) -- Swap the focused window and the master window
, ("M-S-j", windows W.swapDown) -- Swap focused window with next window
, ("M-S-k", windows W.swapUp) -- Swap focused window with prev window
, ("M-<Backspace>", promote) -- Moves focused window to master, others maintain order
, ("M1-S-<Tab>", rotSlavesDown) -- Rotate all windows except master and keep focus in place
, ("M1-C-<Tab>", rotAllDown) -- Rotate all the windows in the current stack
--, ("M-S-s", windows copyToAll)
, ("M-C-s", killAllOtherCopies)
-- Layouts
, ("M-<Tab>", sendMessage NextLayout) -- Switch to next layout
, ("M-C-M1-<Up>", sendMessage Arrange)
, ("M-C-M1-<Down>", sendMessage DeArrange)
, ("M-<Space>", sendMessage (MT.Toggle NBFULL) >> sendMessage ToggleStruts) -- Toggles noborder/full
, ("M-S-<Space>", sendMessage ToggleStruts) -- Toggles struts
, ("M-S-n", sendMessage $ MT.Toggle NOBORDERS) -- Toggles noborder
, ("M-<KP_Multiply>", sendMessage (IncMasterN 1)) -- Increase number of clients in master pane
, ("M-<KP_Divide>", sendMessage (IncMasterN (-1))) -- Decrease number of clients in master pane
, ("M-S-<KP_Multiply>", increaseLimit) -- Increase number of windows
, ("M-S-<KP_Divide>", decreaseLimit) -- Decrease number of windows
, ("M-h", sendMessage Shrink) -- Shrink horiz window width
, ("M-l", sendMessage Expand) -- Expand horiz window width
, ("M-C-j", sendMessage MirrorShrink) -- Shrink vert window width
, ("M-C-k", sendMessage MirrorExpand) -- Exoand vert window width
-- Workspaces
, ("M-.", nextScreen) -- Switch focus to next monitor
, ("M-,", prevScreen) -- Switch focus to prev monitor
, ("M-S-<KP_Add>", shiftTo Next nonNSP >> moveTo Next nonNSP) -- Shifts focused window to next ws
, ("M-S-<KP_Subtract>", shiftTo Prev nonNSP >> moveTo Prev nonNSP) -- Shifts focused window to prev ws
-- Scratchpads
, ("M-C-<Return>", namedScratchpadAction myScratchPads "terminal")
, ("M-C-c", namedScratchpadAction myScratchPads "mocp")
-- Controls for mocp music player.
, ("M-u p", spawn "mocp --play")
, ("M-u l", spawn "mocp --next")
, ("M-u h", spawn "mocp --previous")
, ("M-u <Space>", spawn "mocp --toggle-pause")
-- Emacs
, ("C-e e", spawn "emacsclient -c -a ''") -- start emacs
, ("C-e a", spawn "emacsclient -c -a '' --eval '(emms)'") -- emms emacs audio player
, ("C-e b", spawn "emacsclient -c -a '' --eval '(ibuffer)'") -- list emacs buffers
, ("C-e d", spawn "emacsclient -c -a '' --eval '(dired nil)'") -- dired emacs file manager
, ("C-e m", spawn "emacsclient -c -a '' --eval '(mu4e)'") -- mu4e emacs email client
, ("C-e n", spawn "emacsclient -c -a '' --eval '(elfeed)'") -- elfeed emacs rss client
, ("C-e s", spawn "emacsclient -c -a '' --eval '(eshell)'") -- eshell within emacs
, ("C-e t", spawn "emacsclient -c -a '' --eval '(+vterm/here nil)'") -- eshell within emacs
--- My Applications (Super+Alt+Key)
, ("M-M1-a", spawn (myTerminal ++ " -e ncpamixer"))
, ("M-M1-b", spawn "surf www.youtube.com/c/DistroTube/")
--, ("M-M1-e", spawn (myTerminal ++ " -e neomutt"))
, ("M-M1-e", spawn "emacsclient -c -a '' --eval '(mu4e)'")
, ("M-M1-f", spawn (myTerminal ++ " -e sh ./.config/vifm/scripts/vifmrun"))
, ("M-M1-i", spawn (myTerminal ++ " -e irssi"))
, ("M-M1-j", spawn (myTerminal ++ " -e joplin"))
, ("M-M1-l", spawn (myTerminal ++ " -e lynx -cfg=~/.lynx/lynx.cfg -lss=~/.lynx/lynx.lss gopher://distro.tube"))
, ("M-M1-m", spawn (myTerminal ++ " -e mocp"))
, ("M-M1-n", spawn "emacsclient -c -a '' --eval '(elfeed)'")
, ("M-M1-p", spawn (myTerminal ++ " -e pianobar"))
, ("M-M1-r", spawn (myTerminal ++ " -e rtv"))
, ("M-M1-t", spawn (myTerminal ++ " -e toot curses"))
, ("M-M1-w", spawn (myTerminal ++ " -e wopr report.xml"))
, ("M-M1-y", spawn (myTerminal ++ " -e youtube-viewer"))
-- Multimedia Keys
, ("<XF86AudioPlay>", spawn "cmus toggle")
, ("<XF86AudioPrev>", spawn "cmus prev")
, ("<XF86AudioNext>", spawn "cmus next")
-- , ("<XF86AudioMute>", spawn "amixer set Master toggle") -- Bug prevents it from toggling correctly in 12.04.
, ("<XF86AudioLowerVolume>", spawn "amixer set Master 5%- unmute")
, ("<XF86AudioRaiseVolume>", spawn "amixer set Master 5%+ unmute")
, ("<XF86HomePage>", spawn "firefox")
, ("<XF86Search>", safeSpawn "firefox" ["https://www.google.com/"])
, ("<XF86Mail>", runOrRaise "geary" (resource =? "thunderbird"))
, ("<XF86Calculator>", runOrRaise "gcalctool" (resource =? "gcalctool"))
, ("<XF86Eject>", spawn "toggleeject")
, ("<Print>", spawn "scrotd 0")
]
-- Appending search engines to keybindings list
++ [("M-s " ++ k, S.promptSearch dtXPConfig' f) | (k,f) <- searchList ]
++ [("M-S-s " ++ k, S.selectSearch f) | (k,f) <- searchList ]
++ [("M-p " ++ k, f dtXPConfig') | (k,f) <- promptList ]
++ [("M-p " ++ k, f dtXPConfig' g) | (k,f,g) <- promptList' ]
-- Appending named scratchpads to keybindings list
where nonNSP = WSIs (return (\ws -> W.tag ws /= "nsp"))
nonEmptyNonNSP = WSIs (return (\ws -> isJust (W.stack ws) && W.tag ws /= "nsp"))
------------------------------------------------------------------------
-- WORKSPACES
------------------------------------------------------------------------
-- My workspaces are clickable meaning that the mouse can be used to switch
-- workspaces. This requires xdotool.
-- workspaces. This requires xdotool. You need to use UnsafeStdInReader instead
-- of simply StdInReader in xmobar config so you can pass actions to it.
xmobarEscape :: String -> String
xmobarEscape = concatMap doubleLts
where
doubleLts '<' = "<<"
doubleLts x = [x]
-- myWorkspaces :: [String]
-- myWorkspaces = clickable . map xmobarEscape
-- $ ["dev", "www", "sys", "doc", "vbox", "chat", "mus", "vid", "gfx"]
-- where
-- clickable l = [ "<action=xdotool key super+" ++ show n ++ ">" ++ ws ++ "</action>" |
-- (i,ws) <- zip [1..9] l,
-- let n = i ]
{- Commented out clickable xmobar workspaces to use TreeSelect workspaces.
myWorkspaces :: [String]
myWorkspaces = clickable . map xmobarEscape
$ ["dev", "www", "sys", "doc", "vbox", "chat", "mus", "vid", "gfx"]
where
clickable l = [ "<action=xdotool key super+" ++ show n ++ ">" ++ ws ++ "</action>" |
(i,ws) <- zip [1..9] l,
let n = i ]
End of comment -}
-- TreeSelect workspaces
myWorkspaces :: Forest String
myWorkspaces = [ Node "Browser" [] -- a workspace for your browser
, Node "Home" -- for everyday activity's
[ Node "1" [] -- with 4 extra sub-workspaces, for even more activity's
, Node "2" []
, Node "3" []
, Node "4" []
myWorkspaces = [ Node "dev"
[ Node "terminal" []
, Node "emacs" []
, Node "docs" []
, Node "files" []
, Node "programming"
[ Node "haskell" []
, Node "python" []
, Node "shell" []
]
, Node "virtualization" []
]
, Node "Programming" -- for all your programming needs
[ Node "Haskell" []
, Node "Docs" [] -- documentation
, Node "web"
[ Node "browser" []
, Node "chat" []
, Node "email" []
, Node "rss" []
, Node "video conferencing" []
]
, Node "graphics"
[ Node "gimp" []
, Node "image viewer" []
]
, Node "music"
[ Node "audio editor" []
, Node "music player" []
]
, Node "video"
[ Node "obs" []
, Node "movie player" []
, Node "video editor" []
]
]
------------------------------------------------------------------------
-- MANAGEHOOK
------------------------------------------------------------------------
-- Sets some rules for certain programs. Examples include forcing certain
-- programs to always float, or to always appear on a certain workspace.
-- Forcing programs to a certain workspace with a doShift requires xdotool
-- if you are using clickable workspaces. You need the className or title
-- if you are using clickable workspaces. You need the className or title
-- of the program. Use xprop to get this info.
myManageHook :: XMonad.Query (Data.Monoid.Endo WindowSet)
myManageHook = composeAll
-- using 'doShift ( myWorkspaces !! 7)' sends program to workspace 8!
-- I'm doing it this way because otherwise I would have to write out
-- I'm doing it this way because otherwise I would have to write out
-- the full name of my clickable workspaces, which would look like:
-- doShift "<action xdotool super+8>gfx</action>"
[ className =? "obs" --> doShift ( "Browser")
, title =? "firefox" --> doShift ( "Browser")
, title =? "qutebrowser" --> doShift ( "Browser")
, className =? "vlc" --> doShift ( "Browser")
, className =? "Gimp" --> doShift ( "Browser")
[ className =? "obs" --> doShift ( "video.obs" )
, title =? "firefox" --> doShift ( "web.browser" )
, title =? "qutebrowser" --> doShift ( "web.browser" )
, className =? "mpv" --> doShift ( "video.movie player" )
, className =? "vlc" --> doShift ( "video.movie player" )
, className =? "Gimp" --> doShift ( "graphics.gimp")
, className =? "Gimp" --> doFloat
, title =? "Oracle VM VirtualBox Manager" --> doFloat
, className =? "Oracle VM VirtualBox Manager" --> doShift ( "Browser")
, className =? "VirtualBox Manager" --> doShift ( "dev.virtualization" )
, (className =? "firefox" <&&> resource =? "Dialog") --> doFloat -- Float Firefox Dialog
] <+> namedScratchpadManageHook myScratchPads
------------------------------------------------------------------------
-- LOGHOOK
------------------------------------------------------------------------
-- sets opacity for inactive (unfocused) windows.
myLogHook :: X ()
myLogHook = fadeInactiveLogHook fadeAmount
where fadeAmount = 0.9
------------------------------------------------------------------------
-- LAYOUTS
------------------------------------------------------------------------
@ -611,7 +622,16 @@ tabs = renamed [Replace "tabs"]
, activeTextColor = "#ffffff"
, inactiveTextColor = "#d0d0d0"
}
-- Theme for showWName which prints current workspace when you change workspaces.
myShowWNameTheme :: SWNConfig
myShowWNameTheme = def
{ swn_font = "xft:Sans:bold:size=60"
, swn_fade = 1.0
, swn_bgcolor = "#000000"
, swn_color = "#FFFFFF"
}
-- The layout hook
myLayoutHook = avoidStruts $ mouseResize $ windowArrange $ T.toggleLayouts floats $
mkToggle (NBFULL ?? NOBORDERS ?? EOT) myDefaultLayout
@ -630,6 +650,8 @@ myLayoutHook = avoidStruts $ mouseResize $ windowArrange $ T.toggleLayouts float
------------------------------------------------------------------------
-- SCRATCHPADS
------------------------------------------------------------------------
-- Allows to have several floating scratchpads running different applications.
-- Import Util.NamedScratchpad. Bind a key to namedScratchpadSpawnAction.
myScratchPads :: [NamedScratchpad]
myScratchPads = [ NS "terminal" spawnTerm findTerm manageTerm
, NS "mocp" spawnMocp findMocp manageMocp
@ -652,6 +674,147 @@ myScratchPads = [ NS "terminal" spawnTerm findTerm manageTerm
t = 0.95 -h
l = 0.95 -w
------------------------------------------------------------------------
-- KEYBINDINGS
------------------------------------------------------------------------
-- I am using the Xmonad.Util.EZConfig module which allows keybindings
-- to be written in simpler, emacs-like format.
myKeys :: [(String, X ())]
myKeys =
-- Xmonad
[ ("M-C-r", spawn "xmonad --recompile") -- Recompiles xmonad
, ("M-S-r", spawn "xmonad --restart") -- Restarts xmonad
, ("M-S-q", io exitSuccess) -- Quits xmonad
-- Open my preferred terminal
, ("M-<Return>", spawn myTerminal)
-- Run Prompt
, ("M-S-<Return>", shellPrompt dtXPConfig) -- Shell Prompt
-- Windows
, ("M-S-c", kill1) -- Kill the currently focused client
, ("M-S-a", killAll) -- Kill all windows on current workspace
-- Floating windows
, ("M-f", sendMessage (T.Toggle "floats")) -- Toggles my 'floats' layout
, ("M-<Delete>", withFocused $ windows . W.sink) -- Push floating window back to tile
, ("M-S-<Delete>", sinkAll) -- Push ALL floating windows to tile
-- Grid Select (CTRL-g followed by a key)
, ("C-g g", spawnSelected' myAppGrid) -- grid select favorite apps
, ("C-g m", spawnSelected' myBookmarkGrid) -- grid select some bookmarks
, ("C-g c", spawnSelected' myConfigGrid) -- grid select useful config files
, ("C-g t", goToSelected $ mygridConfig myColorizer) -- goto selected window
, ("C-g b", bringSelected $ mygridConfig myColorizer) -- bring selected window
-- Tree Select/
-- tree select actions menu
, ("C-t a", treeselectAction tsDefaultConfig)
-- tree select workspaces menu
, ("C-t t", TS.treeselectWorkspace tsDefaultConfig myWorkspaces W.greedyView)
-- tree select choose workspace to send window
, ("C-t g", TS.treeselectWorkspace tsDefaultConfig myWorkspaces W.shift)
-- Windows navigation
, ("M-m", windows W.focusMaster) -- Move focus to the master window
, ("M-j", windows W.focusDown) -- Move focus to the next window
, ("M-k", windows W.focusUp) -- Move focus to the prev window
--, ("M-S-m", windows W.swapMaster) -- Swap the focused window and the master window
, ("M-S-j", windows W.swapDown) -- Swap focused window with next window
, ("M-S-k", windows W.swapUp) -- Swap focused window with prev window
, ("M-<Backspace>", promote) -- Moves focused window to master, others maintain order
, ("M1-S-<Tab>", rotSlavesDown) -- Rotate all windows except master and keep focus in place
, ("M1-C-<Tab>", rotAllDown) -- Rotate all the windows in the current stack
--, ("M-S-s", windows copyToAll)
, ("M-C-s", killAllOtherCopies)
-- Layouts
, ("M-<Tab>", sendMessage NextLayout) -- Switch to next layout
, ("M-C-M1-<Up>", sendMessage Arrange)
, ("M-C-M1-<Down>", sendMessage DeArrange)
, ("M-<Space>", sendMessage (MT.Toggle NBFULL) >> sendMessage ToggleStruts) -- Toggles noborder/full
, ("M-S-<Space>", sendMessage ToggleStruts) -- Toggles struts
, ("M-S-n", sendMessage $ MT.Toggle NOBORDERS) -- Toggles noborder
, ("M-<KP_Multiply>", sendMessage (IncMasterN 1)) -- Increase number of clients in master pane
, ("M-<KP_Divide>", sendMessage (IncMasterN (-1))) -- Decrease number of clients in master pane
, ("M-S-<KP_Multiply>", increaseLimit) -- Increase number of windows
, ("M-S-<KP_Divide>", decreaseLimit) -- Decrease number of windows
, ("M-h", sendMessage Shrink) -- Shrink horiz window width
, ("M-l", sendMessage Expand) -- Expand horiz window width
, ("M-C-j", sendMessage MirrorShrink) -- Shrink vert window width
, ("M-C-k", sendMessage MirrorExpand) -- Exoand vert window width
-- Workspaces
, ("M-.", nextScreen) -- Switch focus to next monitor
, ("M-,", prevScreen) -- Switch focus to prev monitor
, ("M-S-<KP_Add>", shiftTo Next nonNSP >> moveTo Next nonNSP) -- Shifts focused window to next ws
, ("M-S-<KP_Subtract>", shiftTo Prev nonNSP >> moveTo Prev nonNSP) -- Shifts focused window to prev ws
-- Scratchpads
, ("M-C-<Return>", namedScratchpadAction myScratchPads "terminal")
, ("M-C-c", namedScratchpadAction myScratchPads "mocp")
-- Controls for mocp music player.
, ("M-u p", spawn "mocp --play")
, ("M-u l", spawn "mocp --next")
, ("M-u h", spawn "mocp --previous")
, ("M-u <Space>", spawn "mocp --toggle-pause")
-- Emacs (CTRL-e followed by a key)
, ("C-e e", spawn "emacsclient -c -a ''") -- start emacs
, ("C-e a", spawn "emacsclient -c -a '' --eval '(emms)'") -- emms emacs audio player
, ("C-e b", spawn "emacsclient -c -a '' --eval '(ibuffer)'") -- list emacs buffers
, ("C-e d", spawn "emacsclient -c -a '' --eval '(dired nil)'") -- dired emacs file manager
, ("C-e m", spawn "emacsclient -c -a '' --eval '(mu4e)'") -- mu4e emacs email client
, ("C-e n", spawn "emacsclient -c -a '' --eval '(elfeed)'") -- elfeed emacs rss client
, ("C-e s", spawn "emacsclient -c -a '' --eval '(eshell)'") -- eshell within emacs
, ("C-e t", spawn "emacsclient -c -a '' --eval '(+vterm/here nil)'") -- eshell within emacs
--- My Applications (Super+Alt+Key)
, ("M-M1-a", spawn (myTerminal ++ " -e ncpamixer"))
, ("M-M1-b", spawn "surf www.youtube.com/c/DistroTube/")
--, ("M-M1-e", spawn (myTerminal ++ " -e neomutt"))
, ("M-M1-e", spawn "emacsclient -c -a '' --eval '(mu4e)'")
, ("M-M1-f", spawn (myTerminal ++ " -e sh ./.config/vifm/scripts/vifmrun"))
, ("M-M1-i", spawn (myTerminal ++ " -e irssi"))
, ("M-M1-j", spawn (myTerminal ++ " -e joplin"))
, ("M-M1-l", spawn (myTerminal ++ " -e lynx -cfg=~/.lynx/lynx.cfg -lss=~/.lynx/lynx.lss gopher://distro.tube"))
, ("M-M1-m", spawn (myTerminal ++ " -e mocp"))
, ("M-M1-n", spawn "emacsclient -c -a '' --eval '(elfeed)'")
, ("M-M1-p", spawn (myTerminal ++ " -e pianobar"))
, ("M-M1-r", spawn (myTerminal ++ " -e rtv"))
, ("M-M1-t", spawn (myTerminal ++ " -e toot curses"))
, ("M-M1-w", spawn (myTerminal ++ " -e wopr report.xml"))
, ("M-M1-y", spawn (myTerminal ++ " -e youtube-viewer"))
-- Multimedia Keys
, ("<XF86AudioPlay>", spawn "cmus toggle")
, ("<XF86AudioPrev>", spawn "cmus prev")
, ("<XF86AudioNext>", spawn "cmus next")
-- , ("<XF86AudioMute>", spawn "amixer set Master toggle") -- Bug prevents it from toggling correctly in 12.04.
, ("<XF86AudioLowerVolume>", spawn "amixer set Master 5%- unmute")
, ("<XF86AudioRaiseVolume>", spawn "amixer set Master 5%+ unmute")
, ("<XF86HomePage>", spawn "firefox")
, ("<XF86Search>", safeSpawn "firefox" ["https://www.google.com/"])
, ("<XF86Mail>", runOrRaise "geary" (resource =? "thunderbird"))
, ("<XF86Calculator>", runOrRaise "gcalctool" (resource =? "gcalctool"))
, ("<XF86Eject>", spawn "toggleeject")
, ("<Print>", spawn "scrotd 0")
]
-- Appending search engine prompts to keybindings list.
-- Look at "search engines" section of this config for values for "k".
++ [("M-s " ++ k, S.promptSearch dtXPConfig' f) | (k,f) <- searchList ]
++ [("M-S-s " ++ k, S.selectSearch f) | (k,f) <- searchList ]
-- Appending some extra xprompts to keybindings list.
-- Look at "xprompt settings" section this of config for values for "k".
++ [("M-p " ++ k, f dtXPConfig') | (k,f) <- promptList ]
++ [("M-p " ++ k, f dtXPConfig' g) | (k,f,g) <- promptList' ]
-- The following lines are needed for named scratchpads.
where nonNSP = WSIs (return (\ws -> W.tag ws /= "nsp"))
nonEmptyNonNSP = WSIs (return (\ws -> isJust (W.stack ws) && W.tag ws /= "nsp"))
------------------------------------------------------------------------
-- MAIN
------------------------------------------------------------------------
@ -666,31 +829,31 @@ main = do
{ manageHook = ( isFullscreen --> doFullFloat ) <+> myManageHook <+> manageDocks
-- Run xmonad commands from command line with "xmonadctl command". Commands include:
-- shrink, expand, next-layout, default-layout, restart-wm, xterm, kill, refresh, run,
-- focus-up, focus-down, swap-up, swap-down, swap-master, sink, quit-wm. You can run
-- focus-up, focus-down, swap-up, swap-down, swap-master, sink, quit-wm. You can run
-- "xmonadctl 0" to generate full list of commands written to ~/.xsession-errors.
, handleEventHook = serverModeEventHookCmd
<+> serverModeEventHook
, handleEventHook = serverModeEventHookCmd
<+> serverModeEventHook
<+> serverModeEventHookF "XMONAD_PRINT" (io . putStrLn)
<+> docksEventHook
, modMask = myModMask
, terminal = myTerminal
, startupHook = myStartupHook
, layoutHook = myLayoutHook
, layoutHook = showWName' myShowWNameTheme myLayoutHook
, workspaces = TS.toWorkspaces myWorkspaces
, borderWidth = myBorderWidth
, normalBorderColor = myNormColor
, focusedBorderColor = myFocusColor
, logHook = dynamicLogWithPP $ xmobarPP
{ ppOutput = \x -> hPutStrLn xmproc0 x >> hPutStrLn xmproc1 x >> hPutStrLn xmproc2 x
, ppCurrent = xmobarColor "#c3e88d" "" . wrap "[" "]" -- Current workspace in xmobar
, ppVisible = xmobarColor "#c3e88d" "" -- Visible but not current workspace
, ppHidden = xmobarColor "#82AAFF" "" . wrap "*" "" -- Hidden workspaces in xmobar
, ppHiddenNoWindows = xmobarColor "#F07178" "" -- Hidden workspaces (no windows)
, ppTitle = xmobarColor "#d0d0d0" "" . shorten 60 -- Title of active window in xmobar
, ppSep = "<fc=#666666> | </fc>" -- Separators in xmobar
, ppUrgent = xmobarColor "#C45500" "" . wrap "!" "!" -- Urgent workspace
, ppExtras = [windowCount] -- # of windows current workspace
, ppOrder = \(ws:l:t:ex) -> [ws,l]++ex++[t]
}
} `additionalKeysP` myKeys
, logHook = workspaceHistoryHook <+> myLogHook <+> dynamicLogWithPP xmobarPP
{ ppOutput = \x -> hPutStrLn xmproc0 x >> hPutStrLn xmproc1 x >> hPutStrLn xmproc2 x
, ppCurrent = xmobarColor "#c3e88d" "" . wrap "[" "]" -- Current workspace in xmobar
, ppVisible = xmobarColor "#c3e88d" "" -- Visible but not current workspace
, ppHidden = xmobarColor "#82AAFF" "" . wrap "*" "" -- Hidden workspaces in xmobar
-- , ppHiddenNoWindows = xmobarColor "#F07178" "" -- Hidden workspaces (no windows)
, ppHiddenNoWindows= \( _ ) -> "" -- Only shows visible workspaces. Useful for TreeSelect.
, ppTitle = xmobarColor "#d0d0d0" "" . shorten 60 -- Title of active window in xmobar
, ppSep = "<fc=#666666> | </fc>" -- Separators in xmobar
, ppUrgent = xmobarColor "#C45500" "" . wrap "!" "!" -- Urgent workspace
, ppExtras = [windowCount] -- # of windows current workspace
, ppOrder = \(ws:l:t:ex) -> [ws,l]++ex++[t]
}
} `additionalKeysP` myKeys