Personal tools

Xmonad/Config archive/sereven xmonad.hs

From HaskellWiki

< Xmonad | Config archive(Difference between revisions)
Jump to: navigation, search
(Move to page properly named for config download script)
 
m (Update for vi + arrow window navigation)
Line 2: Line 2:
 
{-# OPTIONS_GHC -Wall -fno-warn-missing-signatures #-}
 
{-# OPTIONS_GHC -Wall -fno-warn-missing-signatures #-}
 
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-} -- for TallAlt
 
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-} -- for TallAlt
+
--
-- sereven's xmonad.hs (0.9.2 - 0.10) $ 2011-03-15
+
-- sereven xmonad.hs, 0.9.1 - 0.10 2011-11-02
  +
--
   
 
-- imports {{{
 
-- imports {{{
  +
 
import XMonad hiding (keys)
 
import XMonad hiding (keys)
 
import qualified XMonad.StackSet as W
 
import qualified XMonad.StackSet as W
   
 
-- standard libraries
 
-- standard libraries
import Control.Applicative ((<$>))
+
import Control.Applicative ((<$>)) -- , liftA2)
import Control.Monad (liftM2)
+
import Control.Monad (liftM2, (>=>))
  +
--import Data.List (isPrefixOf, isInfixOf, nub)
 
import Data.List (isPrefixOf, nub)
 
import Data.List (isPrefixOf, nub)
import Data.Maybe (fromMaybe)
+
--import Data.Maybe (fromMaybe)
 
import System.Exit
 
import System.Exit
   
-- xmonad-contrib
+
-- xmonad-contrib (darcs || 0.10)
import XMonad.Actions.CycleWS (swapNextScreen, toggleOrDoSkip, nextWS, prevWS)
+
import XMonad.Actions.CycleWS
 
import XMonad.Actions.FlexibleManipulate as Flex
 
import XMonad.Actions.FlexibleManipulate as Flex
 
import XMonad.Actions.OnScreen (onlyOnScreen)
 
import XMonad.Actions.OnScreen (onlyOnScreen)
import XMonad.Actions.Search hiding (isPrefixOf)
+
import XMonad.Actions.UpdatePointer
 
import XMonad.Actions.WindowNavigation
 
import XMonad.Actions.WindowNavigation
 
import XMonad.Config.Gnome
 
import XMonad.Config.Gnome
import XMonad.Hooks.DynamicLog
+
--import XMonad.Hooks.DynamicLog
 
import XMonad.Hooks.ManageDocks
 
import XMonad.Hooks.ManageDocks
 
import XMonad.Hooks.ManageHelpers
 
import XMonad.Hooks.ManageHelpers
 
import XMonad.Hooks.SetWMName
 
import XMonad.Hooks.SetWMName
import XMonad.Layout.IM
 
 
import XMonad.Layout.LayoutHints
 
import XMonad.Layout.LayoutHints
import XMonad.Layout.LayoutScreens
 
 
import XMonad.Layout.LimitWindows
 
import XMonad.Layout.LimitWindows
 
import XMonad.Layout.NoBorders
 
import XMonad.Layout.NoBorders
 
import XMonad.Layout.PerWorkspace
 
import XMonad.Layout.PerWorkspace
import XMonad.Layout.Reflect (reflectHoriz)
+
import XMonad.Layout.Spacing
 
import XMonad.Layout.ToggleLayouts
 
import XMonad.Layout.ToggleLayouts
 
import XMonad.Layout.WorkspaceDir
 
import XMonad.Layout.WorkspaceDir
Line 39: Line 38:
 
import XMonad.Prompt.RunOrRaise
 
import XMonad.Prompt.RunOrRaise
 
import XMonad.Util.EZConfig
 
import XMonad.Util.EZConfig
import XMonad.Util.Run (hPutStrLn, spawnPipe)
+
--import XMonad.Util.Run (hPutStrLn, spawnPipe)
import XMonad.Util.Scratchpad
+
import XMonad.Util.NamedScratchpad
import XMonad.Util.WorkspaceCompare
+
--import XMonad.Util.WorkspaceCompare
 
-- }}}
 
-- }}}
   
  +
  +
-- Workspace ID list is used all over the place
 
wsIds = map return "123456789" ++ ["NSP"]
 
wsIds = map return "123456789" ++ ["NSP"]
   
infixr 0 ~> -- <http://mauke.ath.cx/stuff/xmonad/xmonad.hs>
+
-- Infix (,) to clean up key and mouse bindings
  +
