Xmonad/Config archive/sereven's xmonad.hs one-host: Difference between revisions

From HaskellWiki
(fix so file compiles -- apparently was too big for xselection)
mNo edit summary
 
(12 intermediate revisions by one other user not shown)
Line 1: Line 1:
Apparently this file is too big to copy all at once without errors, so copy paste in two sections, see -- SPLIT HERE -- comment
<haskell>
<haskell>
------ may not want scaling dzen bar -------------
------ sereven.0.8.base.xmonad.hs ----------------
import Graphics.X11.Xlib
import Graphics.X11.Xinerama
import Data.Maybe (fromMaybe)
------ normal imports                          --
import XMonad
import XMonad
import qualified XMonad.StackSet as W
import qualified XMonad.StackSet as W
------                                          --
import System.Environment (getEnvironment)
import qualified Data.Map as M
import XMonad.Actions.DynamicWorkspaces
import Data.Ratio ((%)) -- for Layout.IM
import XMonad.Actions.WindowNavigation
------                                          --
import XMonad.Hooks.DynamicLog
import XMonad.Hooks.ManageDocks
import XMonad.Hooks.ManageDocks
import XMonad.Hooks.ManageHelpers(doCenterFloat)
import XMonad.Hooks.ManageHelpers (doCenterFloat, isFullscreen, doFullFloat)
import XMonad.Hooks.UrgencyHook
import XMonad.Hooks.UrgencyHook
import XMonad.Hooks.DynamicLog
import XMonad.Layout.IM -- (m%n) can be (m/n) don't need Data.Ratio
------                                          --
import XMonad.Layout.LayoutScreens
import XMonad.Actions.CycleWS
import XMonad.Layout.NoBorders
import XMonad.Actions.WindowGo
import XMonad.Layout.PerWorkspace
import XMonad.Actions.Warp
------                                          --
import XMonad.Layout.IM
import XMonad.Layout.Reflect
import XMonad.Layout.Reflect
import XMonad.Layout.PerWorkspace
import XMonad.Layout.ResizableTile
import XMonad.Layout.ResizableTile
import XMonad.Layout.ToggleLayouts as TL
import XMonad.Layout.TwoPane
import XMonad.Layout.WindowNavigation
import XMonad.Layout.WindowNavigation
import XMonad.Layout.NoBorders
import qualified XMonad.Layout.ToggleLayouts as TL
------                                          --
import XMonad.Prompt
import XMonad.Prompt
import XMonad.Prompt.Shell
import XMonad.Prompt.Shell
import XMonad.Prompt.RunOrRaise
import XMonad.Prompt.RunOrRaise
------                                          --
import XMonad.Util.EZConfig
import XMonad.Util.Run
import XMonad.Util.Run
import XMonad.Util.Scratchpad
import XMonad.Util.Scratchpad
import XMonad.Util.EZConfig
import XMonad.Util.WorkspaceCompare (getSortByTag,getSortByIndex)


modm = mod4Mask
sWorkspaces = [ [x] | x <- ['A'..'I'] ] -- /3 MINIMUM/ (easy to mod num wss)


-- "Make it so, Mr. X!" --------------------
ws2 = sWorkspaces !! 1
ws3 = sWorkspaces !! 2


main = do
main = do
     scrxpw <- getXPositionAndWidthOfScreen 0 -- dzen screen number
     dz <- spawnPipe $ dzenWith darkXPC
     let dzencmd = uncurry dzenWithParamsFrom (fromMaybe (0, 1024) scrxpw) darkXPC
     home <- fmap (maybe "/home/svv/" (++"/") . lookup "HOME") getEnvironment
     dz <- spawnPipe dzencmd
     conf <- withWindowNavigation (xK_k, xK_h, xK_j, xK_l) $
            withUrgencyHook NoUrgencyHook $
              defaultConfig
                  { modMask            = modm
                  , focusFollowsMouse  = True
                  , terminal          = "urxvtc"
                  , focusedBorderColor = "#694"
                  , normalBorderColor  = "black"
                  , borderWidth        = 1
                  , workspaces        = sWorkspaces
                  , layoutHook        = sLayouts
                  , logHook            = dynamicLogWithPP $ dzdarkPP home dz
                  , manageHook        = sManageHook
                  }  `additionalKeys` sKeys `additionalKeysP` sKeysP
                    -- silly to use both, but.. meh..
    xmonad conf


    -- uncomment to show dzen params while setting up other bars in .xinitrc
