diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) The Xmonad Community
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. Neither the name of the author nor the names of his contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
diff --git a/Setup.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,4 @@
+#!/usr/bin/env runhaskell
+
+> import Distribution.Simple
+> main = defaultMain
diff --git a/XMonad/Actions/Eval.hs b/XMonad/Actions/Eval.hs
new file mode 100644
--- /dev/null
+++ b/XMonad/Actions/Eval.hs
@@ -0,0 +1,98 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  XMonad.Actions.Eval
+-- Copyright   :  (c) 2009 Daniel Schoepe
+-- License     :  BSD3-style (see LICENSE)
+--
+-- Maintainer  :  Daniel Schoepe <daniel.schoepe@gmail.com>
+-- Stability   :  unstable
+-- Portability :  unportable
+--
+-- Evaluate haskell expressions at runtime in the running xmonad instance.
+--
+-----------------------------------------------------------------------------
+
+module XMonad.Actions.Eval (
+                            -- * Usage
+                            -- $usage
+
+                            -- * Documentation
+                            -- $documentation
+
+                             evalExpression
+                           , evalExpressionWithReturn
+                           , EvalConfig(..)
+                           , defaultEvalConfig
+                           ) where
+
+import XMonad.Core
+import XMonad.Util.Run
+import Language.Haskell.Interpreter
+import Control.Monad
+import Data.List
+
+-- $usage
+-- This module provides functions to evaluate haskell expressions at runtime
+-- To use it, bind a key to evalExpression, for example in combination with a prompt:
+--
+-- > import XMonad
+-- > import XMonad.Actions.Eval
+-- > import XMonad.Prompt.Input
+-- > ..
+-- >   , ((modMask,xK_t), inputPrompt defaultXPConfig "Eval" >>= flip whenJust (evalExpression defaultEvalConfig))
+--
+-- For detailed instructions on editing your key bindings, see
+-- "XMonad.Doc.Extending#Editing_key_bindings".
+
+-- $documentation
+
+-- In here due to the apparent lack of a replace function in the standard library.
+-- (Used for correctly displaying newlines in error messages)
+replace :: Eq a => [a] -> [a] -> [a] -> [a]
+replace lst@(x:xs) sub repl | sub `isPrefixOf` lst = repl ++ replace (drop (length sub) lst) sub repl
+                            | otherwise = x:(replace xs sub repl)
+replace _ _ _ = []
+
+-- | Configuration structure
+data EvalConfig = EvalConfig { handleError :: InterpreterError -> X String
+                             -- ^ Function to handle errors
+                             , imports     :: [(ModuleName,Maybe String)]
+                             -- ^ Modules to import for interpreting the expression.
+                             -- The pair consists of the module name and an optional
+                             -- qualification of the imported module.
+                             , modules     :: [String]
+                             -- ^ Other source files that should be loaded
+                             -- The definitions of these modules will be visible
+                             -- regardless of whether they are exported.
+                             }
+
+-- | Defaults for evaluating expressions.
+defaultEvalConfig :: EvalConfig
+defaultEvalConfig = EvalConfig { handleError = handleErrorDefault
+                               , imports = [("Prelude",Nothing),("XMonad",Nothing),
+                                            ("XMonad.StackSet",Just "W"),("XMonad.Core",Nothing)]
+                               , modules = []
+                               }
+
+-- | Default way to handle(in this case: display) an error during interpretation of an expression.
+handleErrorDefault :: InterpreterError -> X String
+handleErrorDefault err = io (safeSpawn "/usr/bin/xmessage" [replace (show err) "\\n" "\n"]) >>
+                         return "Error"
+
+-- | Returns an Interpreter action that loads the desired modules and interprets the expression.
+interpret' :: EvalConfig -> String -> Interpreter (X String)
+interpret' conf s = do
+  loadModules $ modules conf
+  setTopLevelModules =<< getLoadedModules
+  setImportsQ $ imports conf
+  interpret ("show `fmap` ("++s++")") (return "")
+
+-- | Evaluates a given expression whose result type has to be an instance of Show
+evalExpressionWithReturn :: EvalConfig -> String -> X String
+evalExpressionWithReturn conf s = io (runInterpreter $ interpret' conf s) >>=
+                                  either (handleError conf) id
+
+-- | Evaluates a given expression, but discard the returned value. Provided for
+-- more convenient use in keybindings
+evalExpression :: EvalConfig -> String -> X ()
+evalExpression cnf = (>> return ()) . evalExpressionWithReturn cnf
diff --git a/XMonad/Actions/Volume.hs b/XMonad/Actions/Volume.hs
new file mode 100644
--- /dev/null
+++ b/XMonad/Actions/Volume.hs
@@ -0,0 +1,262 @@
+-- boilerplate {{{
+----------------------------------------------------------------------------
+-- |
+-- Module       : XMonad.Actions.Volume
+-- Copyright    : (c) daniel@wagner-home.com
+-- License      : BSD3-style (see LICENSE)
+--
+-- Maintainer   : daniel@wagner-home.com
+-- Stability    : unstable
+-- Portability  : unportable
+--
+-- A minimal interface to the "amixer" command-line utility.
+--
+----------------------------------------------------------------------------
+module XMonad.Actions.Volume (
+    -- * Usage
+    -- $usage
+
+    -- * Common functions
+    toggleMute,
+    raiseVolume,
+    lowerVolume,
+
+    -- * Low-level interface
+    getVolume,
+    getMute,
+    getVolumeMute,
+    setVolume,
+    setMute,
+    setVolumeMute,
+    modifyVolume,
+    modifyMute,
+    modifyVolumeMute,
+
+    -- * Variants that take a list of channels
+    defaultChannels,
+
+    toggleMuteChannels,
+    raiseVolumeChannels,
+    lowerVolumeChannels,
+    getVolumeChannels,
+    getMuteChannels,
+    getVolumeMuteChannels,
+    setVolumeChannels,
+    setMuteChannels,
+    setVolumeMuteChannels,
+    modifyVolumeChannels,
+    modifyMuteChannels,
+    modifyVolumeMuteChannels,
+
+    defaultOSDOpts,
+    osdCat
+) where
+
+import Control.Monad
+import Control.Monad.Trans
+import Data.List.Split (splitOn)
+import Data.Maybe
+import System.IO
+import System.Process
+import Text.ParserCombinators.Parsec
+import XMonad.Core
+
+infixl 1 <*
+(<*) :: Monad m => m a -> m b -> m a
+pa <* pb = pa >>= \a -> pb >> return a
+
+{- $usage
+You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
+
+> import XMonad.Actions.Volume
+
+then add appropriate keybinds to adjust the volume; for example:
+
+> , ((modMask x, xK_F8 ), lowerVolume 3 >> return ())
+> , ((modMask x, xK_F9 ), raiseVolume 3 >> return ())
+> , ((modMask x, xK_F10), toggleMute    >> return ())
+
+For detailed instructions on editing your key bindings, see
+"XMonad.Doc.Extending#Editing_key_bindings".
+-}
+-- }}}
+-- API {{{
+-- | Toggle mutedness on the default channels.  Returns 'True' when this attempts to mute the speakers and 'False' when this attempts to unmute the speakers.
+toggleMute          :: MonadIO m => m Bool
+-- | Raise the volume on the default channels the given number of percentage points.  Returns the volume it attempts to set.
+raiseVolume         :: MonadIO m => Double -> m Double
+-- | Lower the volume on the default channels the given number of percentage points.  Returns the volume it attempts to set.
+lowerVolume         :: MonadIO m => Double -> m Double
+-- | Get the geometric mean of the volumes on the default channels.
+getVolume           :: MonadIO m => m Double
+-- | Get the mutedness of the default channels.  Returns 'True' if any of the channels are muted, and 'False' otherwise.
+getMute             :: MonadIO m => m Bool
+-- | Get both the volume and the mutedness of the default channels.
+getVolumeMute       :: MonadIO m => m (Double, Bool)
+-- | Attempt to set the default channels to a volume given in percentage of maximum.
+setVolume           :: MonadIO m => Double         -> m ()
+-- | Attempt to set the muting on the default channels.
+setMute             :: MonadIO m => Bool           -> m ()
+-- | Attempt to set both the volume in percent and the muting on the default channels.
+setVolumeMute       :: MonadIO m => Double -> Bool -> m ()
+-- | Apply a function to the volume of the default channels, and return the modified value.
+modifyVolume        :: MonadIO m => (Double         -> Double        ) -> m Double
+-- | Apply a function to the muting on the default channels, and return the modified value.
+modifyMute          :: MonadIO m => (Bool           -> Bool          ) -> m Bool
+-- | Apply a function to both the volume and the muting of the default channels, and return the modified values.
+modifyVolumeMute    :: MonadIO m => (Double -> Bool -> (Double, Bool)) -> m (Double, Bool)
+
+toggleMute          = toggleMuteChannels       defaultChannels
+raiseVolume         = raiseVolumeChannels      defaultChannels
+lowerVolume         = lowerVolumeChannels      defaultChannels
+getVolume           = getVolumeChannels        defaultChannels
+getMute             = getMuteChannels          defaultChannels
+getVolumeMute       = getVolumeMuteChannels    defaultChannels
+setVolume           = setVolumeChannels        defaultChannels
+setMute             = setMuteChannels          defaultChannels
+setVolumeMute       = setVolumeMuteChannels    defaultChannels
+modifyVolume        = modifyVolumeChannels     defaultChannels
+modifyMute          = modifyMuteChannels       defaultChannels
+modifyVolumeMute    = modifyVolumeMuteChannels defaultChannels
+
+-- | Channels are what amixer calls \"simple controls\".  The most common ones are \"Master\", \"Wave\", and \"PCM\", so these are included in 'defaultChannels'.  It is guaranteed to be safe to pass channel names that don't exist on the default sound device to the *Channels family of functions.
+defaultChannels :: [String]
+defaultChannels = ["Master", "Wave", "PCM"]
+
+toggleMuteChannels          :: MonadIO m => [String] -> m Bool
+raiseVolumeChannels         :: MonadIO m => [String] -> Double -> m Double
+lowerVolumeChannels         :: MonadIO m => [String] -> Double -> m Double
+getVolumeChannels           :: MonadIO m => [String] -> m Double
+getMuteChannels             :: MonadIO m => [String] -> m Bool
+getVolumeMuteChannels       :: MonadIO m => [String] -> m (Double, Bool)
+setVolumeChannels           :: MonadIO m => [String] -> Double         -> m ()
+setMuteChannels             :: MonadIO m => [String] -> Bool           -> m ()
+setVolumeMuteChannels       :: MonadIO m => [String] -> Double -> Bool -> m ()
+modifyVolumeChannels        :: MonadIO m => [String] -> (Double         -> Double        ) -> m Double
+modifyMuteChannels          :: MonadIO m => [String] -> (Bool           -> Bool          ) -> m Bool
+modifyVolumeMuteChannels    :: MonadIO m => [String] -> (Double -> Bool -> (Double, Bool)) -> m (Double, Bool)
+
+toggleMuteChannels  cs = modifyMuteChannels   cs not
+raiseVolumeChannels cs = modifyVolumeChannels cs . (+)
+lowerVolumeChannels cs = modifyVolumeChannels cs . (subtract)
+
+getVolumeChannels     = liftIO . fmap fst . amixerGetAll
+getMuteChannels       = liftIO . fmap snd . amixerGetAll
+getVolumeMuteChannels = liftIO            . amixerGetAll
+
+setVolumeChannels     cs v   = liftIO (amixerSetVolumeOnlyAll v   cs)
+setMuteChannels       cs   m = liftIO (amixerSetMuteOnlyAll     m cs)
+setVolumeMuteChannels cs v m = liftIO (amixerSetAll           v m cs)
+
+modifyVolumeChannels = modify getVolumeChannels setVolumeChannels
+modifyMuteChannels   = modify getMuteChannels   setMuteChannels
+modifyVolumeMuteChannels cs = modify getVolumeMuteChannels (\cs' -> uncurry (setVolumeMuteChannels cs')) cs . uncurry
+-- }}}
+-- internals {{{
+geomMean :: Floating a => [a] -> a
+geomMean xs = product xs ** (recip . fromIntegral . length $ xs)
+
+clip :: (Num t, Ord t) => t -> t
+clip = min 100 . max 0
+
+modify :: Monad m => (arg -> m value) -> (arg -> value -> m ()) -> arg -> (value -> value) -> m value
+modify get set cs f = do
+    v <- liftM f $ get cs
+    set cs v
+    return v
+
+outputOf :: String -> IO String
+outputOf s = do
+    uninstallSignalHandlers
+    (hIn, hOut, hErr, p) <- runInteractiveCommand s
+    mapM_ hClose [hIn, hErr]
+    hGetContents hOut <* waitForProcess p <* installSignalHandlers
+
+amixerSetAll :: Double -> Bool -> [String] -> IO ()
+amixerSet    :: Double -> Bool ->  String  -> IO String
+amixerGetAll :: [String] -> IO (Double, Bool)
+amixerGet    ::  String  -> IO String
+amixerSetAll    = (mapM_ .) . amixerSet
+amixerSet v m s = outputOf $ "amixer set '" ++ s ++ "' " ++ show (clip v) ++ "% " ++ (if m then "" else "un") ++ "mute"
+amixerGetAll    = fmap parseAmixerGetAll . mapM amixerGet
+amixerGet     s = outputOf $ "amixer get \'" ++ s ++ "\'"
+
+amixerSetVolumeOnlyAll :: Double -> [String] -> IO ()
+amixerSetVolumeOnly    :: Double ->  String  -> IO String
+amixerSetVolumeOnlyAll  = mapM_ . amixerSetVolumeOnly
+amixerSetVolumeOnly v s = outputOf $ "amixer set '" ++ s ++ "' " ++ show (clip v) ++ "% "
+
+amixerSetMuteOnlyAll :: Bool -> [String] -> IO ()
+amixerSetMuteOnly    :: Bool ->  String  -> IO String
+amixerSetMuteOnlyAll  = mapM_ . amixerSetMuteOnly
+amixerSetMuteOnly m s = outputOf $ "amixer set '" ++ s ++ "' " ++ (if m then "" else "un") ++ "mute"
+
+parseAmixerGetAll :: [String] -> (Double, Bool)
+parseAmixerGetAll ss = (geomMean vols, mute) where
+    (vols, mutings)  = unzip [v | Right p <- map (parse amixerGetParser "") ss, v <- p]
+    mute             = or . catMaybes $ mutings
+
+amixerGetParser :: Parser [(Double, Maybe Bool)]
+amixerGetParser = headerLine >> playbackChannels >>= volumes <* eof
+
+headerLine       :: Parser  String
+playbackChannels :: Parser [String]
+volumes          :: [String] -> Parser [(Double, Maybe Bool)]
+headerLine = string "Simple mixer control " >> upTo '\n'
+playbackChannels = keyValueLine >>= \kv -> case kv of
+    ("Playback channels", v) -> return (splitOn " - " v)
+    _                        -> playbackChannels
+volumes channels = fmap concat . many1 $ keyValueLine >>= \kv -> return $ case kv of
+    (k, v) | k `elem` channels -> parseChannel v
+           | otherwise         -> []
+
+upTo         :: Char -> Parser String
+keyValueLine :: Parser (String, String)
+upTo c = many (satisfy (/= c)) <* char c
+keyValueLine = do
+    string "  "
+    key   <- upTo ':'
+    value <- upTo '\n'
+    return (key, drop 1 value)
+
+parseChannel  :: String -> [(Double, Maybe Bool)]
+channelParser :: Parser    [(Double, Maybe Bool)]
+parseChannel  = either (const []) id . parse channelParser ""
+channelParser = fmap catMaybes (many1 playbackOrCapture) <* eof
+
+playbackOrCapture :: Parser (Maybe (Double, Maybe Bool))
+playbackOrCapture = do
+    f <- (string "Playback " >> return Just) <|>
+         (string "Capture "  >> return (const Nothing))
+    many1 digit
+    char ' '
+    es <- extras
+    case filter ('%' `elem`) es of
+        [volume] -> return . f . (,) (read (init volume) :: Double) $ case ("off" `elem` es, "on" `elem` es) of
+            (False, False) -> Nothing
+            (mute, _)      -> Just mute
+        _        -> fail "no percentage-volume found in playback section"
+
+extras :: Parser [String]
+extras = sepBy' (char '[' >> upTo ']') (char ' ')
+
+sepBy' :: Parser a -> Parser b -> Parser [a]
+sepBy' p sep = liftM2 (:) p loop where
+    loop = (sep >> (liftM2 (:) p loop <|> return [])) <|> return []
+
+-- | Helper function to output current volume via osd_cat.(Needs the osd_cat executable).
+-- The second parameter is passed True when the speakers are muted and should
+-- return the options to pass to osd_cat.
+osdCat :: MonadIO m => Double -> (Bool -> String) -> m ()
+osdCat vol opts = do
+  m <- getMute
+  spawn $ "osd_cat -b percentage -P " ++ show (truncate vol :: Integer) ++ opts m
+
+-- | Default options for displaying the volume.
+defaultOSDOpts :: Bool -> String
+defaultOSDOpts mute = "--align=center --pos=top --delay=1 --text=\"Volume" ++
+                      (if mute then "[muted]\" " else "\" ") ++
+                      "--font='-bitstream-bitstream vera sans-bold-r-*-*-10-*-*-*-*-*-*-*' " ++
+                      "--outline=1"
+
+-- }}}
diff --git a/XMonad/Prompt/Eval.hs b/XMonad/Prompt/Eval.hs
new file mode 100644
--- /dev/null
+++ b/XMonad/Prompt/Eval.hs
@@ -0,0 +1,67 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  XMonad.Prompt.Eval
+-- Copyright   :  Daniel Schoepe <daniel.schoepe@gmail.com>
+-- License     :  BSD3
+--
+-- Maintainer  :  Daniel Schoepe <daniel.schoepe@gmail.com>
+-- Stability   :  unstable
+-- Portability :  unportable
+--
+-- A prompt for evaluating Haskell expressions(in the context of the running
+-- xmonad instance).
+--
+-----------------------------------------------------------------------------
+
+module XMonad.Prompt.Eval (
+                          -- * Usage
+                          -- $usage
+                           evalPrompt
+                          ,evalPromptWithOutput
+                          ,showWithDzen
+                          ) where
+
+import XMonad
+import XMonad.Prompt
+import XMonad.Actions.Eval
+import XMonad.Util.Dzen
+
+-- $usage
+-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
+--
+-- > import XMonad.Prompt
+-- > import XMonad.Prompt.Eval
+--
+-- in your keybindings add:
+--
+-- >   , ((modMask x .|. controlMask, xK_x), evalPrompt defaultEvalConfig)
+--
+-- For detailed instruction on editing the key binding see
+-- "XMonad.Doc.Extending#Editing_key_bindings".
+
+data EvalPrompt = EvalPrompt
+
+instance XPrompt EvalPrompt where
+    showXPrompt EvalPrompt = "Eval: "
+
+-- | A prompt that evaluates the entered Haskell expression, whose type has
+-- to be an instance of Show.
+evalPrompt :: EvalConfig -> XPConfig -> X ()
+evalPrompt evc c = evalPromptWithOutput evc c (const $ return ())
+
+-- | The same as 'evalPrompt', but lets the user supply a function to be
+-- executed on the returned string, which is produced by applying show
+-- to the executed expression. (This is a crude solution, but the returned
+-- type has to be monomorphic)
+evalPromptWithOutput :: EvalConfig -> XPConfig -> (String -> X ()) -> X ()
+evalPromptWithOutput evc c f =
+  flip whenJust f =<< mkXPromptWithReturn EvalPrompt c (const $ return []) (evalExpressionWithReturn evc)
+
+-- | A nice default to have the result of an expression displayed by dzen,
+-- if it's interesting (i.e. not () or an empty string).
+-- The first parameter specifies the display time in microseconds, the second parameter
+-- allows to pass additional options to dzen.
+showWithDzen :: Int -> [String] -> String -> X ()
+showWithDzen t args "Error" = dzenWithArgs "Error" (["-bg","#ff0000","-fg","#000000"]++args) t
+showWithDzen t args s | s `elem` ["","()"] = return ()
+                      | otherwise = dzenWithArgs s (["-bg","#00c600","-fg","#000000"]++args) t
diff --git a/XMonad/Prompt/MPD.hs b/XMonad/Prompt/MPD.hs
new file mode 100644
--- /dev/null
+++ b/XMonad/Prompt/MPD.hs
@@ -0,0 +1,94 @@
+{-# LANGUAGE PatternGuards, Rank2Types #-}
+
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  XMonad.Prompt.MPD
+-- Copyright   :  Daniel Schoepe <daniel.schoepe@gmail.com>
+-- License     :  BSD3-style (see LICENSE)
+--
+-- Maintainer  :  Daniel Schoepe <daniel.schoepe@gmail.com>
+-- Stability   :  unstable
+-- Portability :  unportable
+--
+-- This module lets you select songs and add/play songs with MPD by filtering
+-- them by user-supplied criteria(E.g. ask for an artist, then for the album..)
+--
+-----------------------------------------------------------------------------
+
+-- TODO: Add other backends besides mpd(e.g. amarok via dcop).
+
+module XMonad.Prompt.MPD (-- * Usage
+                          -- $usage
+                          findMatching
+                         ,addMatching
+                         ,addAndPlay
+                         ,RunMPD
+                         ,findOrAdd
+                         )  where
+import Control.Monad
+import Control.Applicative
+import Data.Char
+import Network.MPD
+import System.IO
+import XMonad
+import XMonad.Prompt
+import XMonad.Prompt.Input
+import Data.List (nub,isPrefixOf,findIndex)
+
+
+-- $usage
+--
+-- To use this, import the following modules:
+--
+-- > import XMonad.Prompt.MPD
+-- > import qualified Network.MPD as MPD
+--
+-- You can then use this in a keybinding, to filter first by artist, then by album and add 
+-- the matching songs:
+-- 
+-- > addMatching MPD.withMPD defaultXPConfig [MPD.sgArtist, MPD.sgAlbum] >> return ()
+--
+-- If you need a password to connect to your MPD or need a different host/port, you can pass a
+-- partially applied withMPDEx to the function:
+--
+-- > addMatching (MPD.withMPDEx "your.host" 666 (return $ Just $ "password")) ..
+--
+
+-- | Allows the user to supply a custom way to connect to MPD (e.g. partially applied withMPDEx).
+type RunMPD = forall a . MPD a -> IO (Response a)
+
+-- | Creates a case-insensitive completion function from a list.
+mkComplLst :: [String] -> String -> IO [String]
+mkComplLst lst s = return . filter (\s' -> map toLower s `isPrefixOf` map toLower s') $ lst
+
+findMatching' :: XPConfig -> [Song] -> (Song -> String) -> X [Song]
+findMatching' xp s m = do
+  Just input <- inputPromptWithCompl xp "MPD" (mkComplLst . nub . map m $ s)
+  return $ filter ((==input) . m) s
+
+-- | Lets the user filter out non-matching with a prompt by supplied criteria.
+findMatching :: RunMPD -> XPConfig -> [Song -> String] -> X [Song]
+findMatching runMPD xp ms = do
+  -- rs <- io (runMPD $ rights `fmap` listAllInfo "")
+  -- workaround due to a bug in libmpd(reported and fixed in darcs).
+  -- should be replaced by the line above when a new version is released.
+  -- (last version with this bug: 0.3.1)
+  rs <- io . runMPD . fmap concat $ mapM findArtist =<< listArtists
+  case rs of
+    Left e -> io (hPutStrLn stderr $ "MPD error: " ++ show e)  >> return []
+    Right s -> foldM (findMatching' xp) s ms
+
+-- | Determine playlist position of the song and add it, if it isn't present.
+findOrAdd :: Song -> MPD PLIndex
+findOrAdd s = playlistInfo Nothing >>= \pl -> do
+  case findIndex ((== sgFilePath s) . sgFilePath) pl of
+    Just i -> return . Pos . fromIntegral $ i
+    Nothing -> ID <$> (addId . sgFilePath $ s)
+
+-- | Add all selected songs to the playlist if they are not on it.
+addMatching :: RunMPD -> XPConfig -> [Song -> String] -> X [PLIndex]
+addMatching r xp ms = findMatching r xp ms >>= fmap (either (const []) id) . io . r . mapM findOrAdd
+
+-- | Add matching songs and play the first one.
+addAndPlay :: RunMPD -> XPConfig -> [Song -> String] -> X ()
+addAndPlay r xp ms = addMatching r xp ms >>= io . r . play . Just . head >> return ()
diff --git a/xmonad-extras.cabal b/xmonad-extras.cabal
new file mode 100644
--- /dev/null
+++ b/xmonad-extras.cabal
@@ -0,0 +1,71 @@
+name:               xmonad-extras
+version:            0.0
+homepage:           http://projects.haskell.org/xmonad-extras
+synopsis:           Third party extensions for xmonad with wacky dependencies
+category:           System
+license:            BSD3
+license-file:       LICENSE
+author:             The Daniels Schoepe and Wagner
+maintainer:         daniel@wagner-home.com, daniel.schoepe@gmail.com
+cabal-version:      >= 1.2.1
+build-type:         Simple
+
+flag small_base
+  description: Choose the new smaller, split-up base package.
+
+flag with_parsec
+  description: Build modules depending on the parsec package
+
+flag with_split
+  description: Build modules depending on Data.Split
+
+flag with_hint
+  description: Build modules depending on hint(for evaluating Haskell expressions at runtime).
+
+flag with_mpd
+  description: Build modules depending on libmpd.
+
+flag testing
+  description: Testing mode
+  default: False
+
+library
+    if flag(small_base)
+        build-depends: base >= 3 && < 4, containers, directory, process, random, old-time, old-locale
+    else
+        build-depends: base < 3
+
+    build-depends:      mtl, unix, X11>=1.4.3, xmonad>=0.9 && <1.0, xmonad-contrib>=0.9 && <1.0
+    ghc-options:        -Wall
+
+    if flag(testing)
+        ghc-options:    -Werror
+
+    if impl (ghc == 6.10.1) && arch (x86_64)
+        ghc-options:    -O0
+
+    if flag(with_parsec) && flag(with_split)
+        build-depends: parsec, split
+        exposed-modules: XMonad.Actions.Volume
+
+    if flag(with_hint)
+        build-depends: hint, network
+        exposed-modules: XMonad.Actions.Eval XMonad.Prompt.Eval
+--                         XMonad.Hooks.EvalServer
+
+    if flag(with_mpd)
+        build-depends: libmpd
+        exposed-modules: XMonad.Prompt.MPD
+
+-- executable xmonadcmd
+--     main-is: XMonadCmd.hs
+--     build-depends:      mtl, unix, X11>=1.4.3, xmonad>=0.9 && <1.0, xmonad-contrib>=0.9 && <1.0
+--     ghc-options:        -Wall
+--     if !flag(with_hint)
+--         Buildable: False
+-- 
+--     if flag(with_hint)
+--         build-depends: network
+-- 
+--     if flag(testing)
+--         ghc-options:  -Werror