infixr 0 ~>
 
(~>) :: a -> b -> (a, b)
 
(~>) :: a -> b -> (a, b)
 
(~>) = (,)
 
(~>) = (,)
   
 
-- main {{{
 
-- main {{{
  +
 
main = do
 
main = do
dz <- spawnPipe themedDzen
+
conf <- viAndArrowNav $ -- play nicer with irssi nav
conf <- withNavKeys (xK_k, xK_h, xK_j, xK_l) $
 
 
gnomeConfig
 
gnomeConfig
 
{ terminal = "urxvt"
 
{ terminal = "urxvt"
 
, modMask = mod4Mask
 
, modMask = mod4Mask
, normalBorderColor = bgColor promptConfig
+
, normalBorderColor = fgColor promptConfig
, focusedBorderColor = fgColor promptConfig
+
, focusedBorderColor = bgColor promptConfig
  +
, borderWidth = 2
 
, workspaces = wsIds
 
, workspaces = wsIds
, logHook = dynamicLogWithPP dzPP { ppOutput = hPutStrLn dz }
 
 
, manageHook = manageHooks
 
, manageHook = manageHooks
 
, layoutHook = layouts
 
, layoutHook = layouts
 
}
 
}
 
`additionalKeysP` keys `additionalMouseBindings` buttons
 
`additionalKeysP` keys `additionalMouseBindings` buttons
xmonad conf { startupHook = do
+
xmonad conf
startupHook gnomeConfig
+
{ startupHook = do
checkKeymap conf keys
+
startupHook gnomeConfig
setWMName "LG3D"
+
checkKeymap conf keys
windows $ onlyOnScreen 1 "8"
+
setWMName "LG3D"
}
+
windows $ onlyOnScreen 1 "8"
  +
-- spawn "xcompmgr -Cc -r 3 -l -5 -t -5 &"
  +
, logHook = do
  +
updatePointer $ Relative 0.88 0.88
  +
-- fadeMostInactives 0.89 -- plus xcompmgr
  +
}
  +
where
  +
viAndArrowNav =
  +
withNavKeys (xK_k, xK_h, xK_j, xK_l) >=> withNavKeys (xK_Up, xK_Left, xK_Down, xK_Right)
  +
withNavKeys (u,l,d,r) = withWindowNavigationKeys
  +
[ (mod4Mask , u) ~> WNGo U
  +
, (mod4Mask , l) ~> WNGo L
  +
, (mod4Mask , d) ~> WNGo D
  +
, (mod4Mask , r) ~> WNGo R
  +
, (mod4Mask .|. mod1Mask, u) ~> WNSwap U
  +
, (mod4Mask .|. mod1Mask, l) ~> WNSwap L
  +
, (mod4Mask .|. mod1Mask, d) ~> WNSwap D
  +
, (mod4Mask .|. mod1Mask, r) ~> WNSwap R ]
  +
 
-- }}}
 
-- }}}
   
 
-- keyboard and mouse {{{
 
-- keyboard and mouse {{{
-- uses mod4 on winkey and on capslock via ` Option "XkbOptions" "caps:super" '
 
   
withNavKeys (u,l,d,r) = withWindowNavigationKeys
+
-- Uses mod4 on win key *and* caps lock
[ (mod4Mask , u) ~> WNGo U
+
-- via `Option "XkbOptions" "caps:super"'
, (mod4Mask , l) ~> WNGo L
+
-- Both shift keys pressed together turns on capslock, either one alone turns it off,
, (mod4Mask , d) ~> WNGo D
+
-- via "shift:both_capslock_cancel"
, (mod4Mask , r) ~> WNGo R
 
, (mod4Mask .|. mod1Mask, u) ~> WNSwap U
 
, (mod4Mask .|. mod1Mask, l) ~> WNSwap L
 
, (mod4Mask .|. mod1Mask, d) ~> WNSwap D
 
, (mod4Mask .|. mod1Mask, r) ~> WNSwap R ]
 
   
 
buttons =
 
buttons =
Line 84: Line 84:
 
, (mod4Mask , button4) ~> const $ windows W.swapDown
 
, (mod4Mask , button4) ~> const $ windows W.swapDown
 
, (mod4Mask , button5) ~> const $ windows W.swapUp
 
, (mod4Mask , button5) ~> const $ windows W.swapUp
, (mod1Mask .|. mod4Mask, button4) ~> const nextWS
+
, (mod4Mask .|. mod1Mask, button4) ~> const $ moveTo Next HiddenWS
, (mod1Mask .|. mod4Mask, button5) ~> const prevWS ]
+
, (mod4Mask .|. mod1Mask, button5) ~> const $ moveTo Prev HiddenWS ]
  +
   
keys =
+
keys = --
[ "M-M1-S-q" ~> io (exitWith ExitSuccess)
+
[ "M-C-S-q" ~> io (exitWith ExitSuccess)
, "M-S-q" ~> spawn "xmessage -- [ Shift+Mod1+Mod4+Q to exit; no gnome-session mgr] --"
 
 
, "M-<Space>" ~> sendMessage ToggleLayout -- toggle fullscreen
 
, "M-<Space>" ~> sendMessage ToggleLayout -- toggle fullscreen
 
, "M-c" ~> sendMessage NextLayout
 
, "M-c" ~> sendMessage NextLayout
, "M-M1-." ~> sendMessage Shrink
+
, "M-<Return>" ~> windows W.focusMaster
, "M-M1-," ~> sendMessage Expand
+
, "M-M1-<Return>" ~> windows $ W.focusUp . W.focusMaster
, "M-<F9>" ~> layoutScreens 3 $ fixedLayout
+
, "M-M1-," ~> sendMessage Shrink
[Rectangle 0 0 1600 1200, Rectangle 1600 0 1600 480
+
, "M-M1-." ~> sendMessage Expand
, Rectangle 1600 480 1280 720]
 
, "M-<F8>" ~> rescreen
 
 
]
 
]
-- workspaces and screens -- 1 2 3 \
+
-- workspaces and screens -- 1 2 3 \
-- q w e \
+
-- q w e \
-- a s d \ f g
+
++ -- a s d \ f g
++ -- \ v b
+
[ "M-v" ~> swapNextScreen -- \ v b
[ mask ++ [key] ~> action i
+
, "M-b" ~> toggleWS ]
| (key, i) <- zip "123qweasd=" wsIds
+
-- , "M-b" ~> toggleWS' ["NSP"] ]
  +
++
  +
[ mask ++ [key] ~> action i | (key, i) <- zip "123qweasd=" wsIds
 
, (mask, action) <- [ ("M-", toggled W.greedyView)
 
, (mask, action) <- [ ("M-", toggled W.greedyView)
 
, ("M-M1-", toggled followShift) ] ]
 
, ("M-M1-", toggled followShift) ] ]
 
++
 
++
 
[ mask ++ [key] ~> screenWorkspace s >>= flip whenJust (windows . action)
 
[ mask ++ [key] ~> screenWorkspace s >>= flip whenJust (windows . action)
| (key, s) <- zip "fgb" [0..]
+
| (key, s) <- zip "fg" [0..]
 
, (mask, action) <- [ ("M-", W.view)
 
, (mask, action) <- [ ("M-", W.view)
 
, ("M-M1-", W.shift) ] ]
 
, ("M-M1-", W.shift) ] ]
++
+
++ -- toolbox
[ "M-v" ~> swapNextScreen
+
[ "M-<Tab>" ~> namedScratchpadAction pads "scratch"
-- scratch term, prompts and searches
+
, "M-<F1>" ~> namedScratchpadAction pads "nautilus"
, "M-<Tab>" ~> scratchpadSpawnActionTerminal "urxvt -pe tabbed"
+
, "M-<F2>" ~> namedScratchpadAction pads "cryptote"
, "M-r" ~> runOrRaisePrompt promptConfig
+
, "M-M1-<F2>" ~> namedScratchpadAction pads "keepassx"
, "M-M1-r" ~> changeDir promptConfig ]
+
, "M-<F3>" ~> namedScratchpadAction pads "picard"
++
+
, "M-M1-<F3>" ~> namedScratchpadAction pads "asunder"
[ "M-/ " ++ ks ~> promptSearch promptConfig s | (ks,s) <- searches ]
+
, "M-r" ~> runOrRaisePrompt promptConfig
++
+
, "M-M1-r" ~> changeDir promptConfig
[ "M-M1-/ " ++ ks ~> selectSearch s | (ks,s) <- searches ]
+
]
 
where
 
where
searches = [ ("f" , fgo)
 
, ("r" , rseek)
 
, ("s" , scroogle)
 
, ("x" , xm_gmane)
 
, ("g" , google)
 
, ("i" , images)
 
, ("w" , wikipedia)
 
]
 
fgo = searchEngineF "gentoo forums" $
 
wrap "http://www.google.com/search?q="
 
"+site%3Aforums.gentoo.org+-inurl%3Asearch.php" . escape
 
rseek = searchEngineF "RSeek" $
 
wrap "http://www.rseek.org/?cx=010923144343702598753%3Aboaz1reyxd4&newwindow=1&q="
 
"&sa=Search&cof=FORID%3A11&siteurl=rseek.org%252F#1666" . escape
 
scroogle = searchEngine "scroogle"
 
"https://ssl.scroogle.org/cgi-bin/nbbwssl.cgi?Gw="
 
xm_gmane = searchEngine "xmonad ml"
 
"http://search.gmane.org/?group=gmane.comp.lang.haskell.xmonad&query="
 
 
 
toggled = toggleOrDoSkip ["NSP"]
 
toggled = toggleOrDoSkip ["NSP"]
 
followShift = liftM2 (.) W.view W.shift
 
followShift = liftM2 (.) W.view W.shift
  +
 
-- }}}
 
