diff --git a/lib/AppGroups.hs b/lib/AppGroups.hs
index 7040f95..3ad3086 100644
--- a/lib/AppGroups.hs
+++ b/lib/AppGroups.hs
@@ -1,9 +1,9 @@
{-# LANGUAGE ExistentialQuantification, TypeSynonymInstances, FlexibleInstances #-}
module AppGroups
- (Key, App (..), Apps, Condition (..), Cond (..), Regex (..),
+ (Key, App (..), Apps, Condition (..), Cond (..),
query,
oneOf, apps2hooks, apps2keys,
- selectAppGroup,
+ selectAppGroup, runNewApp,
switchToApp,
doFullscreen)
where
@@ -18,7 +18,7 @@ import qualified XMonad.StackSet as W
import XMonad.Actions.GridSelect
import XMonad.Actions.DynamicWorkspaces
import XMonad.Util.WindowProperties
--- import XMonad.Hooks.ManageHelpers hiding (C)
+import XMonad.Util.WindowPropertiesRE
import CommonFunctions ((~?), selectOneWindow)
@@ -65,30 +65,13 @@ instance Condition String where
instance Condition Property where
toQuery p = propertyToQuery p
--- | Regular expression over condition
-data (Condition a) => Regex a = Regex a
-
-instance (Show a, Condition a) => Show (Regex a) where
- show (Regex a) = show a
-
-instance Condition (Regex String) where
- toQuery (Regex s) = className ~? s
+instance Condition PropertyRE where
+ toQuery (RE p) = propertyToQueryRE p
-- | Query WM_WINDOW_ROLE atom
role :: Query String
role = stringProperty "WM_WINDOW_ROLE"
-instance Condition (Regex Property) where
- toQuery (Regex (Title s)) = title ~? s
- toQuery (Regex (Resource s)) = resource ~? s
- toQuery (Regex (ClassName s)) = className ~? s
- toQuery (Regex (Role s)) = role ~? s
- toQuery (Regex (Machine s)) = stringProperty "WM_CLIENT_MACHINE" ~? s
- toQuery (Regex (And p1 p2)) = toQuery p1 <&&> toQuery p2
- toQuery (Regex (Or p1 p2)) = toQuery p1 <||> toQuery p2
- toQuery (Regex (Not p)) = not `fmap` toQuery p
- toQuery (Regex (Const b)) = return b
-
-- | Turn any X () operation on window into ManageHook
fromWindowOp :: (Window -> X()) -> ManageHook
fromWindowOp fn = ask >>= \w -> liftX (fn w) >> doF id
@@ -176,14 +159,35 @@ groupName (_ :-> wksp) = wksp
groupName (Float app) = groupName app
groupName (Named _ name) = name
+appWorkspace :: App -> Maybe WorkspaceId
+appWorkspace (On app _) = appWorkspace app
+appWorkspace (_ ::: _) = Nothing
+appWorkspace (_ :>> _) = Nothing
+appWorkspace (Group _) = Nothing
+appWorkspace (_ :-> wksp) = Just wksp
+appWorkspace (Float app) = appWorkspace app
+appWorkspace (Fullscreen app) = appWorkspace app
+appWorkspace (Named app _) = appWorkspace app
+
+appAction :: App -> Maybe (X ())
+appAction (On app _) = appAction app
+appAction (command ::: app) = Just $ spawn command
+appAction (action :>> _) = Just action
+appAction (Group _) = Nothing
+appAction (Fullscreen app) = appAction app
+appAction (Named app _) = appAction app
+appAction (Float app) = appAction app
+appAction (app :-> _) = appAction app
+
runApp :: App -> X ()
-runApp (On app _) = runApp app
-runApp (command ::: _) = spawn command
-runApp (action :>> _) = action
-runApp (Group _) = return ()
-runApp (Fullscreen app) = runApp app
-runApp (app :-> _) = runApp app
-runApp (Named app _) = runApp app
+runApp (command ::: _) = spawn command
+runApp (app :-> wksp) = runApp app
+runApp (action :>> _) = action
+runApp (On app _) = runApp app
+runApp (Group _) = return ()
+runApp (Fullscreen ap) = runApp ap
+runApp (Float app) = runApp app
+runApp (Named app _) = runApp app
apps2hooks :: Apps -> [ManageHook]
apps2hooks lst = map appHook lst
@@ -230,7 +234,21 @@ selectAppGroup gscA gscW apps = do
group <- gridselect gscA $ zip names nonempty
whenJust group $ \app ->
selectWithQuery gscW (query app) (runApp app)
- where
- isNotEmpty :: App -> X Bool
- isNotEmpty group = (not . null) `fmap` matchingWindows (query group)
+
+isNotEmpty :: App -> X Bool
+isNotEmpty group = (not . null) `fmap` matchingWindows (query group)
+
+shouldRun :: App -> X Bool
+shouldRun group = do
+ ws <- matchingWindows (query group)
+ if null ws
+ then return $ isJust $ appAction group
+ else return False
+
+runNewApp :: GSConfig App -> Apps -> X ()
+runNewApp gsconfig apps = do
+ empty <- filterM shouldRun apps
+ let names = map groupName empty
+ selected <- gridselect gsconfig $ zip names empty
+ whenJust selected runApp
diff --git a/lib/CommonFunctions.hs b/lib/CommonFunctions.hs
index d0cde73..a437306 100644
--- a/lib/CommonFunctions.hs
+++ b/lib/CommonFunctions.hs
@@ -7,7 +7,8 @@ module CommonFunctions
gotoWorkspace,
selectOneWindow, searchInWorkspace,
specialMove,
- vimsessions, textEditors,
+ vimsession, vimsessions, textEditors,
+ edit_config,
recent,
(~?),
isFloat,
@@ -36,6 +37,7 @@ import XMonad.Util.NamedWindows
import XMonad.Actions.DynamicWorkspaces
import XMonad.Actions.GridSelect
+import XMonad.Actions.SpawnOn
import Themes
@@ -144,6 +146,9 @@ returnToCurrent c s = W.view curtag s
curstack :: W.StackSet i l a sid sd -> Maybe (W.Stack a)
curstack s = W.stack $ W.workspace $ W.current s
+getCurrentWorkspace :: X WorkspaceId
+getCurrentWorkspace = withWindowSet (\ws -> return $ W.tag $ W.workspace $ W.current ws)
+
emptyCurrentWorkspace :: (Eq s) => W.StackSet String l a s sd -> W.StackSet String l a s sd
emptyCurrentWorkspace s = returnToCurrent s (addStackToTarget "trash" (curstack s) $ emptyCurrentWs s)
@@ -202,15 +207,21 @@ recent types = "recently-used.py " ++ unwords (map mime types)
("doc", "application/msword application/vnd.oasis.opendocument.text"),
("png", "image/png")]
+-- | Open specified GVim session
+vimsession :: String -> X ()
+vimsession name = do
+ home <- io $ getEnv "HOME"
+ let path = home </> ".vim/sessions" </> (name ++ ".vimsession")
+ spawn ("gvim -S " ++ path)
+
-- | Open selected GVim session
vimsessions :: X ()
vimsessions = do
home <- io $ getEnv "HOME"
paths <- io $ (concat . fst) `fmap` globDir [compile "*.vimsession"] (home </> ".vim/sessions")
- let actions = map ("gvim -S " ++) paths
- sessions = map (dropExtension . takeFileName) paths
- selected <- gridselect myGSConfig $ zip sessions actions
- whenJust selected spawn
+ let sessions = map (dropExtension . takeFileName) paths
+ selected <- gridselect myGSConfig $ zip sessions sessions
+ whenJust selected vimsession
-- | Run the selected text editor
textEditors :: X ()
@@ -246,10 +257,19 @@ trashWindow = do
-- | On window unmap, remove current workspace if it's empty.
unmapEventHook :: Event -> X All
-unmapEventHook (UnmapEvent {}) = removeEmptyWorkspace >> return (All True)
+unmapEventHook (UnmapEvent {}) = do
+ current <- getCurrentWorkspace
+ when (current /= "dashboard") removeEmptyWorkspace
+ return (All True)
unmapEventHook _ = return (All True)
-- | Regular expressions matching for ManageHooks
(~?) :: (Functor f) => f String -> String -> f Bool
q ~? x = fmap (=~ x) q
+edit_config :: X ()
+edit_config = do
+ vimsession "xmonad"
+ spawnOn "text" =<< asks (terminal . config)
+
+
diff --git a/lib/GroupsSetup.hs b/lib/GroupsSetup.hs
index 54f7163..d8d54e4 100644
--- a/lib/GroupsSetup.hs
+++ b/lib/GroupsSetup.hs
@@ -1,35 +1,37 @@
{-# LANGUAGE NoMonomorphismRestriction, FlexibleContexts #-}
module GroupsSetup where
+import XMonad.Util.WindowProperties
+import XMonad.Util.WindowPropertiesRE
+
import AppGroups
-import CommonFunctions (textEditors, recent)
+import CommonFunctions (textEditors, recent, edit_config)
-regex :: (Condition (Regex a), Condition a) => a -> Cond
-regex = C . Regex
+regex = C . RE . ClassName
defaultFM :: String
defaultFM = "konqueror --profile filemanagement"
myApps =
[ "iceweasel" ::: [C "Epiphany-browser", C "Kontact", C "Iceweasel",
- C "Firefox", C "Opera", C "Arora" ] :-> "inet" `On` "M1-x w" `Named` "internet",
- "icedove" ::: [C "Icedove", C "Kontact" ] :-> "inet" `On` "M1-x y" `Named` "mail",
- "rssowl" ::: [C "Liferea", C "RSSOwl"] :-> "inet" `Named` "rss",
- "transmission-gtk" ::: [regex "Transmission"] :-> "torrents" `On` "M1-x r",
+ C "Firefox", C "Opera", C "Arora" ] :-> "inet" `On` "M1-x w" `Named` "internet",
+ "icedove" ::: [C "Icedove", C "Kontact" ] :-> "inet" `On` "M1-x y" `Named` "mail",
+ "rssowl" ::: [C "Liferea", C "RSSOwl"] :-> "inet" `Named` "rss",
+ "transmission-gtk" ::: [regex "Transmission"] :-> "torrents" `On` "M1-x r",
Group [C "Inkscape", C "Eog", C "Gwenview", C "Dia",
C "MyPaint"] :-> "graphics" `On` "M1-x d",
- Group [regex "Gimp"] :-> "gimp" `On` "M1-x g",
- Group [C "F-spot",C "Digikam"] :-> "photo" `On` "M1-x p",
- "gnome-terminal" ::: [C "Gnome-terminal", C "Konsole"] :-> "term" `On` "M1-x t",
+ Group [regex "Gimp"] :-> "gimp" `On` "M1-x g",
+ Group [C "F-spot",C "Digikam"] :-> "photo" `On` "M1-x p",
+ "gnome-terminal" ::: [C "Gnome-terminal", C "Konsole"] :-> "term" `On` "M1-x t",
textEditors :>> [C "Gedit", C "Leafpad",
- C "Gvim", C "Kate", C "KWrite", C "Emacs"] :-> "text" `On` "M1-x e",
- recent ["doc"] ::: [regex "libreoffice", C "TeXmacs"] :-> "office" `On` "M1-x o",
- recent ["pdf","djvu"] ::: [C "Evince", C "Okular"] :-> "docs" `On` "M1-x k",
+ C "Gvim", C "Kate", C "Kwrite", C "Emacs"] :-> "text" `On` "M1-x e",
+ recent ["doc"] ::: [regex "libreoffice", C "TeXmacs"] :-> "office" `On` "M1-x o",
+ recent ["pdf","djvu"] ::: [C "Evince", C "Okular"] :-> "docs" `On` "M1-x k",
defaultFM ::: [C "Nautilus", C "Dolphin", C "Konqueror",
- C "Krusader"] :-> "files" `On` "M1-x f",
+ C "Krusader"] :-> "files" `On` "M1-x f",
Group [C "Amarok", C "Rhythmbox",
- regex "Audacious" ] :-> "music" `On` "M1-x a",
- Group [C "MPlayer", C "Totem"] :-> "video" `On` "M1-x v",
- Group [C "Wxmaxima"] :-> "math" `On` "M1-x m",
- "pidgin" ::: [C "Pidgin", C "Kopete"] :-> "im" `On` "M1-x i" ]
+ regex "Audacious" ] :-> "music" `On` "M1-x a",
+ Group [C "MPlayer", C "Totem"] :-> "video" `On` "M1-x v",
+ Group [C "Wxmaxima"] :-> "math" `On` "M1-x m",
+ "pidgin" ::: [C "Pidgin", C "Kopete"] :-> "im" `On` "M1-x i"]
diff --git a/lib/KeyBindings.hs b/lib/KeyBindings.hs
index 9889250..6fa0cfd 100644
--- a/lib/KeyBindings.hs
+++ b/lib/KeyBindings.hs
@@ -32,7 +32,7 @@ import XMonad.Prompt.Window
import CommonFunctions
import Mouse
import Themes (myXPConfig, myGSConfig, searchGS)
-import AppGroups (switchToApp)
+import AppGroups (switchToApp, runNewApp)
import GroupsSetup (myApps)
workspaceOrder = ["inet","text","files","im","term"]
@@ -68,6 +68,7 @@ addKeys = [-- ("M1-<F2>", gnomeRun),
("M1-<F2>", spawn "gmrun"),
("<Pause>", spawn "qwerty.py -a -f -g 640x400"),
("M-v", vimsessions),
+ ("M-a", runNewApp searchGS myApps),
-- close focused window
("M1-<F4>", killIfNot (Role "buddy_list")),
@@ -83,14 +84,13 @@ addKeys = [-- ("M1-<F2>", gnomeRun),
("M-b", sendMessage $ ToggleStruts),
- -- Focus urgent window
- ("M-<F12>", focusUrgent),
+ ("M1-e", windows (W.greedyView "dashboard")),
-- Bring any window to current workspace
- ("M1-w", windowPromptBring myXPConfig),
- ("M1-x x", searchInWorkspace searchGS),
- ("M1-z", goToSelected searchGS),
- ("M-z", gridselectWorkspace searchGS W.greedyView),
+ ("M1-w", bringSelected searchGS),
+ ("M1-<Tab>", searchInWorkspace searchGS),
+ ("M-<Tab>", gridselectWorkspace searchGS W.greedyView),
+ ("M1-/", goToSelected searchGS),
("M-<Backspace>", nextMatch History (return True)),
@@ -99,7 +99,6 @@ addKeys = [-- ("M1-<F2>", gnomeRun),
-- Move focus to the next window
-- ("M1-<Tab>", windows W.focusDown),
- ("M1-<Tab>", searchInWorkspace searchGS),
("M-j", windows W.focusDown),
("M-k", windows W.focusUp ),
@@ -125,8 +124,6 @@ addKeys = [-- ("M1-<F2>", gnomeRun),
("M-M1-u", withFocused (sendMessage . UnMerge)),
- ("M-M1-u", withFocused (sendMessage . UnMergeAll)),
-
-- Shrink/expand the master area
("M-e", sendMessage Shrink),
("M-r", sendMessage Expand),
@@ -134,7 +131,7 @@ addKeys = [-- ("M1-<F2>", gnomeRun),
-- Push window back into tiling
("M-S-f", withFocused $ windows . W.sink),
- ("M-<Home>", spawn "gvim ~/.xmonad/xmonad.hs"),
+ ("M-<Home>", edit_config),
("M-l", spawn "xscreensaver-command -lock"),
diff --git a/lib/Themes.hs b/lib/Themes.hs
index 003d740..47c50f1 100644
--- a/lib/Themes.hs
+++ b/lib/Themes.hs
@@ -28,7 +28,7 @@ searchGS = defaultGSConfig {
-----------------------------------------------------------------------
-- Some general settings
myWorkspaces :: [WorkspaceId]
-myWorkspaces = ["main"]
+myWorkspaces = ["dashboard"]
myFocusedBorderColor :: String
myFocusedBorderColor = "#E3A775"
diff --git a/xmonad.hs b/xmonad.hs
index c7cdb0c..d56e8ac 100644
--- a/xmonad.hs
+++ b/xmonad.hs
@@ -6,6 +6,7 @@ import XMonad.Config.Kde (kde4Config)
import XMonad.Actions.GroupNavigation (historyHook)
import XMonad.Actions.UpdatePointer
+import XMonad.Actions.SpawnOn
-- Import hooks to support EWMH and other compatibility hooks
import XMonad.Hooks.EwmhDesktops (ewmh)
@@ -45,7 +46,7 @@ main = do
-- hooks, layouts
layoutHook = myLayout,
handleEventHook = unmapEventHook <+> minimizeEventHook,
- manageHook = baseManageHook <+> myManageHook,
+ manageHook = manageSpawn <+> baseManageHook <+> myManageHook,
logHook = do
baseLogHook
updatePointer (TowardsCentre 0.5 0.5)