sKeys = -- need normal bindings for testing ScreenWorkspaces
     -- spawn $ "xmessage " ++ "'" ++ dzencmd ++ "'"
    [ ((modm .|. controlMask, xK_space), sendMessage TL.ToggleLayout )
    , ((modm,xK_b)    , sendMessage ToggleStruts)
    , ((shiftMask,xK_F1), shellPrompt darkXPC)
    , ((shiftMask,xK_F2), runOrRaisePrompt darkXPC)
     , ((shiftMask,xK_F3), scratchpadSpawnActionTerminal "urxvt -pe tabbed")


    let conf  = sConfig "/home/gvg" dz
     -- for more screens, workspaces, or exploring ion style subframes
    let sKeys = keysWithPath "/home/gvg" conf
     , ((modm,              xK_backslash), selectWorkspace darkXPC)
    xmonad $ withUrgencyHook NoUrgencyHook $
     , ((modm .|. shiftMask ,xK_BackSpace), removeWorkspace)
      conf {startupHook = return () >> checkKeymap conf sKeys}
     , ((modm              ,   xK_F8), rescreen)
      `additionalKeysP` sKeys
     , ((modm .|. shiftMask,   xK_F8), layoutScreens 4 (Tall 2 (1/8) (1/2)))
 
    ]
     -- using this XConfig
 
sConfig hm dzh = defaultConfig
    { workspaces         = sWorkspaces
     , manageHook        = sManageHook
     , layoutHook        = sLayout
    , logHook            = dynamicLogWithPP $ dzdarkPP hm dzh
     , borderWidth        = 1
    , focusedBorderColor = hlightCol dkCols  -- ltCol dkCols
    , normalBorderColor  = dkCol dkCols
     , focusFollowsMouse = True
    , modMask            = mod4Mask
    , terminal          = "urxvtc"
    }
 
 
-- (frequently edited bits nearer the top) -------
 