-- }}}
   
-- manage hook {{{
+
-- scratchpad descriptions - used in key bindings and manageHook {{{
manageHooks = composeAll
+
[ ("OpenOffice" `isPrefixOf`) <$> className --> doShift "3"
+
pads =
, ("Gimp" `isPrefixOf`) <$> className --> doShift "5"
+
[ NS "scratch" "urxvt -pe tabbed -name scratch" (resource =? "scratch") scratchHook
, className =? "Acroread" --> doShift "2"
+
, NS "nautilus" "nautilus --browser --sm-client-disable" (resource =? "nautilus") nautilusHook
, className =? "Qjackctl" --> doFloat
+
, NS "cryptote" "cryptote" (resource =? "cryptote") cryptoteHook
, className =? "feh" --> doFloat
+
, NS "keepassx" "keepassx" (title =? "KeePassX - Password Manager") keepassxHook
, className =? "" --> doFloat -- low budget gtk windows
+
, NS "picard" "picard" (title =? "MusicBrainz Picard") picardHook
, className =? "XFontSel" --> doF W.shiftMaster <+> doCenterFloat
+
, NS "asunder" "asunder" (("Asunder" `isPrefixOf`) <$> title) asunderHook
, className =? "Xmessage" --> doF W.shiftMaster <+> doCenterFloat
 
, isDialog --> doF W.shiftMaster <+> doFloat
 
, scratchpadManageHook (W.RationalRect 0.43 0.575 0.53 0.34)
 
, transience'
 
, manageDocks
 
 
]
 
]
  +
where
  +
scratchHook = doRectFloat $ rr 0.51 0.52 0.46 0.44
  +
nautilusHook = doRectFloat $ rr 0.45 0.19 0.5 0.65
  +
cryptoteHook = doRectFloat $ rr 0.42 0.07 0.48 0.6
  +
keepassxHook = doRectFloat $ rr 0.49 0.03 0.51 0.52
  +
picardHook = doRectFloat $ rr 0.35 0.28 0.64 0.65
  +
asunderHook = doRectFloat $ rr 0.61 0.156 0.3 0.72
  +
rr = W.RationalRect -- in fractions of screen: x y w h
  +
  +
-- }}}
  +
  +
-- manage hook {{{
  +
manageHooks = namedScratchpadManageHook pads <+> composeOne
  +
[ isDialog -?> doF W.shiftMaster <+> doFloat
  +
, ("libreoffice" `isPrefixOf`) <$> className -?> doShift "3"
  +
, ("Gimp" `isPrefixOf`) <$> className -?> doShift "5"
  +
, title =? "Quick Alarm" -?> doF W.shiftMaster <+> doFloat
  +
, role =? "reminderFoxEdit" -?>
  +
doF W.shiftMaster <+> doRectFloat (W.RationalRect 0.15 0.46 0.52 0.432)
  +
, className =? "Gpick" -?> doFloat
  +
, className =? "Wuala" -?> doShift "NSP"
  +
, className =? "Audacity" -?> doShift "9"
  +
, className =? "Firefox" -?> doShift "8"
  +
, isMPlayerFull -?> doShift "6"
  +
, className =? "Apvlv" -?> doShift "2"
  +
, className =? "Xmessage" -?> doF W.shiftMaster <+> doCenterFloat
  +
, className =? "feh" -?> doF W.shiftMaster <+> doFloat
  +
, className =? "" -?> doFloat -- low budget gtk windows
  +
] <+> transience' <+> manageDocks
  +
where
  +
role = stringProperty "WM_WINDOW_ROLE"
  +
isMPlayerFull = (className =? "MPlayer" <&&> appName =? "gl2")
  +
<||> title =? "Gnome MPlayer Fullscreen"
 
-- }}}
 
-- }}}
   
 
-- layouts {{{
 
-- layouts {{{
  +
  +
layouts = modifiers
  +
. onWorkspaces ["1", "4"] (workspaceDir "~" edit)
  +
. onWorkspaces ["2", "3"] (workspaceDir "~/doc" doc)
  +
. onWorkspace "5" (workspaceDir "~/images" edit)
  +
. onWorkspace "7" (workspaceDir "~/.xmonad" edit) $ workspaceDir cwd many
  +
where
  +
cwd = "/e4/av/Music"
  +
modifiers = smartBorders . toggleLayouts (noBorders Full)
  +
. layoutHintsToCenter . spacing 1 . avoidStruts
  +
doc = limitWindows 6 $ TallAlt i 0.5 ||| Mirror (Tall 1 i 0.516)
  +
edit = limitWindows 4 (TallAlt i 0.516) ||| Full
  +
many = Mirror (TallAlt i 0.705) ||| Full ||| Tall 1 i 0.591
  +
i = 0.00125
   
 
-- TallAlt from <http://www.haskell.org/pipermail/xmonad/2009-July/008270.html>
 
-- TallAlt from <http://www.haskell.org/pipermail/xmonad/2009-July/008270.html>
Line 173: Line 202:
 
Shrink -> TallAlt i (d-i)
 
Shrink -> TallAlt i (d-i)
   
-- Note: Workspace dir prompt only works on layouts mod'd by workspaceDir
 
layouts =
 
modifiers . onWorkspaces (take 4 wsIds) (workspaceDir cwd many) . onWorkspace "5" gimp
 
. onWorkspace "7" (workspaceDir "~/.xmonad" four) $ workspaceDir "~" many
 
where
 
modifiers =
 
smartBorders . toggleLayouts (noBorders Full) . layoutHintsToCenter . avoidStruts
 
four = limitWindows 4 . Mirror $ TallAlt 0.03 (31/44) ||| Full
 
gimp = workspaceDir "~/images" . reflectHoriz $ withIM 0.145 (Role "gimp-toolbox") four
 
many = Mirror $ TallAlt 0.03 (31/44) ||| Full ||| Tall 1 0.03 (13/22)
 
cwd = "~/cet_spr/phy/labs"
 
 
-- }}}
 
-- }}}
   
