
[XMonad.Config.Prime, a do-notation for config
me@twifkak.com**20130311094617
 Ignore-this: 8bbccaf7d8673f166ce5bb8dcd418fa2
 Note that the use of RebindableSyntax is because of the need to vary the
 layoutHook type throughout the config. The alternative, using the existential
 Layout type, was rejected because it required TemplateHaskell in order to look
 nice, and TemplateHaskell is not portable.
] {
addfile ./XMonad/Config/Prime.hs
hunk ./XMonad/Config/Prime.hs 1
+{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses #-}
+
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  XMonad.Config.Prime
+-- Copyright   :  Devin Mullins <me@twifkak.com>
+-- License     :  BSD-style (see LICENSE)
+--
+-- Maintainer  :  Devin Mullins <me@twifkak.com>
+-- Stability   :  unstable
+-- Portability :  unportable
+--
+-- This is a draft of a brand new config syntax for xmonad. It aims to be:
+--
+--  * easier to copy/paste snippets from the docs
+--
+--  * easier to get the gist for what's going on, for you imperative programmers
+--
+-- It's brand new, so it's pretty much guaranteed to break or change syntax.
+-- But what's the worst that could happen? Xmonad crashes and logs you out?
+-- It probably won't do that. Give it a try.
+--
+-----------------------------------------------------------------------------
+
+module XMonad.Config.Prime (
+-- Note: The identifiers here are listed in the order that makes the most sense
+-- for a user, while the definitions below are listed in the order that makes
+-- the most sense for a developer.
+
+-- * Start here
+-- $start_here
+xmonad,
+nothing,
+-- * Attributes you can set
+-- $settables
+normalBorderColor,
+focusedBorderColor,
+terminal,
+modMask,
+borderWidth,
+focusFollowsMouse,
+(=:),
+(=.),
+
+-- * Attributes you can add to
+-- $summables
+manageHook,
+handleEventHook,
+workspaces,
+logHook,
+startupHook,
+(=+),
+
+-- * Modifying the keyboard / mouse bindings
+-- $bindings
+addKeys,
+removeKeys,
+addMouseBindings,
+removeMouseBindings,
+keys,
+mouseBindings,
+
+-- * Modifying the layoutHook
+-- $layout
+addLayout,
+resetLayout,
+modifyLayout,
+
+-- * Update entire XConfig
+-- $update
+apply,
+
+-- * The rest of the world
+-- | Everything you know and love from the core "XMonad" module is available
+-- for use in your config file, too.
+module XMonad,
+-- | (Almost) everything you know and love from the Haskell "Prelude" is
+-- available for use in your config file. Note that '>>' and friends have been
+-- overriden, so if you want to create do-blocks for normal monads, you'll need
+-- some let statements or a separate module.
+module Prelude,
+
+-- * Core
+-- | These are the building blocks on which the config language is built.
+-- Regular people shouldn't need to know about these.
+Prime,
+(>>), (>>=), fail,
+Summable,
+(^+),
+
+-- * Example config
+-- $example
+) where
+
+import Prelude hiding ((>>=), (>>), fail)
+import qualified Prelude as P ((>>=), (>>), fail)
+
+import Data.Accessor (accessor, Accessor, (^=), (^:))
+import qualified Data.Map as M
+import Data.Monoid (All, Monoid, mappend)
+
+import XMonad hiding (xmonad, XConfig(..))
+import XMonad (XConfig(XConfig))
+import qualified XMonad as X (xmonad, XConfig(..))
+
+import XMonad.Util.EZConfig (additionalKeysP, additionalMouseBindings, checkKeymap, removeKeysP)
+import qualified XMonad.Util.EZConfig as EZ (removeMouseBindings)
+
+-- $start_here
+-- To start with, have a @~\/.xmonad\/xmonad.hs@ that looks like this:
+--
+-- > {-# LANGUAGE RebindableSyntax #-}
+-- >
+-- > import XMonad.Config.Prime
+-- >
+-- > -- Imports go here.
+-- >
+-- > main = xmonad $ do
+-- >   nothing
+-- >   -- Configs go here.
+--
+-- This will give you a default xmonad install, with room to grow. The lines
+-- starting with double dashes are comments. You may delete them. Note that
+-- Haskell is a bit precise about indentation. Make sure all the statements in
+-- your do-block start at the same column, and make sure that any multi-line
+-- statements are indented further on the subsequent lines. (For an example,
+-- see the 'addKeys' statement in the /Example config/ section, below.)
+
+--
+-- The Prime "Monad"
+--
+
+-- | A Prime is a function that transforms an XConfig. It's not a monad, but we
+-- turn on RebindableSyntax so we can abuse the pretty do notation.
+type Prime l l' = XConfig l -> IO (XConfig l')
+
+-- | Composes two Primes using 'Prelude.>>=' from "Prelude".
+(>>) :: Prime l l' -> Prime l' l'' -> Prime l l''
+(>>) x y c = (P.>>=) (x c) y
+
+-- | An alias to '>>', passing @()@ as the encapsulated value. @y <- x@ syntax
+-- doesn't have any meaning in this config language. Here for completeness.
+(>>=) :: Prime l l' -> (() -> Prime l' l'') -> Prime l l''
+(>>=) x y = x >> y ()
+
+-- | Delegates to the 'Prelude.fail' definition for the 'IO' instance. Here for completeness.
+fail :: String -> Prime l l''
+fail s = const $ P.fail s
+
+-- | This is the xmonad main function. It passes 'defaultConfig' to your
+-- do-block, takes the modified config out of your do-block, and runs xmonad.
+--
+-- The do-block is a 'Prime'. Advanced readers can skip right to that
+-- definition.
+
+-- TODO: Figure out how to type this without hard-coding the defaultConfig layout type.
+xmonad :: (Read (l Window), LayoutClass l Window) =>
+          (XConfig (Choose Tall (Choose (Mirror Tall) Full)) -> IO (XConfig l)) -> IO ()
+xmonad prime = (P.>>=) (prime defaultConfig) X.xmonad
+
+-- | This doesn't modify the config in any way. It's just here for your initial
+-- config because Haskell doesn't allow empty do-blocks. Feel free to delete it
+-- once you've added other stuff.
+nothing :: Prime l l
+nothing = return
+
+-- $settables
+-- These are a bunch of attributes that you can set. Syntax looks like this:
+--
+-- >   terminal =: "urxvt"
+--
+-- Strings are double quoted, Dimensions are unquoted integers, booleans are
+-- 'True' or 'False' (case-sensitive), and 'modMask' is usually 'mod1Mask' or
+-- 'mod4Mask'.
+
+-- | This lets you set an attribute.
+(=:) :: Accessor (XConfig l) x -> x -> Prime l l
+s =: x = return . (s ^= x)
+
+-- | This lets you apply a function to an attribute (i.e. read, modify, write).
+(=.) :: Accessor (XConfig l) x -> (x -> x) -> Prime l l
+s =. f = return . (s ^: f)
+
+-- | Non-focused windows border color. Default: @\"#dddddd\"@
+normalBorderColor  :: Accessor (XConfig l) String
+normalBorderColor = accessor X.normalBorderColor (\x c -> c { X.normalBorderColor = x })
+
+-- | Focused windows border color. Default: @\"#ff0000\"@
+focusedBorderColor :: Accessor (XConfig l) String
+focusedBorderColor = accessor X.focusedBorderColor (\x c -> c { X.focusedBorderColor = x })
+
+-- | The preferred terminal application. Default: @\"xterm\"@
+terminal :: Accessor (XConfig l) String
+terminal = accessor X.terminal (\x c -> c { X.terminal = x })
+
+-- | The mod modifier, as used by key bindings. Default: @mod1Mask@ (which is
+-- probably alt on your computer).
+modMask :: Accessor (XConfig l) KeyMask
+modMask = accessor X.modMask (\x c -> c { X.modMask = x })
+
+-- | The border width (in pixels). Default: @1@
+borderWidth :: Accessor (XConfig l) Dimension
+borderWidth = accessor X.borderWidth (\x c -> c { X.borderWidth = x })
+
+-- | Whether window focus follows the mouse cursor on move, or requires a mouse
+-- click. (Mouse? What's that?) Default: @True@
+focusFollowsMouse :: Accessor (XConfig l) Bool
+focusFollowsMouse = accessor X.focusFollowsMouse (\x c -> c { X.focusFollowsMouse = x })
+
+-- $summables
+-- In addition to being able to set these attributes, they have a special
+-- syntax for being able to add to them. The operator is @=+@ (the plus comes
+-- /after/ the equals), but each attribute has a different syntax for what
+-- comes after the operator.
+
+-- | Any old thing which can accumulate stuff. A monoid without the associativity requirement?
+class Summable x y where
+  (.+.) :: x -> y -> x
+
+-- This covers a suprising number of cases.
+instance Monoid m => Summable m m where
+  (.+.) = mappend
+
+-- | Adds 'y' to the given accessor 'x'.
+(^+) :: Summable x y => Accessor r x -> y -> r -> r
+s ^+ y = s ^: (.+. y)
+infixr 5 ^+
+
+-- | This lets you add to an attribute.
+(=+) :: Summable x y => Accessor (XConfig l) x -> y -> Prime l l
+s =+ y = return . (s ^+ y)
+infix 0 =+
+
+-- | The action to run when a new window is opened. Default:
+--
+-- >   manageHook =: composeAll [className =? "MPlayer" --> doFloat, className =? "Gimp" --> doFloat]
+--
+-- To add more rules to this list, you can say, for instance:
+--
+-- >   manageHook =+ (className =? "Emacs" --> doF . kill =<< ask)
+-- >   manageHook =+ (className =? "Vim" --> doF . shiftMaster =<< ask)
+--
+-- Note that operator precedence mandates the parentheses here.
+manageHook :: Accessor (XConfig l) ManageHook
+manageHook = accessor X.manageHook (\x c -> c { X.manageHook = x })
+
+-- | Custom X event handler. Return @All True@ if the default handler should
+-- also be run afterwards. Default does nothing. To add an event handler:
+--
+-- > import XMonad.Hooks.ServerMode
+-- > ...
+-- >   handleEventHook =+ serverModeEventHook
+handleEventHook :: Accessor (XConfig l) (Event -> X All)
+handleEventHook = accessor X.handleEventHook (\x c -> c { X.handleEventHook = x })
+
+-- | List of workspaces' names. Default: @map show [1 .. 9 :: Int]@. Adding
+-- appends to the end:
+--
+-- >   workspaces =+ ["0"]
+--
+-- This is useless unless you also create keybindings for this.
+workspaces :: Accessor (XConfig l) [String]
+workspaces = accessor X.workspaces (\x c -> c { X.workspaces = x })
+
+-- TODO: Rework the workspaces thing to pair names with keybindings.
+
+-- | The action to perform when the windows set is changed. This happens
+-- whenever focus change, a window is moved, etc. @logHook =+@ takes an @X ()@
+-- and appends it via '(>>)'. For instance:
+--
+-- > import XMonad.Hooks.ICCCMFocus
+-- > ...
+-- >   logHook =+ takeTopFocus
+--
+-- Note that if your expression is parametrically typed (e.g. of type
+-- @MonadIO m => m ()@), you'll need to explicitly annotate it, like so:
+--
+-- >   logHook =+ (io $ putStrLn "Hello, world!" :: X ())
+logHook :: Accessor (XConfig l) (X ())
+logHook = accessor X.logHook (\x c -> c { X.logHook = x })
+
+-- | The action to perform on startup. @startupHook =+@ takes an @X ()@ and
+-- appends it via '(>>)'. For instance:
+--
+-- > import XMonad.Hooks.SetWMName
+-- > ...
+-- >   startupHook =+ setWMName "LG3D"
+--
+-- Note that if your expression is parametrically typed (e.g. of type
+-- @MonadIO m => m ()@), you'll need to explicitly annotate it, as documented
+-- in 'logHook'.
+startupHook :: Accessor (XConfig l) (X ())
+startupHook = accessor X.startupHook (\x c -> c { X.startupHook = x })
+
+-- $bindings
+-- Technically, you can modify 'keys' and 'mouseBindings' using the @=:@ and
+-- @=.@ operators, but you're better off using the following helper functions.
+
+-- | Add a key binding to an 'X' action. Default: see @`man xmonad`@. 'addKeys'
+-- takes a list of keybindings specified emacs-style, as documented in
+-- 'XMonad.Util.EZConfig.mkKeyMap'. For example, to add a help button to
+-- XMonad:
+--
+-- >   addKeys [("<F1>", spawn "echo RTFS | dzen2 -p 2")]
+
+-- Note: Since checkKeymap happens on newKeys, it doesn't check for
+-- duplicates between repeated applications. Probably OK. (Especially since
+-- overriding defaults is a common behavior.)
+-- Also note that there's no reference cycle here. Yay!
+addKeys :: [(String, X ())] -> Prime l l
+addKeys newKeys c = return (c `additionalKeysP` newKeys) { X.startupHook = (P.>>) (X.startupHook c) (checkKeymap c newKeys) }
+
+-- | Remove a key binding. For example, if you accidentally hit mod-shift-q a
+-- lot and would rather @`pkill xmonad`@ to logout:
+--
+-- >   removeKeys ["M-S-q"]
+removeKeys :: [String] -> Prime l l
+removeKeys sadKeys c = return (c `removeKeysP` sadKeys)
+
+-- | Add a mouse button binding to an 'X' action on a window. Default: see @`man
+-- xmonad`@. To make mod-<scrollwheel> switch workspaces:
+--
+-- > import XMonad.Actions.CycleWS (nextWS, prevWS)
+-- > ...
+-- >   addMouseBindings [((mod4Mask, button4), const prevWS),
+-- >                     ((mod4Mask, button5), const nextWS)]
+--
+-- Note that you need to specify the numbered mod-mask e.g. 'mod4Mask' instead
+-- of just 'modMask'.
+addMouseBindings :: [((ButtonMask, Button), Window -> X ())] -> Prime l l
+addMouseBindings newBindings c = return (c `additionalMouseBindings` newBindings)
+
+-- | Remove a mouse button binding. For instance:
+--
+-- >   removeMouseBindings [(mod4Mask, button2)]
+removeMouseBindings :: [(ButtonMask, Button)] -> Prime l l
+removeMouseBindings sadBindings c = return (c `EZ.removeMouseBindings` sadBindings)
+
+-- | The keys accessor, if you want to do it the hard way.
+keys :: Accessor (XConfig l) (XConfig Layout -> M.Map (ButtonMask, KeySym) (X ()))
+keys = accessor X.keys (\x c -> c { X.keys = x })
+
+-- | The mouseBindings accessor, if you want to do it the hard way.
+mouseBindings :: Accessor (XConfig l) (XConfig Layout -> M.Map (ButtonMask, Button) (Window -> X ()))
+mouseBindings = accessor X.mouseBindings (\x c -> c { X.mouseBindings = x })
+
+-- $layout
+-- Layouts are special. You can't modify them using the @=:@ or @=.@ operator.
+-- You need to use the following functions.
+
+-- | Add a layout to the list of layouts choosable with mod-space. For instance:
+--
+-- > import XMonad.Layout.Tabbed
+-- > ...
+-- >   addLayout simpleTabbed
+addLayout :: (LayoutClass l Window, LayoutClass r Window) => r Window -> Prime l (Choose l r)
+addLayout r c = return c { X.layoutHook = X.layoutHook c ||| r }
+
+-- | Reset the layoutHook from scratch. For instance, to get rid of the wide
+-- layout:
+--
+-- >   resetLayout $ Tall 1 (3/100) (1/2) ||| Full
+--
+-- (The dollar is like an auto-closing parenthesis, so all the stuff to the
+-- right of it is treated like an argument to resetLayout.)
+resetLayout :: (LayoutClass r Window) => r Window -> Prime l r
+resetLayout r c = return c { X.layoutHook = r }
+
+-- | Modify your 'layoutHook' with some wrapper function. You probably want to call
+-- this after you're done calling 'addLayout'. Example:
+--
+-- > import XMonad.Layout.NoBorders
+-- > ...
+-- >   modifyLayout smartBorders
+modifyLayout :: (LayoutClass r Window) => (l Window -> r Window) -> Prime l r
+modifyLayout f c = return c { X.layoutHook = f $ X.layoutHook c }
+
+-- $update
+-- Finally, there are a few contrib modules that bundle multiple attribute
+-- updates up into functions that update the entire configuration. There are
+-- two types: those that involve IO and those that don't. The syntax for each
+-- is different.
+--
+-- For instance, 'XMonad.Hooks.UrgencyHook.withUrgencyHook' returns an @XConfig
+-- l@, so we need to use 'apply':
+--
+-- > import XMonad.Hooks.UrgencyHook
+-- > ...
+-- >   apply $ withUrgencyHook dzenUrgencyHook
+--
+-- On the other hand, 'XMonad.Hooks.DynamicLog.xmobar' returns an @IO (XConfig
+-- l)@, so we can include it like so:
+--
+-- > import XMonad.Hooks.DynamicLog
+-- > ...
+-- >   xmobar
+
+-- | Turns a pure function on 'XConfig' into a 'Prime'.
+apply :: (XConfig l -> XConfig l') -> Prime l l'
+apply f = return . f
+
+-- $example
+-- As an example, I've included below a subset of my current config. Note that
+-- my import statements specify individual identifiers in parentheticals.
+-- That's optional. The default is to import the entire module. I just find it
+-- helpful to remind me where things came from.
+--
+-- > {-# LANGUAGE RebindableSyntax #-}
+-- > import XMonad.Config.Prime
+-- >
+-- > import XMonad.Actions.CycleWS (prevWS, nextWS)
+-- > import XMonad.Actions.WindowNavigation (withWindowNavigation)
+-- > import XMonad.Layout.Fullscreen (fullscreenSupport)
+-- > import XMonad.Layout.NoBorders (smartBorders)
+-- > import XMonad.Layout.Tabbed (simpleTabbed)
+-- >
+-- > main = xmonad $ do
+-- >   modMask =: mod4Mask
+-- >   normalBorderColor =: "#222222"
+-- >   terminal =: "urxvt"
+-- >   focusFollowsMouse =: False
+-- >   resetLayout $ Tall 1 (3/100) (1/2) ||| simpleTabbed
+-- >   apply fullscreenSupport
+-- >   modifyLayout smartBorders
+-- >   withWindowNavigation (xK_w, xK_a, xK_s, xK_d)
+-- >   addKeys [
+-- >       ("M-,",                      sendMessage $ IncMasterN (-1)),
+-- >       ("M-.",                      sendMessage $ IncMasterN 1),
+-- >       ("M-M1-d",                   spawn "date | dzen2 -fg '#eeeeee' -p 2"),
+-- >       ("C-S-q",                    return ()),
+-- >       ("<XF86AudioLowerVolume>",   spawn "amixer set Master 5%-"),
+-- >       ("<XF86AudioRaiseVolume>",   spawn "amixer set Master 5%+"),
+-- >       ("M-M1-x",                   kill),
+-- >       ("M-i",                      prevWS),
+-- >       ("M-o",                      nextWS)
+-- >     ]
hunk ./XMonad/Layout/Fullscreen.hs 1
-{-# LANGUAGE DeriveDataTypeable, MultiParamTypeClasses, FlexibleInstances, TypeSynonymInstances #-}
+{-# LANGUAGE DeriveDataTypeable, FlexibleContexts, MultiParamTypeClasses, FlexibleInstances, TypeSynonymInstances #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  XMonad.Layout.Decoration
hunk ./XMonad/Layout/Fullscreen.hs 18
 module XMonad.Layout.Fullscreen
     ( -- * Usage:
       -- $usage
-     fullscreenFull
+     fullscreenSupport
+    ,fullscreenFull
     ,fullscreenFocus
     ,fullscreenFullRect
     ,fullscreenFocusRect
hunk ./XMonad/Layout/Fullscreen.hs 57
 -- To use this module, add 'fullscreenEventHook' and 'fullscreenManageHook'
 -- to your config, i.e.
 --
--- > xmonad defaultconfig { handleEventHook = fullscreenEventHook,
+-- > xmonad defaultConfig { handleEventHook = fullscreenEventHook,
 -- >                        manageHook = fullscreenManageHook,
 -- >                        layoutHook = myLayouts }
 --
hunk ./XMonad/Layout/Fullscreen.hs 67
 -- > myLayouts = fullscreenFull someLayout
 --
 
+-- | Modifies your config to apply basic fullscreen support -- fullscreen
+-- windows when they request it. Example usage:
+--
+-- > main = xmonad
+-- >      $ fullscreenSupport
+-- >      $ defaultConfig { ... }
+fullscreenSupport :: LayoutClass l Window =>
+  XConfig l -> XConfig (ModifiedLayout FullscreenFull l)
+fullscreenSupport c = c {
+    layoutHook = fullscreenFull $ layoutHook c,
+    handleEventHook = handleEventHook c <+> fullscreenEventHook,
+    manageHook = manageHook c <+> fullscreenManageHook
+  }
+
 -- | Messages that control the fullscreen state of the window.
 -- AddFullscreen and RemoveFullscreen are sent to all layouts
 -- when a window wants or no longer wants to be fullscreen.
hunk ./xmonad-contrib.cabal 75
         extensions: ForeignFunctionInterface
         cpp-options: -DXFT
 
-    build-depends:      mtl >= 1 && < 3, unix, X11>=1.6.1 && < 1.7, xmonad>=0.11   && < 0.12, utf8-string
+    build-depends:      mtl >= 1 && < 3, unix, X11 >= 1.6.1 && < 1.7, xmonad >= 0.11 && < 0.12, utf8-string,
+                        data-accessor >= 0.1.2
 
     if true
         ghc-options:    -fwarn-tabs -Wall
hunk ./xmonad-contrib.cabal 158
                         XMonad.Config.Droundy
                         XMonad.Config.Gnome
                         XMonad.Config.Kde
+                        XMonad.Config.Prime
                         XMonad.Config.Sjanssen
                         XMonad.Config.Xfce
                         XMonad.Hooks.CurrentWorkspaceOnTop
}
[X.C.Prime: add support for the 3 newest fields
me@twifkak.com**20130312103606
 Ignore-this: 29a5ef86e811f61ebf4f730ebcdcb97b
 Add support for clickJustFocuses, clientMask, and rootMask. Got rid of the
 ill-behaved Summable class. It may return pending a reworking of the accessors.
] {
hunk ./XMonad/Config/Prime.hs 2
 {-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
 
 -----------------------------------------------------------------------------
 -- |
hunk ./XMonad/Config/Prime.hs 43
 modMask,
 borderWidth,
 focusFollowsMouse,
+clickJustFocuses,
 (=:),
 (=.),
 
hunk ./XMonad/Config/Prime.hs 54
 workspaces,
 logHook,
 startupHook,
+clientMask,
+rootMask,
 (=+),
 
 -- * Modifying the keyboard / mouse bindings
hunk ./XMonad/Config/Prime.hs 92
 -- Regular people shouldn't need to know about these.
 Prime,
 (>>), (>>=), fail,
-Summable,
 (^+),
 
 -- * Example config
hunk ./XMonad/Config/Prime.hs 103
 
 import Data.Accessor (accessor, Accessor, (^=), (^:))
 import qualified Data.Map as M
-import Data.Monoid (All, Monoid, mappend)
+import Data.Monoid (All, Monoid(mempty, mappend))
 
 import XMonad hiding (xmonad, XConfig(..))
 import XMonad (XConfig(XConfig))
hunk ./XMonad/Config/Prime.hs 116
 -- To start with, have a @~\/.xmonad\/xmonad.hs@ that looks like this:
 --
 -- > {-# LANGUAGE RebindableSyntax #-}
--- >
 -- > import XMonad.Config.Prime
 -- >
 -- > -- Imports go here.
hunk ./XMonad/Config/Prime.hs 212
 focusFollowsMouse :: Accessor (XConfig l) Bool
 focusFollowsMouse = accessor X.focusFollowsMouse (\x c -> c { X.focusFollowsMouse = x })
 
+-- | If True, a mouse click on an inactive window focuses it, but the click is
+-- not passed to the window. If False, the click is also passed to the window.
+-- Default @True@
+clickJustFocuses :: Accessor (XConfig l) Bool
+clickJustFocuses = accessor X.clickJustFocuses (\x c -> c { X.clickJustFocuses = x })
+
 -- $summables
 -- In addition to being able to set these attributes, they have a special
 -- syntax for being able to add to them. The operator is @=+@ (the plus comes
hunk ./XMonad/Config/Prime.hs 224
 -- /after/ the equals), but each attribute has a different syntax for what
 -- comes after the operator.
 
--- | Any old thing which can accumulate stuff. A monoid without the associativity requirement?
-class Summable x y where
-  (.+.) :: x -> y -> x
-
--- This covers a suprising number of cases.
-instance Monoid m => Summable m m where
-  (.+.) = mappend
+instance Monoid EventMask where
+  mempty = noEventMask
+  mappend = (.|.)
 
 -- | Adds 'y' to the given accessor 'x'.
hunk ./XMonad/Config/Prime.hs 229
-(^+) :: Summable x y => Accessor r x -> y -> r -> r
-s ^+ y = s ^: (.+. y)
+(^+) :: Monoid x => Accessor r x -> x -> r -> r
+s ^+ y = s ^: (`mappend` y)
 infixr 5 ^+
 
 -- | This lets you add to an attribute.
hunk ./XMonad/Config/Prime.hs 234
-(=+) :: Summable x y => Accessor (XConfig l) x -> y -> Prime l l
+(=+) :: Monoid x => Accessor (XConfig l) x -> x -> Prime l l
 s =+ y = return . (s ^+ y)
 infix 0 =+
 
hunk ./XMonad/Config/Prime.hs 299
 startupHook :: Accessor (XConfig l) (X ())
 startupHook = accessor X.startupHook (\x c -> c { X.startupHook = x })
 
+-- | The client events that xmonad is interested in. This is useful in
+-- combination with handleEventHook. Default: @structureNotifyMask .|.
+-- enterWindowMask .|. propertyChangeMask@
+--
+-- >   clientMask =+ keyPressMask .|. keyReleaseMask
+clientMask :: Accessor (XConfig l) EventMask
+clientMask = accessor X.clientMask (\x c -> c { X.clientMask = x })
+
+-- | The root events that xmonad is interested in. This is useful in
+-- combination with handleEventHook. Default: @substructureRedirectMask .|.
+-- substructureNotifyMask .|. enterWindowMask .|. leaveWindowMask .|.
+-- structureNotifyMask .|. buttonPressMask@
+rootMask :: Accessor (XConfig l) EventMask
+rootMask = accessor X.rootMask (\x c -> c { X.rootMask = x })
+
 -- $bindings
 -- Technically, you can modify 'keys' and 'mouseBindings' using the @=:@ and
 -- @=.@ operators, but you're better off using the following helper functions.
}
[X.C.Prime: reintroduce Summable class (and friends)
me@twifkak.com**20130313073818
 Ignore-this: 74da04f73f00deb2966fabd9aa3a0544
 This time it's a bit more structural, so it no longer misbehaves. Switched
 'addKeys' to 'keys =+', etc.
] {
hunk ./XMonad/Config/Prime.hs 1
-{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses #-}
-{-# OPTIONS_GHC -fno-warn-orphans #-}
+{-# LANGUAGE FlexibleContexts, FlexibleInstances, FunctionalDependencies, KindSignatures, MultiParamTypeClasses, UndecidableInstances #-}
 
 -----------------------------------------------------------------------------
 -- |
hunk ./XMonad/Config/Prime.hs 43
 borderWidth,
 focusFollowsMouse,
 clickJustFocuses,
-(=:),
-(=.),
+SettableClass(..),
+UpdateableClass(..),
 
 -- * Attributes you can add to
 -- $summables
hunk ./XMonad/Config/Prime.hs 55
 startupHook,
 clientMask,
 rootMask,
-(=+),
+SummableClass(..),
 
hunk ./XMonad/Config/Prime.hs 57
--- * Modifying the keyboard / mouse bindings
--- $bindings
-addKeys,
-removeKeys,
-addMouseBindings,
-removeMouseBindings,
+-- * Attributes you can add to or remove from
+-- $removables
 keys,
 mouseBindings,
hunk ./XMonad/Config/Prime.hs 61
+RemovableClass(..),
 
 -- * Modifying the layoutHook
 -- $layout
hunk ./XMonad/Config/Prime.hs 88
 -- Regular people shouldn't need to know about these.
 Prime,
 (>>), (>>=), fail,
-(^+),
 
 -- * Example config
 -- $example
hunk ./XMonad/Config/Prime.hs 96
 import Prelude hiding ((>>=), (>>), fail)
 import qualified Prelude as P ((>>=), (>>), fail)
 
-import Data.Accessor (accessor, Accessor, (^=), (^:))
+import Data.Accessor (accessor, Accessor, (^:))
 import qualified Data.Map as M
hunk ./XMonad/Config/Prime.hs 98
-import Data.Monoid (All, Monoid(mempty, mappend))
+import Data.Monoid (All)
 
 import XMonad hiding (xmonad, XConfig(..))
 import XMonad (XConfig(XConfig))
hunk ./XMonad/Config/Prime.hs 104
 import qualified XMonad as X (xmonad, XConfig(..))
 
-import XMonad.Util.EZConfig (additionalKeysP, additionalMouseBindings, checkKeymap, removeKeysP)
-import qualified XMonad.Util.EZConfig as EZ (removeMouseBindings)
+import XMonad.Util.EZConfig (additionalKeysP, additionalMouseBindings, checkKeymap, mkKeymap, removeKeysP, removeMouseBindings)
 
 -- $start_here
 -- To start with, have a @~\/.xmonad\/xmonad.hs@ that looks like this:
hunk ./XMonad/Config/Prime.hs 142
 (>>=) :: Prime l l' -> (() -> Prime l' l'') -> Prime l l''
 (>>=) x y = x >> y ()
 
--- | Delegates to the 'Prelude.fail' definition for the 'IO' instance. Here for completeness.
+-- | Delegates to the 'Prelude.fail' definition for the 'IO' instance. Here for
+-- completeness.
 fail :: String -> Prime l l''
 fail s = const $ P.fail s
 
hunk ./XMonad/Config/Prime.hs 173
 -- 'True' or 'False' (case-sensitive), and 'modMask' is usually 'mod1Mask' or
 -- 'mod4Mask'.
 
--- | This lets you set an attribute.
-(=:) :: Accessor (XConfig l) x -> x -> Prime l l
-s =: x = return . (s ^= x)
+class UpdateableClass s x y | s -> x y where
+  -- | This lets you apply a function to an attribute (i.e. read, modify, write).
+  (=.) :: s l -> (x -> y) -> Prime l l
 
hunk ./XMonad/Config/Prime.hs 177
--- | This lets you apply a function to an attribute (i.e. read, modify, write).
-(=.) :: Accessor (XConfig l) x -> (x -> x) -> Prime l l
-s =. f = return . (s ^: f)
+class SettableClass s x y | s -> x y where
+  -- | This lets you modify an attribute.
+  (=:) :: s l -> y -> Prime l l
+
+-- Undecideable instance. But it's nice to leave open the possibility to write
+-- fields you can't read (e.g. `wmName =: ...`).
+instance UpdateableClass s x y => SettableClass s x y where
+  s =: y = s =. const y
+
+newtype Settable x l = Settable (Accessor (XConfig l) x) -- ^ getter/setter
+
+instance UpdateableClass (Settable x) x x where
+  Settable s =. f = return . (s ^: f)
+
+settable :: (XConfig l -> x) -> (x -> XConfig l -> XConfig l) -> Settable x l
+settable g s = Settable (accessor g s)
 
 -- | Non-focused windows border color. Default: @\"#dddddd\"@
hunk ./XMonad/Config/Prime.hs 195
-normalBorderColor  :: Accessor (XConfig l) String
-normalBorderColor = accessor X.normalBorderColor (\x c -> c { X.normalBorderColor = x })
+normalBorderColor  :: Settable String l
+normalBorderColor = settable X.normalBorderColor (\x c -> c { X.normalBorderColor = x })
 
 -- | Focused windows border color. Default: @\"#ff0000\"@
hunk ./XMonad/Config/Prime.hs 199
-focusedBorderColor :: Accessor (XConfig l) String
-focusedBorderColor = accessor X.focusedBorderColor (\x c -> c { X.focusedBorderColor = x })
+focusedBorderColor :: Settable String l
+focusedBorderColor = settable X.focusedBorderColor (\x c -> c { X.focusedBorderColor = x })
 
 -- | The preferred terminal application. Default: @\"xterm\"@
hunk ./XMonad/Config/Prime.hs 203
-terminal :: Accessor (XConfig l) String
-terminal = accessor X.terminal (\x c -> c { X.terminal = x })
+terminal :: Settable String l
+terminal = settable X.terminal (\x c -> c { X.terminal = x })
 
 -- | The mod modifier, as used by key bindings. Default: @mod1Mask@ (which is
 -- probably alt on your computer).
hunk ./XMonad/Config/Prime.hs 208
-modMask :: Accessor (XConfig l) KeyMask
-modMask = accessor X.modMask (\x c -> c { X.modMask = x })
+modMask :: Settable KeyMask l
+modMask = settable X.modMask (\x c -> c { X.modMask = x })
 
 -- | The border width (in pixels). Default: @1@
hunk ./XMonad/Config/Prime.hs 212
-borderWidth :: Accessor (XConfig l) Dimension
-borderWidth = accessor X.borderWidth (\x c -> c { X.borderWidth = x })
+borderWidth :: Settable Dimension l
+borderWidth = settable X.borderWidth (\x c -> c { X.borderWidth = x })
 
 -- | Whether window focus follows the mouse cursor on move, or requires a mouse
 -- click. (Mouse? What's that?) Default: @True@
hunk ./XMonad/Config/Prime.hs 217
-focusFollowsMouse :: Accessor (XConfig l) Bool
-focusFollowsMouse = accessor X.focusFollowsMouse (\x c -> c { X.focusFollowsMouse = x })
+focusFollowsMouse :: Settable Bool l
+focusFollowsMouse = settable X.focusFollowsMouse (\x c -> c { X.focusFollowsMouse = x })
 
 -- | If True, a mouse click on an inactive window focuses it, but the click is
 -- not passed to the window. If False, the click is also passed to the window.
hunk ./XMonad/Config/Prime.hs 223
 -- Default @True@
-clickJustFocuses :: Accessor (XConfig l) Bool
-clickJustFocuses = accessor X.clickJustFocuses (\x c -> c { X.clickJustFocuses = x })
+clickJustFocuses :: Settable Bool l
+clickJustFocuses = settable X.clickJustFocuses (\x c -> c { X.clickJustFocuses = x })
 
 -- $summables
 -- In addition to being able to set these attributes, they have a special
hunk ./XMonad/Config/Prime.hs 232
 -- /after/ the equals), but each attribute has a different syntax for what
 -- comes after the operator.
 
-instance Monoid EventMask where
-  mempty = noEventMask
-  mappend = (.|.)
+class SummableClass s y | s -> y where
+  -- | This lets you add to an attribute.
+  (=+) :: s l -> y -> Prime l l
+  infix 0 =+
 
hunk ./XMonad/Config/Prime.hs 237
--- | Adds 'y' to the given accessor 'x'.
-(^+) :: Monoid x => Accessor r x -> x -> r -> r
-s ^+ y = s ^: (`mappend` y)
-infixr 5 ^+
+data Summable x y l = Summable (Accessor (XConfig l) x) -- ^ getter/setter
+                               (x -> y -> x)            -- ^ accumulator
 
hunk ./XMonad/Config/Prime.hs 240
--- | This lets you add to an attribute.
-(=+) :: Monoid x => Accessor (XConfig l) x -> x -> Prime l l
-s =+ y = return . (s ^+ y)
-infix 0 =+
+instance UpdateableClass (Summable x y) x x where
+  Summable s _ =. f = return . (s ^: f)
+
+instance SummableClass (Summable x y) y where
+  Summable s plus =+ y = return . (s ^: (`plus` y))
+
+summable :: (XConfig l -> x) -> (x -> XConfig l -> XConfig l) -> (x -> y -> x) -> Summable x y l
+summable g s a = Summable (accessor g s) a
 
 -- | The action to run when a new window is opened. Default:
 --
hunk ./XMonad/Config/Prime.hs 255
 --
 -- To add more rules to this list, you can say, for instance:
 --
--- >   manageHook =+ (className =? "Emacs" --> doF . kill =<< ask)
--- >   manageHook =+ (className =? "Vim" --> doF . shiftMaster =<< ask)
+-- > import XMonad.StackSet
+-- > ...
+-- >   manageHook =+ (className =? "Emacs" --> doF kill)
+-- >   manageHook =+ (className =? "Vim" --> doF shiftMaster)
 --
 -- Note that operator precedence mandates the parentheses here.
hunk ./XMonad/Config/Prime.hs 261
-manageHook :: Accessor (XConfig l) ManageHook
-manageHook = accessor X.manageHook (\x c -> c { X.manageHook = x })
+manageHook :: Summable ManageHook ManageHook l
+manageHook = summable X.manageHook (\x c -> c { X.manageHook = x }) (<+>)
 
 -- | Custom X event handler. Return @All True@ if the default handler should
 -- also be run afterwards. Default does nothing. To add an event handler:
hunk ./XMonad/Config/Prime.hs 270
 -- > import XMonad.Hooks.ServerMode
 -- > ...
 -- >   handleEventHook =+ serverModeEventHook
-handleEventHook :: Accessor (XConfig l) (Event -> X All)
-handleEventHook = accessor X.handleEventHook (\x c -> c { X.handleEventHook = x })
+handleEventHook :: Summable (Event -> X All) (Event -> X All) l
+handleEventHook = summable X.handleEventHook (\x c -> c { X.handleEventHook = x }) (<+>)
 
 -- | List of workspaces' names. Default: @map show [1 .. 9 :: Int]@. Adding
 -- appends to the end:
hunk ./XMonad/Config/Prime.hs 279
 -- >   workspaces =+ ["0"]
 --
 -- This is useless unless you also create keybindings for this.
-workspaces :: Accessor (XConfig l) [String]
-workspaces = accessor X.workspaces (\x c -> c { X.workspaces = x })
+workspaces :: Summable [String] [String] l
+workspaces = summable X.workspaces (\x c -> c { X.workspaces = x }) (++)
 
 -- TODO: Rework the workspaces thing to pair names with keybindings.
 
hunk ./XMonad/Config/Prime.hs 296
 -- @MonadIO m => m ()@), you'll need to explicitly annotate it, like so:
 --
 -- >   logHook =+ (io $ putStrLn "Hello, world!" :: X ())
-logHook :: Accessor (XConfig l) (X ())
-logHook = accessor X.logHook (\x c -> c { X.logHook = x })
+logHook :: Summable (X ()) (X ()) l
+logHook = summable X.logHook (\x c -> c { X.logHook = x }) (P.>>)
 
 -- | The action to perform on startup. @startupHook =+@ takes an @X ()@ and
 -- appends it via '(>>)'. For instance:
hunk ./XMonad/Config/Prime.hs 309
 -- Note that if your expression is parametrically typed (e.g. of type
 -- @MonadIO m => m ()@), you'll need to explicitly annotate it, as documented
 -- in 'logHook'.
-startupHook :: Accessor (XConfig l) (X ())
-startupHook = accessor X.startupHook (\x c -> c { X.startupHook = x })
+startupHook :: Summable (X ()) (X ()) l
+startupHook = summable X.startupHook (\x c -> c { X.startupHook = x }) (P.>>)
 
 -- | The client events that xmonad is interested in. This is useful in
 -- combination with handleEventHook. Default: @structureNotifyMask .|.
hunk ./XMonad/Config/Prime.hs 317
 -- enterWindowMask .|. propertyChangeMask@
 --
 -- >   clientMask =+ keyPressMask .|. keyReleaseMask
-clientMask :: Accessor (XConfig l) EventMask
-clientMask = accessor X.clientMask (\x c -> c { X.clientMask = x })
+clientMask :: Summable EventMask EventMask l
+clientMask = summable X.clientMask (\x c -> c { X.clientMask = x }) (.|.)
 
 -- | The root events that xmonad is interested in. This is useful in
 -- combination with handleEventHook. Default: @substructureRedirectMask .|.
hunk ./XMonad/Config/Prime.hs 324
 -- substructureNotifyMask .|. enterWindowMask .|. leaveWindowMask .|.
 -- structureNotifyMask .|. buttonPressMask@
-rootMask :: Accessor (XConfig l) EventMask
-rootMask = accessor X.rootMask (\x c -> c { X.rootMask = x })
+rootMask :: Summable EventMask EventMask l
+rootMask = summable X.rootMask (\x c -> c { X.rootMask = x }) (.|.)
 
hunk ./XMonad/Config/Prime.hs 327
--- $bindings
--- Technically, you can modify 'keys' and 'mouseBindings' using the @=:@ and
--- @=.@ operators, but you're better off using the following helper functions.
+-- $removables
+-- The following support the the @=+@ for adding items and the @=-@ operator
+-- for removing items.
 
hunk ./XMonad/Config/Prime.hs 331
--- | Add a key binding to an 'X' action. Default: see @`man xmonad`@. 'addKeys'
--- takes a list of keybindings specified emacs-style, as documented in
--- 'XMonad.Util.EZConfig.mkKeyMap'. For example, to add a help button to
--- XMonad:
---
--- >   addKeys [("<F1>", spawn "echo RTFS | dzen2 -p 2")]
+class RemovableClass r y | r -> y where
+  -- | This lets you remove from an attribute.
+  (=-) :: r l -> y -> Prime l l
+  infix 0 =-
 
hunk ./XMonad/Config/Prime.hs 336
--- Note: Since checkKeymap happens on newKeys, it doesn't check for
+data Keys (l :: * -> *) = Keys
+
+-- Note that since checkKeymap happens on newKeys, it doesn't check for
 -- duplicates between repeated applications. Probably OK. (Especially since
hunk ./XMonad/Config/Prime.hs 340
--- overriding defaults is a common behavior.)
--- Also note that there's no reference cycle here. Yay!
-addKeys :: [(String, X ())] -> Prime l l
-addKeys newKeys c = return (c `additionalKeysP` newKeys) { X.startupHook = (P.>>) (X.startupHook c) (checkKeymap c newKeys) }
+-- overriding defaults is a common behavior.) Also note that there's no
+-- reference cycle here. Yay!
+
+instance UpdateableClass Keys (XConfig Layout -> M.Map (ButtonMask, KeySym) (X ())) [(String, X ())] where
+  (_ =. f) c = return c { X.keys = \c' -> mkKeymap c' newKeys,
+                          X.startupHook = (P.>>) (X.startupHook c) (checkKeymap c newKeys) }
+    where newKeys = f $ X.keys c
 
hunk ./XMonad/Config/Prime.hs 348
--- | Remove a key binding. For example, if you accidentally hit mod-shift-q a
--- lot and would rather @`pkill xmonad`@ to logout:
+instance SummableClass Keys [(String, X ())] where
+  (_ =+ newKeys) c = return (c `additionalKeysP` newKeys) { X.startupHook = (P.>>) (X.startupHook c) (checkKeymap c newKeys) }
+
+instance RemovableClass Keys [String] where
+  (_ =- sadKeys) c = return (c `removeKeysP` sadKeys)
+
+-- | Key bindings to 'X' actions. Default: see @`man xmonad`@. 'keys'
+-- takes a list of keybindings specified emacs-style, as documented in
+-- 'XMonad.Util.EZConfig.mkKeyMap'. For example, to change the "kill window"
+-- key:
 --
hunk ./XMonad/Config/Prime.hs 359
--- >   removeKeys ["M-S-q"]
-removeKeys :: [String] -> Prime l l
-removeKeys sadKeys c = return (c `removeKeysP` sadKeys)
+-- >   keys =- ["M-S-c"]
+-- >   keys =+ [("M-M1-x", kill)]
+keys :: Keys l
+keys = Keys
 
hunk ./XMonad/Config/Prime.hs 364
--- | Add a mouse button binding to an 'X' action on a window. Default: see @`man
+data MouseBindings (l :: * -> *) = MouseBindings
+
+instance SummableClass MouseBindings [((ButtonMask, Button), Window -> X ())] where
+  (_ =+ newBindings) c = return (c `additionalMouseBindings` newBindings)
+
+instance RemovableClass MouseBindings [(ButtonMask, Button)] where
+  (_ =- sadBindings) c = return (c `removeMouseBindings` sadBindings)
+
+
+-- | Mouse button bindings to an 'X' actions on a window. Default: see @`man
 -- xmonad`@. To make mod-<scrollwheel> switch workspaces:
 --
 -- > import XMonad.Actions.CycleWS (nextWS, prevWS)
hunk ./XMonad/Config/Prime.hs 378
 -- > ...
--- >   addMouseBindings [((mod4Mask, button4), const prevWS),
+-- >   mouseBindings =+ [((mod4Mask, button4), const prevWS),
 -- >                     ((mod4Mask, button5), const nextWS)]
 --
 -- Note that you need to specify the numbered mod-mask e.g. 'mod4Mask' instead
hunk ./XMonad/Config/Prime.hs 383
 -- of just 'modMask'.
-addMouseBindings :: [((ButtonMask, Button), Window -> X ())] -> Prime l l
-addMouseBindings newBindings c = return (c `additionalMouseBindings` newBindings)
-
--- | Remove a mouse button binding. For instance:
---
--- >   removeMouseBindings [(mod4Mask, button2)]
-removeMouseBindings :: [(ButtonMask, Button)] -> Prime l l
-removeMouseBindings sadBindings c = return (c `EZ.removeMouseBindings` sadBindings)
-
--- | The keys accessor, if you want to do it the hard way.
-keys :: Accessor (XConfig l) (XConfig Layout -> M.Map (ButtonMask, KeySym) (X ()))
-keys = accessor X.keys (\x c -> c { X.keys = x })
-
--- | The mouseBindings accessor, if you want to do it the hard way.
-mouseBindings :: Accessor (XConfig l) (XConfig Layout -> M.Map (ButtonMask, Button) (Window -> X ()))
-mouseBindings = accessor X.mouseBindings (\x c -> c { X.mouseBindings = x })
+mouseBindings :: MouseBindings l
+mouseBindings = MouseBindings
 
 -- $layout
 -- Layouts are special. You can't modify them using the @=:@ or @=.@ operator.
hunk ./XMonad/Config/Prime.hs 465
 -- >   apply fullscreenSupport
 -- >   modifyLayout smartBorders
 -- >   withWindowNavigation (xK_w, xK_a, xK_s, xK_d)
--- >   addKeys [
+-- >   keys =+ [
 -- >       ("M-,",                      sendMessage $ IncMasterN (-1)),
 -- >       ("M-.",                      sendMessage $ IncMasterN 1),
 -- >       ("M-M1-d",                   spawn "date | dzen2 -fg '#eeeeee' -p 2"),
}
[X.C.Prime: add startWith (e.g. for gnomeConfig)
me@twifkak.com**20130313074113
 Ignore-this: dafc7c22e34dbe7df67bc840581a9221
] {
hunk ./XMonad/Config/Prime.hs 71
 
 -- * Update entire XConfig
 -- $update
+startWith,
 apply,
 
 -- * The rest of the world
hunk ./XMonad/Config/Prime.hs 420
 
 -- $update
 -- Finally, there are a few contrib modules that bundle multiple attribute
--- updates up into functions that update the entire configuration. There are
--- two types: those that involve IO and those that don't. The syntax for each
--- is different.
+-- updates together. There are three types: 1) wholesale replacements for the
+-- default config, 2) pure functions on the config, and 3) IO actions on the
+-- config. The syntax for each is different. Examples:
 --
hunk ./XMonad/Config/Prime.hs 424
--- For instance, 'XMonad.Hooks.UrgencyHook.withUrgencyHook' returns an @XConfig
--- l@, so we need to use 'apply':
+-- 1) To start with a 'XMonad.Config.Gnome.gnomeConfig' instead of the default,
+-- we use 'startWith':
+--
+-- > import XMonad.Config.Gnome
+-- > ...
+-- >   startWith gnomeConfig
+--
+-- 2) 'XMonad.Hooks.UrgencyHook.withUrgencyHook' is a pure function, so we need
+-- to use 'apply':
 --
 -- > import XMonad.Hooks.UrgencyHook
 -- > ...
hunk ./XMonad/Config/Prime.hs 438
 -- >   apply $ withUrgencyHook dzenUrgencyHook
 --
--- On the other hand, 'XMonad.Hooks.DynamicLog.xmobar' returns an @IO (XConfig
--- l)@, so we can include it like so:
+-- 3) 'XMonad.Hooks.DynamicLog.xmobar' returns an @IO (XConfig l)@, so we can
+-- include it like so:
 --
 -- > import XMonad.Hooks.DynamicLog
 -- > ...
hunk ./XMonad/Config/Prime.hs 445
 -- >   xmobar
 
+-- | Replace the current 'XConfig' with the given one. If you use this, you
+-- probably want it to be the first line of your config.
+startWith :: XConfig l' -> Prime l l'
+startWith = const . return
+
 -- | Turns a pure function on 'XConfig' into a 'Prime'.
 apply :: (XConfig l -> XConfig l') -> Prime l l'
 apply f = return . f
hunk ./XMonad/Config/Prime.hs 475
 -- >   terminal =: "urxvt"
 -- >   focusFollowsMouse =: False
 -- >   resetLayout $ Tall 1 (3/100) (1/2) ||| simpleTabbed
--- >   apply fullscreenSupport
 -- >   modifyLayout smartBorders
hunk ./XMonad/Config/Prime.hs 476
+-- >   apply fullscreenSupport
 -- >   withWindowNavigation (xK_w, xK_a, xK_s, xK_d)
 -- >   keys =+ [
 -- >       ("M-,",                      sendMessage $ IncMasterN (-1)),
}
[X.C.Prime: add 'applyIO' for some future flexibility
me@twifkak.com**20130313075043
 Ignore-this: 9c88011ee6aed9a244cf1168e389c7b7
] {
hunk ./XMonad/Config/Prime.hs 73
 -- $update
 startWith,
 apply,
+applyIO,
 
 -- * The rest of the world
 -- | Everything you know and love from the core "XMonad" module is available
hunk ./XMonad/Config/Prime.hs 439
 -- > ...
 -- >   apply $ withUrgencyHook dzenUrgencyHook
 --
--- 3) 'XMonad.Hooks.DynamicLog.xmobar' returns an @IO (XConfig l)@, so we can
--- include it like so:
+-- 3) 'XMonad.Hooks.DynamicLog.xmobar' returns an @IO (XConfig l)@, so we need
+-- to use 'applyIO':
 --
 -- > import XMonad.Hooks.DynamicLog
 -- > ...
hunk ./XMonad/Config/Prime.hs 444
--- >   xmobar
+-- >   applyIO xmobar
 
 -- | Replace the current 'XConfig' with the given one. If you use this, you
 -- probably want it to be the first line of your config.
hunk ./XMonad/Config/Prime.hs 455
 apply :: (XConfig l -> XConfig l') -> Prime l l'
 apply f = return . f
 
+-- | Turns an IO function on 'XConfig' into a 'Prime'.
+applyIO :: (XConfig l -> IO (XConfig l')) -> Prime l l'
+applyIO = id  -- This is here in case we want to change the Prime type later.
+
 -- $example
 -- As an example, I've included below a subset of my current config. Note that
 -- my import statements specify individual identifiers in parentheticals.
hunk ./XMonad/Config/Prime.hs 482
 -- >   resetLayout $ Tall 1 (3/100) (1/2) ||| simpleTabbed
 -- >   modifyLayout smartBorders
 -- >   apply fullscreenSupport
--- >   withWindowNavigation (xK_w, xK_a, xK_s, xK_d)
+-- >   applyIO $ withWindowNavigation (xK_w, xK_a, xK_s, xK_d)
 -- >   keys =+ [
 -- >       ("M-,",                      sendMessage $ IncMasterN (-1)),
 -- >       ("M-.",                      sendMessage $ IncMasterN 1),
}
[X.C.Prime: get rid of the data-accessor dependency
me@twifkak.com**20130313081529
 Ignore-this: ae6727a93188fd99b02b20b7db80d839
 The previous patch nearly obviated the library. This one does so completely.
] {
hunk ./XMonad/Config/Prime.hs 98
 import Prelude hiding ((>>=), (>>), fail)
 import qualified Prelude as P ((>>=), (>>), fail)
 
-import Data.Accessor (accessor, Accessor, (^:))
 import qualified Data.Map as M
 import Data.Monoid (All)
 
hunk ./XMonad/Config/Prime.hs 187
 instance UpdateableClass s x y => SettableClass s x y where
   s =: y = s =. const y
 
-newtype Settable x l = Settable (Accessor (XConfig l) x) -- ^ getter/setter
+data Settable x l = Settable (XConfig l -> x)              -- ^ getter
+                             (x -> XConfig l -> XConfig l) -- ^ setter
 
 instance UpdateableClass (Settable x) x x where
hunk ./XMonad/Config/Prime.hs 191
-  Settable s =. f = return . (s ^: f)
-
-settable :: (XConfig l -> x) -> (x -> XConfig l -> XConfig l) -> Settable x l
-settable g s = Settable (accessor g s)
+  (Settable g s =. f) c = return $ s (f $ g c) c
 
 -- | Non-focused windows border color. Default: @\"#dddddd\"@
 normalBorderColor  :: Settable String l
hunk ./XMonad/Config/Prime.hs 195
-normalBorderColor = settable X.normalBorderColor (\x c -> c { X.normalBorderColor = x })
+normalBorderColor = Settable X.normalBorderColor (\x c -> c { X.normalBorderColor = x })
 
 -- | Focused windows border color. Default: @\"#ff0000\"@
 focusedBorderColor :: Settable String l
hunk ./XMonad/Config/Prime.hs 199
-focusedBorderColor = settable X.focusedBorderColor (\x c -> c { X.focusedBorderColor = x })
+focusedBorderColor = Settable X.focusedBorderColor (\x c -> c { X.focusedBorderColor = x })
 
 -- | The preferred terminal application. Default: @\"xterm\"@
 terminal :: Settable String l
hunk ./XMonad/Config/Prime.hs 203
-terminal = settable X.terminal (\x c -> c { X.terminal = x })
+terminal = Settable X.terminal (\x c -> c { X.terminal = x })
 
 -- | The mod modifier, as used by key bindings. Default: @mod1Mask@ (which is
 -- probably alt on your computer).
hunk ./XMonad/Config/Prime.hs 208
 modMask :: Settable KeyMask l
-modMask = settable X.modMask (\x c -> c { X.modMask = x })
+modMask = Settable X.modMask (\x c -> c { X.modMask = x })
 
 -- | The border width (in pixels). Default: @1@
 borderWidth :: Settable Dimension l
hunk ./XMonad/Config/Prime.hs 212
-borderWidth = settable X.borderWidth (\x c -> c { X.borderWidth = x })
+borderWidth = Settable X.borderWidth (\x c -> c { X.borderWidth = x })
 
 -- | Whether window focus follows the mouse cursor on move, or requires a mouse
 -- click. (Mouse? What's that?) Default: @True@
hunk ./XMonad/Config/Prime.hs 217
 focusFollowsMouse :: Settable Bool l
-focusFollowsMouse = settable X.focusFollowsMouse (\x c -> c { X.focusFollowsMouse = x })
+focusFollowsMouse = Settable X.focusFollowsMouse (\x c -> c { X.focusFollowsMouse = x })
 
 -- | If True, a mouse click on an inactive window focuses it, but the click is
 -- not passed to the window. If False, the click is also passed to the window.
hunk ./XMonad/Config/Prime.hs 223
 -- Default @True@
 clickJustFocuses :: Settable Bool l
-clickJustFocuses = settable X.clickJustFocuses (\x c -> c { X.clickJustFocuses = x })
+clickJustFocuses = Settable X.clickJustFocuses (\x c -> c { X.clickJustFocuses = x })
 
 -- $summables
 -- In addition to being able to set these attributes, they have a special
hunk ./XMonad/Config/Prime.hs 236
   (=+) :: s l -> y -> Prime l l
   infix 0 =+
 
-data Summable x y l = Summable (Accessor (XConfig l) x) -- ^ getter/setter
-                               (x -> y -> x)            -- ^ accumulator
+data Summable x y l = Summable (XConfig l -> x)              -- ^ getter
+                               (x -> XConfig l -> XConfig l) -- ^ setter
+                               (x -> y -> x)                 -- ^ accumulator
 
 instance UpdateableClass (Summable x y) x x where
hunk ./XMonad/Config/Prime.hs 241
-  Summable s _ =. f = return . (s ^: f)
+  (Summable g s _ =. f) c = return $ s (f $ g c) c
 
 instance SummableClass (Summable x y) y where
hunk ./XMonad/Config/Prime.hs 244
-  Summable s plus =+ y = return . (s ^: (`plus` y))
-
-summable :: (XConfig l -> x) -> (x -> XConfig l -> XConfig l) -> (x -> y -> x) -> Summable x y l
-summable g s a = Summable (accessor g s) a
+  (Summable g s a =+ y) c = return $ s (g c `a` y) c
 
 -- | The action to run when a new window is opened. Default:
 --
hunk ./XMonad/Config/Prime.hs 259
 --
 -- Note that operator precedence mandates the parentheses here.
 manageHook :: Summable ManageHook ManageHook l
-manageHook = summable X.manageHook (\x c -> c { X.manageHook = x }) (<+>)
+manageHook = Summable X.manageHook (\x c -> c { X.manageHook = x }) (<+>)
 
 -- | Custom X event handler. Return @All True@ if the default handler should
 -- also be run afterwards. Default does nothing. To add an event handler:
hunk ./XMonad/Config/Prime.hs 268
 -- > ...
 -- >   handleEventHook =+ serverModeEventHook
 handleEventHook :: Summable (Event -> X All) (Event -> X All) l
-handleEventHook = summable X.handleEventHook (\x c -> c { X.handleEventHook = x }) (<+>)
+handleEventHook = Summable X.handleEventHook (\x c -> c { X.handleEventHook = x }) (<+>)
 
 -- | List of workspaces' names. Default: @map show [1 .. 9 :: Int]@. Adding
 -- appends to the end:
hunk ./XMonad/Config/Prime.hs 277
 --
 -- This is useless unless you also create keybindings for this.
 workspaces :: Summable [String] [String] l
-workspaces = summable X.workspaces (\x c -> c { X.workspaces = x }) (++)
+workspaces = Summable X.workspaces (\x c -> c { X.workspaces = x }) (++)
 
 -- TODO: Rework the workspaces thing to pair names with keybindings.
 
hunk ./XMonad/Config/Prime.hs 294
 --
 -- >   logHook =+ (io $ putStrLn "Hello, world!" :: X ())
 logHook :: Summable (X ()) (X ()) l
-logHook = summable X.logHook (\x c -> c { X.logHook = x }) (P.>>)
+logHook = Summable X.logHook (\x c -> c { X.logHook = x }) (P.>>)
 
 -- | The action to perform on startup. @startupHook =+@ takes an @X ()@ and
 -- appends it via '(>>)'. For instance:
hunk ./XMonad/Config/Prime.hs 307
 -- @MonadIO m => m ()@), you'll need to explicitly annotate it, as documented
 -- in 'logHook'.
 startupHook :: Summable (X ()) (X ()) l
-startupHook = summable X.startupHook (\x c -> c { X.startupHook = x }) (P.>>)
+startupHook = Summable X.startupHook (\x c -> c { X.startupHook = x }) (P.>>)
 
 -- | The client events that xmonad is interested in. This is useful in
 -- combination with handleEventHook. Default: @structureNotifyMask .|.
hunk ./XMonad/Config/Prime.hs 315
 --
 -- >   clientMask =+ keyPressMask .|. keyReleaseMask
 clientMask :: Summable EventMask EventMask l
-clientMask = summable X.clientMask (\x c -> c { X.clientMask = x }) (.|.)
+clientMask = Summable X.clientMask (\x c -> c { X.clientMask = x }) (.|.)
 
 -- | The root events that xmonad is interested in. This is useful in
 -- combination with handleEventHook. Default: @substructureRedirectMask .|.
hunk ./XMonad/Config/Prime.hs 322
 -- substructureNotifyMask .|. enterWindowMask .|. leaveWindowMask .|.
 -- structureNotifyMask .|. buttonPressMask@
 rootMask :: Summable EventMask EventMask l
-rootMask = summable X.rootMask (\x c -> c { X.rootMask = x }) (.|.)
+rootMask = Summable X.rootMask (\x c -> c { X.rootMask = x }) (.|.)
 
 -- $removables
 -- The following support the the @=+@ for adding items and the @=-@ operator
hunk ./XMonad/Config/Prime.hs 369
 instance RemovableClass MouseBindings [(ButtonMask, Button)] where
   (_ =- sadBindings) c = return (c `removeMouseBindings` sadBindings)
 
-
 -- | Mouse button bindings to an 'X' actions on a window. Default: see @`man
 -- xmonad`@. To make mod-<scrollwheel> switch workspaces:
 --
hunk ./xmonad-contrib.cabal 75
         extensions: ForeignFunctionInterface
         cpp-options: -DXFT
 
-    build-depends:      mtl >= 1 && < 3, unix, X11 >= 1.6.1 && < 1.7, xmonad >= 0.11 && < 0.12, utf8-string,
-                        data-accessor >= 0.1.2
+    build-depends:      mtl >= 1 && < 3, unix, X11 >= 1.6.1 && < 1.7, xmonad >= 0.11 && < 0.12, utf8-string
 
     if true
         ghc-options:    -fwarn-tabs -Wall
}
[X.C.Prime: fix haddock errors
me@twifkak.com**20130313084850
 Ignore-this: bfdbbe4004d4926f03e5c7f9bef2704b
] {
hunk ./XMonad/Config/Prime.hs 187
 instance UpdateableClass s x y => SettableClass s x y where
   s =: y = s =. const y
 
-data Settable x l = Settable (XConfig l -> x)              -- ^ getter
-                             (x -> XConfig l -> XConfig l) -- ^ setter
+data Settable x l = Settable (XConfig l -> x)              -- getter
+                             (x -> XConfig l -> XConfig l) -- setter
 
 instance UpdateableClass (Settable x) x x where
   (Settable g s =. f) c = return $ s (f $ g c) c
hunk ./XMonad/Config/Prime.hs 236
   (=+) :: s l -> y -> Prime l l
   infix 0 =+
 
-data Summable x y l = Summable (XConfig l -> x)              -- ^ getter
-                               (x -> XConfig l -> XConfig l) -- ^ setter
-                               (x -> y -> x)                 -- ^ accumulator
+data Summable x y l = Summable (XConfig l -> x)              -- getter
+                               (x -> XConfig l -> XConfig l) -- setter
+                               (x -> y -> x)                 -- accumulator
 
 instance UpdateableClass (Summable x y) x x where
   (Summable g s _ =. f) c = return $ s (f $ g c) c
}