keysWithPath hm cfg =


    [ ("M-<F1>",  shellPrompt darkXPC)
sKeysP = -- TODO convert to additionalKeys
    , ("M-<F2>",  runOrRaisePrompt darkXPC)
     [ ("M-C-k", sendMessage MirrorExpand)
    , ("M-<F3>",  scratchpadSpawnAction cfg)
    , ("M-<F12>", spawn "xscreensaver-command -lock")
 
    , ("M-x f", runOrRaise "firefox" (className =? "Firefox"))
    , ("M-x o", runOrRaise "opera" (className =? "Opera"))
    , ("M-x r", runOrRaise (hm ++ "/bin/shfmRun") (title =? "shellfm"))
    , ("M-x h", runOrRaise "hback" (className =? "Hback"))
    , ("M-x g", spawn "gimp")
    ]
    ++ -- vi directional window navigation similar to XMonad defaults
     [ ("M-k", sendMessage $ Go U)
    , ("M-j", sendMessage $ Go D)
    , ("M-h", sendMessage $ Go L)
    , ("M-l", sendMessage $ Go R)
    , ("M-S-k", sendMessage $ Swap U)    -- shift shifts windows
    , ("M-S-j", sendMessage $ Swap D)
    , ("M-S-h", sendMessage $ Swap L)
    , ("M-S-l", sendMessage $ Swap R)
    , ("M-C-k", sendMessage MirrorExpand) -- ctrl controls size
     , ("M-C-j", sendMessage MirrorShrink)
     , ("M-C-j", sendMessage MirrorShrink)
     , ("M-C-h", sendMessage Shrink)
     , ("M-C-h", sendMessage Shrink)
     , ("M-C-l", sendMessage Expand)
     , ("M-C-l", sendMessage Expand)
     ]
     ]
     ++ -- mod-<key> and mod-shift-<key> are as default (plus 0 and = too)
     ++ -- workspace and screen keys ------------------------------------
      -- mod-<key> and mod-shift-<key> are as default
       -- mod-ctrl-<key> shifts focused window *and* view to <key>'s ws
       -- mod-ctrl-<key> shifts focused window *and* view to <key>'s ws
     [ (addtlmods ++ "M-" ++ [key], action tag)
     [ (addtlmods ++ "M-" ++ [key], action tag)
     |  (tag, key)  <- zip sWorkspaces "1234567890="
     |  (tag, key)  <- zip sWorkspaces "1234567890_="
       , (addtlmods, action) <- [ ("", windows . W.greedyView)
       , (addtlmods, action) <- [ ("", windows . W.greedyView) -- or W.view)
                               , ("S-", windows . W.shift)
                               , ("S-", windows . W.shift)
                               , ("C-", \x -> (windows . W.shift) x >> (windows . W.view) x)]
                               , ("C-", \x -> (windows . W.shift) x >> (windows . W.view) x)]
    ]
    ++ --  mod + m + {left arrow or 'a' key} does action with ws to "left"
    [ (m ++ "M-" ++ key, action) | key <- ["<L>","a"]
      , (m, action) <- [ ("", prevWS), ("S-", shiftToPrev), ("C-", shiftToPrev >> prevWS)]
    ]
    ++ -- mod + m + {right arrow or 'd' key} does action with ws to "right"
    [ (m ++ "M-" ++ key, action) | key  <- ["<R>","d"]
      , (m, action) <- [ ("", nextWS), ("S-", shiftToNext), ("C-", shiftToNext >> nextWS)]
    ]
    ++
    [ ("M-<Space>", sendMessage TL.ToggleLayout ) -- noBorders Full
    , ("M-b", sendMessage ToggleStruts)
    , ("M-C-b", warpToScreen 0 (1/2) 0) -- open XM dzen slave; exit mouse manually to collapse :(
    , ("M-S-b", warpToScreen 0 0 0)  -- open sys dzen slave; exit mouse manually to collapse :(
    , ("M-m", warpToWindow 1 1) -- banish mouse to lower right of focused window
     ]
     ]
sWorkspaces = ["'%", "%", "%'"] ++ ["'*", "*", "*'"] ++ ["c", "m", "#"] ++ ["@", "SP"]


sManageHook = composeAll
sManageHook = composeAll
     [ doF avoidMaster
     [ scratchpadManageHookDefault
    , scratchpadManageHookDefault
     , isFullscreen              --> doFullFloat
 
     , className =? "Gimp"      --> doShift ws3 -- don't float
     , title =? "shellfm"        --> doShift "'*"
     , className =? "MPlayer"    --> doShift ws2
     , className =? "Gimp"      --> doShift "*" -- don't float, IM layout
    , title =? "shellfm"       --> doShift ws2
     , className =? "MPlayer"    --> doShift "*'"


     , title =? ""              --> doFloat    -- SOE graphics
     , title =? ""              --> doFloat    -- SOE graphics
     , title =? "shellfm"        --> doFloat
     , title =? "shellfm"        --> doFloat
    , className =? "MPlayer"    --> doFloat
     , className =? "Hback"      --> doCenterFloat
     , className =? "Hback"      --> doCenterFloat
    , className =? "MPlayer"    --> doFloat
     , className =? "XFontSel"  --> doCenterFloat
     , className =? "XFontSel"  --> doCenterFloat
     , className =? "Xmessage"  --> doCenterFloat
     , className =? "Xmessage"  --> doCenterFloat
     ]
     ]
  where avoidMaster :: W.StackSet i l a s sd -> W.StackSet i l a s sd
        avoidMaster = W.modify' $ \c -> case c of
            W.Stack t [] (r:rs) -> W.Stack t [r] rs
            otherwise          -> c


sLayout  =
sLayouts =
     avoidStruts $ configurableNavigation (noNavigateBorders) $
     smartBorders . avoidStruts $
     TL.toggleLayouts (noBorders Full) $
     TL.toggleLayouts (noBorders Full) $
     modWorkspace "*" reflectHoriz $ withIM (11%64) (Role "gimp-toolbox") $ -- see [gimp]
     modWorkspace ws3 reflectHoriz $ withIM (11/64) (Role "gimp-toolbox") $
    onWorkspace  ws2 (TwoPane (1/118) (11/15)) $
     ResizableTall 2        -- default number of masters
     ResizableTall 2        -- default number of masters
                   (1/118)  -- resize increment
                   (1/118)  -- resize increment
                   (11/20)  -- horizontal ratio: mstr/(mstr+slv)?
                   (11/20)  -- horizontal ratio
                   [5/4 -- master column ~ top/bottom?
                   [5/4 -- master column ~ top/bottom
                   ,5/4 -- no effect w/ 2 masters
                   ,5/4 -- no effect w/ 2 masters
                   ,5/4 -- slave  column ~ top/bottom
                   ,5/4 -- slave  column ~ top/bottom
                   ]    -- then defaults to (repeat 1)
                   ]    -- then defaults to (repeat 1)
    -- [gimp] -- Combining gimp-toolbox and gimp-dock into one works
    -- well in IM layout roster column. Drag panes from gimp-dock or
    -- toolbox to top separator or bar of toolbox to add and re-arrange.
-------- !! SPLIT HERE !! -------------------


-- (theming, font, colors) ------------------
-- (theming, font, colors) ------------------
-- from cross-host conf, better to just use 'color' where needed, but I'm too
darkXPC :: XPConfig
-- lazy to edit this whole file for colors.
 
data Colorset = Colorset
    { ltCol      :: String
    , dkCol      :: String
    , currentCol  :: String
    , hlightCol  :: String
    , visibleCol  :: String
    , hiddenCol  :: String
    , fadedCol    :: String
    , urgentCol  :: String
    }
 
dkCols = Colorset
    { ltCol      = "#d7e19f"
    , dkCol      = "#230"
    , currentCol  = "black"
    , hlightCol  = "#0e3"
    , visibleCol  = "#443"
    , hiddenCol  = "#564"
    , fadedCol    = "#ab9"
    , urgentCol  = "#e30"
    }
 
darkXPC = defaultXPConfig
darkXPC = defaultXPConfig
    { font = "-*-dejavu sans mono-medium-r-*-*-17-*-*-*-*-*-*-*"
      { font = "-*-dejavu sans mono-medium-r-*-*-17-*-*-*-*-*-*-*"
    , height  = 22
      , height  = 28
    , bgColor  = dkCol dkCols
      , bgColor  = "black"
    , fgColor  = ltCol dkCols
      , fgColor  = "#684"
    , bgHLight = ltCol dkCols
      , bgHLight = "#785"
    , fgHLight = dkCol dkCols
      , fgHLight = "black"
    , promptBorderWidth = 0
      , promptBorderWidth = 0
    }
      }
 


-- (dzen) ----------------------------------
-- (dzen) ----------------------------------
 
dzenWith :: XPConfig -> String
getXPositionAndWidthOfScreen :: Int -> IO (Maybe (Int, Int))
dzenWith xpc = -- use XPConfig theming
getXPositionAndWidthOfScreen n = do
     "dzen2 -xs 1 -ta l -h " ++ (show $ height xpc)
    d        <- openDisplay ""
       ++ " -fn '" ++ font    xpc ++ "'"
    screens  <- getScreenInfo d
       ++ " -bg '" ++ bgColor xpc ++ "'"
    let rn = screens!!(min (abs n) (length screens - 1))
       ++ " -fg '" ++ fgColor xpc ++ "'"
    case screens of
        []        -> return Nothing
        [r]      -> return $ Just (fromIntegral $ rect_x r , fromIntegral $ rect_width r)
        otherwise -> return $ Just (fromIntegral $ rect_x rn, fromIntegral $ rect_width rn)
 
-- adjust dzen position & width to screen; use XPConfig theming
dzenWithParamsFrom :: Int -> Int -> XPConfig -> String
dzenWithParamsFrom sx sw xpc =
     "dzen2 -x "  ++ show xpos
      ++ " -w "  ++ show width
      ++ " -h " ++ (show $ height xpc)
       ++ " -fn '" ++ (font    xpc) ++ "'"
       ++ " -bg '" ++ (bgColor xpc) ++ "'"
       ++ " -fg '" ++ (fgColor xpc) ++ "'"
      ++ " -ta l"
      -- normal dzen config --
       ++ " -e 'onstart=lower'"
       ++ " -e 'onstart=lower'"
  where xpos  = sx +      sw * 11 `div` 32        -- a`div`b screenwidth empty to left
        width = sx + sw - sw * 7  `div` 64 - xpos -- and c`div`d to right
                                                  -- (space for .xinіtrc bar and tray)
stripDzen :: String -> String -- strip dzen formatting to undo ppHidden
stripDzen s = aux s []
  where aux [] acc = acc
        aux x  acc = (\(good,bad) -> aux (dropDzen bad) (acc++good)) $ span (/= '^') x
            where dropDzen b = drop 1 $ dropWhile (/= ')') b
            -- dropDzen doesn't properly handle "^^" or non-dzen ')' in text