-- prompt and dzen {{{
+
-- prompt {{{
  +
  +
-- solarized color pallette
  +
solbase03 = "#002b36"
  +
solbase02 = "#073642"
  +
solbase01 = "#586e75"
  +
solbase00 = "#657b83"
  +
solbase0 = "#839496"
  +
solbase1 = "#93a1a1"
  +
solbase2 = "#eee8d5"
  +
solbase3 = "#fdf6e3"
  +
solyellow = "#b58900"
  +
solorange = "#cb4b16"
  +
solred = "#dc322f"
  +
solmagenta = "#d33682"
  +
solviolet = "#6c71c4"
  +
solblue = "#268bd2"
  +
solcyan = "#2aa198"
  +
solgreen = "#859900"
   
 
promptConfig = defaultXPConfig
 
promptConfig = defaultXPConfig
{ font = "xft:Denmark:Thin:size=11"
+
{ font = "xft:Consolas:12"
, bgColor = "gray5"
+
, bgColor = solbase03
, fgColor = "wheat3"
+
, fgColor = solbase1
, fgHLight = "DodgerBlue3"
+
-- , fgColor = solbase2
, bgHLight = "black"
+
, bgHLight = solyellow
  +
, fgHLight = solbase02
 
, promptBorderWidth = 0
 
, promptBorderWidth = 0
, height = 24
+
, height = 28
 
, historyFilter = nub
 
, historyFilter = nub
 
, showCompletionOnTab = True
 
, showCompletionOnTab = True
 
}
 
}
   
themedDzen = "dzen2 -xs 1 -x 25 -ta l -e 'onstart=lower'"
 
++ " -bg " ++ "'" ++ bgColor promptConfig ++ "'"
 
++ " -fg " ++ "'" ++ fgColor promptConfig ++ "'"
 
++ " -fn " ++ "'" ++ drop 4 (font promptConfig) ++ "'" -- dzen doesn't use xft prefix
 
++ " -h " ++ show (height promptConfig + 2)
 
 
dzPP = defaultPP
 
{ ppCurrent = \i -> wsColorCurrent i (wrap "|" "|" (wsIcon i)) ++ "^p(6;)"
 
, ppVisible = \i -> wsColorVisible i (wrap "|" "|" (wsIcon i)) ++ "^p(6;)"
 
, ppHidden = fg "wheat4" . wsIcon
 
, ppHiddenNoWindows = fg "gray28" . wsIcon
 
, ppWsSep = "^p(6;)"
 
, ppTitle = take 108 . dzenEscape
 
, ppSep = ""
 
, ppSort = getSortByXineramaRule -- ensure wsIds alphabetical
 
, ppOrder = \(ws:_:t:_) -> ["^p(18;)", ws, "^p(30;).: ", t, " :."]
 
}
 
where
 
fg c = dzenColor c ""
 
wsIcon = wrap "^i(" ")" . ("/home/gvg/.config/dzen/icons/" ++) . wrap "ws-" ".xbm"
 
wsColorCurrent i =
 
fg . fromMaybe "wheat2" . lookup i . zip wsIds $
 
concatMap (replicate 3) ["DarkOrchid1", "DodgerBlue1", "OliveDrab2"]
 
wsColorVisible i =
 
fg . fromMaybe "wheat4" . lookup i . zip wsIds $
 
concatMap (replicate 3) ["DarkOrchid3", "DodgerBlue4", "OliveDrab4"]
 
 
-- }}}
 
-- }}}
   

