----------------------------------------------------------------------------- -- | -- Module : XMonad.Actions.Commands -- Copyright : (c) David Glasser 2007 -- License : BSD3 -- -- Maintainer : glasser@mit.edu -- Stability : stable -- Portability : portable -- -- Allows you to run internal xmonad commands (X () actions) using -- a dmenu menu in addition to key bindings. Requires dmenu and -- the Dmenu XMonad.Actions module. -- ----------------------------------------------------------------------------- module XMonad.Actions.Commands ( -- * Usage -- $usage commandMap, runCommand, runCommand', workspaceCommands, screenCommands, defaultCommands ) where import XMonad import XMonad.StackSet hiding (workspaces) import XMonad.Util.Dmenu (dmenu) import qualified Data.Map as M import System.Exit import Data.Maybe -- $usage -- -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@: -- -- > import XMonad.Actions.Commands -- -- Then add a keybinding to the runCommand action: -- -- > , ((modm .|. controlMask, xK_y), commands >>= runCommand) -- -- and define the list of commands you want to use: -- -- > commands :: X [(String, X ())] -- > commands = defaultCommands -- -- Whatever key you bound to will now cause a popup menu of internal -- xmonad commands to appear. You can change the commands by changing -- the contents of the list returned by 'commands'. (If you like it -- enough, you may even want to get rid of many of your other key -- bindings!) -- -- For detailed instructions on editing your key bindings, see -- "XMonad.Doc.Extending#Editing_key_bindings". -- | Create a 'Data.Map.Map' from @String@s to xmonad actions from a -- list of pairs. commandMap :: [(String, X ())] -> M.Map String (X ()) commandMap c = M.fromList c -- | Generate a list of commands to switch to\/send windows to workspaces. workspaceCommands :: X [(String, X ())] workspaceCommands = asks (workspaces . config) >>= \spaces -> return [((m ++ show i), windows $ f i) | i <- spaces , (f, m) <- [(view, "view"), (shift, "shift")] ] -- | Generate a list of commands dealing with multiple screens. screenCommands :: [(String, X ())] screenCommands = [((m ++ show sc), screenWorkspace (fromIntegral sc) >>= flip whenJust (windows . f)) | sc <- [0, 1]::[Int] -- TODO: adapt to screen changes , (f, m) <- [(view, "screen"), (shift, "screen-to-")] ] -- | A nice pre-defined list of commands. defaultCommands :: X [(String, X ())] defaultCommands = do wscmds <- workspaceCommands return $ wscmds ++ screenCommands ++ otherCommands where otherCommands = [ ("shrink" , sendMessage Shrink ) , ("expand" , sendMessage Expand ) , ("next-layout" , sendMessage NextLayout ) , ("default-layout" , asks (layoutHook . config) >>= setLayout ) , ("restart-wm" , restart "xmonad" True ) , ("restart-wm-no-resume", restart "xmonad" False ) , ("xterm" , spawn =<< asks (terminal . config) ) , ("run" , spawn "exe=`dmenu_path | dmenu -b` && exec $exe" ) , ("kill" , kill ) , ("refresh" , refresh ) , ("focus-up" , windows focusUp ) , ("focus-down" , windows focusDown ) , ("swap-up" , windows swapUp ) , ("swap-down" , windows swapDown ) , ("swap-master" , windows swapMaster ) , ("sink" , withFocused $ windows . sink ) , ("quit-wm" , io $ exitWith ExitSuccess ) ] -- | Given a list of command\/action pairs, prompt the user to choose a -- command and return the corresponding action. runCommand :: [(String, X ())] -> X () runCommand cl = do let m = commandMap cl choice <- dmenu (M.keys m) fromMaybe (return ()) (M.lookup choice m) -- | Given the name of a command from 'defaultCommands', return the -- corresponding action (or the null action if the command is not -- found). runCommand' :: String -> X () runCommand' c = do m <- fmap commandMap defaultCommands fromMaybe (return ()) (M.lookup c m)