xpm :: String -> String -> String
xpm path = wrap ("^i(" ++ path ++ "/.dzen/icons/") ".xpm)"


dzdarkPP  hm dzIn = defaultPP
dzdarkPP  hm dzIn = defaultPP
     { ppCurrent        = wrap (dzfg hlightCol  "^p(;+7)^r(5x5)^p(+2;-7)") ""  . dzfg currentCol
     { ppOutput          = hPutStrLn dzIn
     , ppVisible        = dzfg visibleCol . ("^p(;+7)^ro(5x5)^p(+2;-7)" ++)
    , ppCurrent        = wrap (dzfg "#4d5" box) ""  . dzfg "#bca"
     , ppHidden          = dzfg hiddenCol
     , ppVisible        = dzfg "#ab9" . (emptybox ++)
     , ppHiddenNoWindows = dzfg fadedCol
     , ppHidden          = dzfg "#786"
     , ppUrgent          = dzfg urgentCol . (\s -> stripDzen s)
     , ppHiddenNoWindows = dzfg "#554"
     , ppUrgent          = dzfg "#d54" . stripDzen
     , ppWsSep          = kernedsp
     , ppWsSep          = kernedsp
     , ppSep            = ""
     , ppSep            = ""
    , ppSort            = fmap (.scratchpadFilterOutWorkspace) getSortByIndex
     , ppExtras          = [xmonicon]
     , ppExtras          = [xmonicon]
     , ppOrder          = \(ws:_:_:xs) ->  ["    "] ++ [ws] ++ xs
     , ppOrder          = \(ws:_:_:xs) ->  ["    "] ++ [ws] ++ xs
     , ppOutput          = hPutStrLn dzIn
     }
     }
     -- for layouts and titles use something like ppOrder = \(ws:l:t:xs) ->  [l,ws,t] ++ xs
   where kernedsp = "^p(+12)"
   where dzfg c      = dzenColor c ""
         dzfg c  = dzenColor (c dkCols) "" -- (Colorset -> String) -> String -> String
        box = "^p(;+7)^r(5x5)^p(+2;-7)"
        emptybox = "^p(;+7)^ro(5x5)^p(+2;-7)"
        kernedsp   = "^p(+12)"
         xpm path = wrap ("^i(" ++ path ++ ".dzen/icons/") ".xpm)"
         xmonicon = io $ return . Just $
         xmonicon = io $ return . Just $
             kernedsp ++ "^p(;4)" ++ xpm hm "xmonad16" ++ "^p(;-4)" ++ kernedsp
             kernedsp ++ "^p(;4)" ++ xpm hm "xmonad16" ++ "^p(;-4)" ++ kernedsp


    -- for layouts and titles use something like ppOrder = \(ws:l:t:xs) ->  [l,ws,t] ++ xs