Revision as of 03:35, 3 October 2011

{-# OPTIONS_GHC -Wall -fno-warn-missing-signatures #-}
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-} -- for TallAlt
--
-- sereven xmonad.hs,  0.9.1 - 0.10  2011-11-02
--
 
-- imports {{{
 
import XMonad hiding (keys)
import qualified XMonad.StackSet as W
 
-- standard libraries
import Control.Applicative ((<$>)) -- , liftA2)
import Control.Monad (liftM2, (>=>))
--import Data.List (isPrefixOf, isInfixOf, nub)
import Data.List (isPrefixOf, nub)
--import Data.Maybe (fromMaybe)
import System.Exit
 
-- xmonad-contrib (darcs || 0.10)
import XMonad.Actions.CycleWS
import XMonad.Actions.FlexibleManipulate as Flex
import XMonad.Actions.OnScreen (onlyOnScreen)
import XMonad.Actions.UpdatePointer
import XMonad.Actions.WindowNavigation
import XMonad.Config.Gnome
--import XMonad.Hooks.DynamicLog
import XMonad.Hooks.ManageDocks
import XMonad.Hooks.ManageHelpers
import XMonad.Hooks.SetWMName
import XMonad.Layout.LayoutHints
import XMonad.Layout.LimitWindows
import XMonad.Layout.NoBorders
import XMonad.Layout.PerWorkspace
import XMonad.Layout.Spacing
import XMonad.Layout.ToggleLayouts
import XMonad.Layout.WorkspaceDir
import XMonad.Prompt
import XMonad.Prompt.RunOrRaise
import XMonad.Util.EZConfig
--import XMonad.Util.Run (hPutStrLn, spawnPipe)
import XMonad.Util.NamedScratchpad
--import XMonad.Util.WorkspaceCompare
-- }}}
 
 
-- Workspace ID list is used all over the place
wsIds = map return "123456789" ++ ["NSP"]
 
-- Infix (,) to clean up key and mouse bindings
infixr 0 ~>
(~>) :: a -> b -> (a, b)
(~>) = (,)
 
-- main {{{
 
main = do
    conf <- viAndArrowNav $ -- play nicer with irssi nav
        gnomeConfig
            { terminal           = "urxvt"
            , modMask            = mod4Mask
            , normalBorderColor  = fgColor promptConfig
            , focusedBorderColor = bgColor promptConfig
            , borderWidth        = 2
            , workspaces         = wsIds
            , manageHook         = manageHooks
            , layoutHook         = layouts
            }
        `additionalKeysP` keys `additionalMouseBindings` buttons
    xmonad conf
        { startupHook = do
            startupHook gnomeConfig
            checkKeymap conf keys
            setWMName "LG3D"
            windows $ onlyOnScreen 1 "8"
--          spawn "xcompmgr -Cc -r 3 -l -5 -t -5 &"
        , logHook = do
            updatePointer $ Relative 0.88 0.88
--          fadeMostInactives 0.89 -- plus xcompmgr
        }
      where
        viAndArrowNav =
            withNavKeys (xK_k, xK_h, xK_j, xK_l) >=> withNavKeys (xK_Up, xK_Left, xK_Down, xK_Right)
        withNavKeys (u,l,d,r) = withWindowNavigationKeys
            [ (mod4Mask             , u) ~> WNGo   U
            , (mod4Mask             , l) ~> WNGo   L
            , (mod4Mask             , d) ~> WNGo   D
            , (mod4Mask             , r) ~> WNGo   R
            , (mod4Mask .|. mod1Mask, u) ~> WNSwap U
            , (mod4Mask .|. mod1Mask, l) ~> WNSwap L
            , (mod4Mask .|. mod1Mask, d) ~> WNSwap D
            , (mod4Mask .|. mod1Mask, r) ~> WNSwap R ]
 
-- }}}
 