stripDzen :: String -> String -- strip dzen formatting to undo ppHidden
stripDzen = strip [] where
    strip keep [] = keep
    strip keep ('^':'^':x) = strip (keep ++ "^") x
    strip keep ('^':x) = strip keep (drop 1 . dropWhile (')' /=) $ x)
    strip keep x = let (good,x') = span ('^' /=) x
        in strip (keep ++ good) x'
</haskell>
</haskell>

Latest revision as of 19:13, 21 February 2010

------ sereven.0.8.base.xmonad.hs ----------------
import XMonad
import qualified XMonad.StackSet as W
import System.Environment (getEnvironment)
import XMonad.Actions.DynamicWorkspaces
import XMonad.Actions.WindowNavigation
import XMonad.Hooks.DynamicLog
import XMonad.Hooks.ManageDocks
import XMonad.Hooks.ManageHelpers (doCenterFloat, isFullscreen, doFullFloat)
import XMonad.Hooks.UrgencyHook
import XMonad.Layout.IM -- (m%n) can be (m/n) don't need Data.Ratio
import XMonad.Layout.LayoutScreens
import XMonad.Layout.NoBorders
import XMonad.Layout.PerWorkspace
import XMonad.Layout.Reflect
import XMonad.Layout.ResizableTile
import XMonad.Layout.ToggleLayouts as TL
import XMonad.Layout.TwoPane
import XMonad.Layout.WindowNavigation
import XMonad.Prompt
import XMonad.Prompt.Shell
import XMonad.Prompt.RunOrRaise
import XMonad.Util.EZConfig
import XMonad.Util.Run
import XMonad.Util.Scratchpad
import XMonad.Util.WorkspaceCompare (getSortByTag,getSortByIndex)

modm = mod4Mask
sWorkspaces = [ [x] | x <- ['A'..'I'] ] -- /3 MINIMUM/ (easy to mod num wss)

ws2 = sWorkspaces !! 1
ws3 = sWorkspaces !! 2

main = do
    dz <- spawnPipe $ dzenWith darkXPC
    home <- fmap (maybe "/home/svv/" (++"/") . lookup "HOME") getEnvironment
    conf <- withWindowNavigation (xK_k, xK_h, xK_j, xK_l) $
            withUrgencyHook NoUrgencyHook $
               defaultConfig
                  { modMask            = modm
                  , focusFollowsMouse  = True
                  , terminal           = "urxvtc"
                  , focusedBorderColor = "#694"
                  , normalBorderColor  = "black"
                  , borderWidth        = 1
                  , workspaces         = sWorkspaces
                  , layoutHook         = sLayouts
                  , logHook            = dynamicLogWithPP $ dzdarkPP home dz
                  , manageHook         = sManageHook
                  }  `additionalKeys` sKeys `additionalKeysP` sKeysP
                     -- silly to use both, but.. meh..
    xmonad conf

sKeys = -- need normal bindings for testing ScreenWorkspaces
    [ ((modm .|. controlMask, xK_space), sendMessage TL.ToggleLayout )
    , ((modm,xK_b)    , sendMessage ToggleStruts)
    , ((shiftMask,xK_F1), shellPrompt darkXPC)
    , ((shiftMask,xK_F2), runOrRaisePrompt darkXPC)
    , ((shiftMask,xK_F3), scratchpadSpawnActionTerminal "urxvt -pe tabbed")

    -- for more screens, workspaces, or exploring ion style subframes
    , ((modm,               xK_backslash), selectWorkspace darkXPC)
    , ((modm .|. shiftMask ,xK_BackSpace), removeWorkspace)
    , ((modm               ,   xK_F8), rescreen)
    , ((modm  .|. shiftMask,   xK_F8), layoutScreens 4 (Tall 2 (1/8) (1/2)))
    ]

sKeysP = -- TODO convert to additionalKeys
    [ ("M-C-k", sendMessage MirrorExpand)
    , ("M-C-j", sendMessage MirrorShrink)
    , ("M-C-h", sendMessage Shrink)
    , ("M-C-l", sendMessage Expand)
    ]
    ++ -- workspace and screen keys ------------------------------------
       -- mod-<key> and mod-shift-<key> are as default
       -- mod-ctrl-<key> shifts focused window *and* view to <key>'s ws
    [ (addtlmods ++ "M-" ++ [key], action tag)
    |   (tag, key)  <- zip sWorkspaces "1234567890_="
      , (addtlmods, action) <- [ ("", windows . W.greedyView) -- or W.view)
                               , ("S-", windows . W.shift)
                               , ("C-", \x -> (windows . W.shift) x >> (windows . W.view) x)]
    ]

sManageHook = composeAll
    [ scratchpadManageHookDefault
    , isFullscreen              --> doFullFloat
    , className =? "Gimp"       --> doShift ws3 -- don't float
    , className =? "MPlayer"    --> doShift ws2
    , title =? "shellfm"        --> doShift ws2

    , title =? ""               --> doFloat     -- SOE graphics
    , title =? "shellfm"        --> doFloat
    , className =? "MPlayer"    --> doFloat
    , className =? "Hback"      --> doCenterFloat
    , className =? "XFontSel"   --> doCenterFloat
    , className =? "Xmessage"   --> doCenterFloat
    ]

sLayouts =
    smartBorders . avoidStruts $
    TL.toggleLayouts (noBorders Full) $
    modWorkspace ws3 reflectHoriz $ withIM (11/64) (Role "gimp-toolbox") $
    onWorkspace  ws2 (TwoPane (1/118) (11/15)) $
    ResizableTall 2         -- default number of masters
                  (1/118)   -- resize increment
                  (11/20)   -- horizontal ratio
                  [5/4 -- master column ~ top/bottom
                  ,5/4 -- no effect w/ 2 masters
                  ,5/4 -- slave  column ~ top/bottom
                  ]    -- then defaults to (repeat 1)

-- (theming, font, colors) ------------------
darkXPC :: XPConfig
darkXPC = defaultXPConfig
      { font = "-*-dejavu sans mono-medium-r-*-*-17-*-*-*-*-*-*-*"
      , height   = 28
      , bgColor  = "black"
      , fgColor  = "#684"
      , bgHLight = "#785"
      , fgHLight = "black"
      , promptBorderWidth = 0
      }