-- keyboard and mouse {{{
 
 -- Uses mod4 on win key *and* caps lock
 --     via `Option "XkbOptions" "caps:super"'
 -- Both shift keys pressed together turns on capslock, either one alone turns it off,
 --     via "shift:both_capslock_cancel"
 
buttons =
    [ (mod4Mask             , button3) ~> Flex.mouseWindow Flex.discrete
    , (mod4Mask             , button4) ~> const $ windows W.swapDown
    , (mod4Mask             , button5) ~> const $ windows W.swapUp
    , (mod4Mask .|. mod1Mask, button4) ~> const $ moveTo Next HiddenWS
    , (mod4Mask .|. mod1Mask, button5) ~> const $ moveTo Prev HiddenWS ]
 
 
keys = --
    [ "M-C-S-q"       ~> io (exitWith ExitSuccess)
    , "M-<Space>"     ~> sendMessage ToggleLayout  -- toggle fullscreen
    , "M-c"           ~> sendMessage NextLayout
    , "M-<Return>"    ~> windows W.focusMaster
    , "M-M1-<Return>" ~> windows $ W.focusUp . W.focusMaster
    , "M-M1-,"        ~> sendMessage Shrink
    , "M-M1-."        ~> sendMessage Expand
    ]
    -- workspaces and screens  -- 1 2 3 \
                               --  q w e \
    ++                         --   a s d \ f g
    [ "M-v" ~> swapNextScreen  --          \ v b
    , "M-b" ~> toggleWS ]
--  , "M-b" ~> toggleWS' ["NSP"] ]
    ++
    [ mask ++ [key] ~> action i | (key, i) <- zip "123qweasd=" wsIds
         , (mask, action) <- [ ("M-", toggled W.greedyView)
                             , ("M-M1-", toggled followShift) ] ]
    ++
    [ mask ++ [key] ~> screenWorkspace s >>= flip whenJust (windows . action)
         | (key, s) <- zip "fg" [0..]
         , (mask, action) <- [ ("M-", W.view)
                             , ("M-M1-", W.shift) ] ]
    ++ -- toolbox
    [ "M-<Tab>"   ~> namedScratchpadAction pads "scratch"
    , "M-<F1>"    ~> namedScratchpadAction pads "nautilus"
    , "M-<F2>"    ~> namedScratchpadAction pads "cryptote"
    , "M-M1-<F2>" ~> namedScratchpadAction pads "keepassx"
    , "M-<F3>"    ~> namedScratchpadAction pads "picard"
    , "M-M1-<F3>" ~> namedScratchpadAction pads "asunder"
    , "M-r"       ~> runOrRaisePrompt promptConfig
    , "M-M1-r"    ~> changeDir promptConfig
    ]
  where
    toggled = toggleOrDoSkip ["NSP"]
    followShift = liftM2 (.) W.view W.shift
 
-- }}}
 
-- scratchpad descriptions - used in key bindings and manageHook {{{
 
pads =
    [ NS "scratch" "urxvt -pe tabbed -name scratch" (resource =? "scratch") scratchHook
    , NS "nautilus" "nautilus --browser --sm-client-disable" (resource =? "nautilus") nautilusHook
    , NS "cryptote" "cryptote" (resource =? "cryptote") cryptoteHook
    , NS "keepassx" "keepassx" (title =? "KeePassX - Password Manager") keepassxHook
    , NS "picard" "picard" (title =? "MusicBrainz Picard") picardHook
    , NS "asunder" "asunder" (("Asunder" `isPrefixOf`) <$> title) asunderHook
    ]
  where
    scratchHook  = doRectFloat $ rr 0.51 0.52 0.46 0.44
    nautilusHook = doRectFloat $ rr 0.45 0.19 0.5 0.65
    cryptoteHook = doRectFloat $ rr 0.42 0.07 0.48 0.6
    keepassxHook = doRectFloat $ rr 0.49 0.03 0.51 0.52
    picardHook   = doRectFloat $ rr 0.35 0.28 0.64 0.65
    asunderHook  = doRectFloat $ rr 0.61 0.156 0.3 0.72
    rr = W.RationalRect -- in fractions of screen: x y w h
 
-- }}}
 
-- manage hook {{{
manageHooks = namedScratchpadManageHook pads <+> composeOne
    [ isDialog                -?> doF W.shiftMaster <+> doFloat
    , ("libreoffice" `isPrefixOf`) <$> className -?> doShift "3"
    , ("Gimp"        `isPrefixOf`) <$> className -?> doShift "5"
    , title =? "Quick Alarm"  -?> doF W.shiftMaster <+> doFloat
    , role =? "reminderFoxEdit" -?>
        doF W.shiftMaster <+> doRectFloat (W.RationalRect 0.15 0.46 0.52 0.432)
    , className =? "Gpick"    -?> doFloat
    , className =? "Wuala"    -?> doShift "NSP"
    , className =? "Audacity" -?> doShift "9"
    , className =? "Firefox"  -?> doShift "8"
    , isMPlayerFull           -?> doShift "6"
    , className =? "Apvlv"    -?> doShift "2"
    , className =? "Xmessage" -?> doF W.shiftMaster <+> doCenterFloat
    , className =? "feh"      -?> doF W.shiftMaster <+> doFloat
    , className =? ""         -?> doFloat -- low budget gtk windows
    ] <+> transience' <+> manageDocks
  where
    role = stringProperty "WM_WINDOW_ROLE"
    isMPlayerFull = (className =? "MPlayer" <&&> appName =? "gl2")
                        <||> title =? "Gnome MPlayer Fullscreen"
-- }}}
 
-- layouts {{{
 
layouts = modifiers
            . onWorkspaces ["1", "4"] (workspaceDir "~" edit)
            . onWorkspaces ["2", "3"] (workspaceDir "~/doc" doc)
            . onWorkspace "5" (workspaceDir "~/images" edit)
            . onWorkspace "7" (workspaceDir "~/.xmonad" edit) $ workspaceDir cwd many
  where
    cwd  = "/e4/av/Music"
    modifiers = smartBorders . toggleLayouts (noBorders Full)
        . layoutHintsToCenter . spacing 1 . avoidStruts
    doc = limitWindows 6 $ TallAlt i 0.5 ||| Mirror (Tall 1 i 0.516)
    edit = limitWindows 4 (TallAlt i 0.516) ||| Full
    many = Mirror (TallAlt i 0.705) ||| Full ||| Tall 1 i 0.591
    i = 0.00125
 
-- TallAlt from <http://www.haskell.org/pipermail/xmonad/2009-July/008270.html>
data TallAlt a = TallAlt
    { tallAltIncrement :: !Rational
    , tallAltRatio :: !Rational
    } deriving (Read, Show)
 
instance LayoutClass TallAlt a where
    doLayout (TallAlt i d) r st =
     fmap (\(x,_) -> (x,Nothing)) $ doLayout (Tall nmaster i d) r st
        where nmaster | stlen > 3 = 2
                      | otherwise = 1
              stlen = length $ W.integrate st
    pureMessage (TallAlt i d) m = (`fmap` fromMessage m) $ \x -> case x of
        Expand -> TallAlt i (d+i)
        Shrink -> TallAlt i (d-i)
 
-- }}}
 
-- prompt {{{
 
-- solarized color pallette
solbase03  = "#002b36"
solbase02  = "#073642"
solbase01  = "#586e75"
solbase00  = "#657b83"
solbase0   = "#839496"
solbase1   = "#93a1a1"
solbase2   = "#eee8d5"
solbase3   = "#fdf6e3"
solyellow  = "#b58900"
solorange  = "#cb4b16"
solred     = "#dc322f"
solmagenta = "#d33682"
solviolet  = "#6c71c4"
solblue    = "#268bd2"
solcyan    = "#2aa198"
solgreen   = "#859900"
 
promptConfig = defaultXPConfig
    { font = "xft:Consolas:12"
    , bgColor  = solbase03
    , fgColor  = solbase1
--  , fgColor  = solbase2
    , bgHLight = solyellow
    , fgHLight = solbase02
    , promptBorderWidth = 0
    , height   = 28
    , historyFilter = nub
    , showCompletionOnTab = True
    }
 
-- }}}
 
-- vim:foldmethod=marker