-- (dzen) ----------------------------------
dzenWith :: XPConfig -> String
dzenWith xpc = -- use XPConfig theming
    "dzen2 -xs 1 -ta l -h " ++ (show $ height xpc)
      ++ " -fn '" ++ font    xpc ++ "'"
      ++ " -bg '" ++ bgColor xpc ++ "'"
      ++ " -fg '" ++ fgColor xpc ++ "'"
      ++ " -e 'onstart=lower'"

dzdarkPP  hm dzIn = defaultPP
    { ppOutput          = hPutStrLn dzIn
    , ppCurrent         = wrap (dzfg "#4d5" box) ""  . dzfg "#bca"
    , ppVisible         = dzfg "#ab9" . (emptybox ++)
    , ppHidden          = dzfg "#786"
    , ppHiddenNoWindows = dzfg "#554"
    , ppUrgent          = dzfg "#d54" . stripDzen
    , ppWsSep           = kernedsp
    , ppSep             = ""
    , ppSort            = fmap (.scratchpadFilterOutWorkspace) getSortByIndex
    , ppExtras          = [xmonicon]
    , ppOrder           = \(ws:_:_:xs) ->  ["    "] ++ [ws] ++ xs
    }
    -- for layouts and titles use something like ppOrder = \(ws:l:t:xs) ->  [l,ws,t] ++ xs
  where dzfg c      = dzenColor c ""
        box = "^p(;+7)^r(5x5)^p(+2;-7)"
        emptybox = "^p(;+7)^ro(5x5)^p(+2;-7)"
        kernedsp    = "^p(+12)"
        xpm path = wrap ("^i(" ++ path ++ ".dzen/icons/") ".xpm)"
        xmonicon = io $ return . Just $
            kernedsp ++ "^p(;4)" ++ xpm hm "xmonad16" ++ "^p(;-4)" ++ kernedsp

stripDzen :: String -> String -- strip dzen formatting to undo ppHidden
stripDzen = strip [] where
    strip keep [] = keep
    strip keep ('^':'^':x) = strip (keep ++ "^") x
    strip keep ('^':x) = strip keep (drop 1 . dropWhile (')' /=) $ x)
    strip keep x = let (good,x') = span ('^' /=) x
        in strip (keep ++ good) x'