{-# LANGUAGE LambdaCase #-}
module XMonad.Actions.SpawnOn (
Spawner,
manageSpawn,
manageSpawnWithGC,
spawnHere,
spawnOn,
spawnAndDo,
shellPromptHere,
shellPromptOn
) where
import System.Posix.Types (ProcessID)
import XMonad
import XMonad.Prelude
import qualified XMonad.StackSet as W
import XMonad.Hooks.ManageHelpers
import XMonad.Prompt
import XMonad.Prompt.Shell
import qualified XMonad.Util.ExtensibleState as XS
import XMonad.Util.Process (getPPIDChain)
newtype Spawner = Spawner {Spawner -> [(ProcessID, Query (Endo WindowSet))]
pidsRef :: [(ProcessID, ManageHook)]}
instance ExtensionClass Spawner where
initialValue :: Spawner
initialValue = [(ProcessID, Query (Endo WindowSet))] -> Spawner
Spawner []
modifySpawner :: ([(ProcessID, ManageHook)] -> [(ProcessID, ManageHook)]) -> X ()
modifySpawner :: ([(ProcessID, Query (Endo WindowSet))]
-> [(ProcessID, Query (Endo WindowSet))])
-> X ()
modifySpawner [(ProcessID, Query (Endo WindowSet))]
-> [(ProcessID, Query (Endo WindowSet))]
f = forall a (m :: * -> *).
(ExtensionClass a, XLike m) =>
(a -> a) -> m ()
XS.modify ([(ProcessID, Query (Endo WindowSet))] -> Spawner
Spawner forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(ProcessID, Query (Endo WindowSet))]
-> [(ProcessID, Query (Endo WindowSet))]
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. Spawner -> [(ProcessID, Query (Endo WindowSet))]
pidsRef)
modifySpawnerM :: ([(ProcessID, ManageHook)] -> X [(ProcessID, ManageHook)]) -> X ()
modifySpawnerM :: ([(ProcessID, Query (Endo WindowSet))]
-> X [(ProcessID, Query (Endo WindowSet))])
-> X ()
modifySpawnerM [(ProcessID, Query (Endo WindowSet))]
-> X [(ProcessID, Query (Endo WindowSet))]
f = forall a (m :: * -> *).
(ExtensionClass a, XLike m) =>
(a -> m a) -> m ()
XS.modifyM (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [(ProcessID, Query (Endo WindowSet))] -> Spawner
Spawner forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(ProcessID, Query (Endo WindowSet))]
-> X [(ProcessID, Query (Endo WindowSet))]
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. Spawner -> [(ProcessID, Query (Endo WindowSet))]
pidsRef)
manageSpawn :: ManageHook
manageSpawn :: Query (Endo WindowSet)
manageSpawn = ([(ProcessID, Query (Endo WindowSet))]
-> X [(ProcessID, Query (Endo WindowSet))])
-> Query (Endo WindowSet)
manageSpawnWithGC (forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Int -> [a] -> [a]
take Int
20)
manageSpawnWithGC :: ([(ProcessID, ManageHook)] -> X [(ProcessID, ManageHook)])
-> ManageHook
manageSpawnWithGC :: ([(ProcessID, Query (Endo WindowSet))]
-> X [(ProcessID, Query (Endo WindowSet))])
-> Query (Endo WindowSet)
manageSpawnWithGC [(ProcessID, Query (Endo WindowSet))]
-> X [(ProcessID, Query (Endo WindowSet))]
garbageCollect = Query (Maybe ProcessID)
pid forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Maybe ProcessID
Nothing -> forall a. Monoid a => a
mempty
Just ProcessID
p -> do
Spawner [(ProcessID, Query (Endo WindowSet))]
pids <- forall a. X a -> Query a
liftX forall a (m :: * -> *). (ExtensionClass a, XLike m) => m a
XS.get
[ProcessID]
ppid_chain <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
io forall a b. (a -> b) -> a -> b
$ ProcessID -> IO [ProcessID]
getPPIDChain ProcessID
p
case forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (forall a b. Eq a => a -> [(a, b)] -> Maybe b
`lookup` [(ProcessID, Query (Endo WindowSet))]
pids) [ProcessID]
ppid_chain of
[] -> forall a. Monoid a => a
mempty
Query (Endo WindowSet)
mh : [Query (Endo WindowSet)]
_ -> forall a. X a -> Query a
liftX (ProcessID -> X ()
gc ProcessID
p) forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Query (Endo WindowSet)
mh
where
gc :: ProcessID -> X ()
gc ProcessID
p = ([(ProcessID, Query (Endo WindowSet))]
-> X [(ProcessID, Query (Endo WindowSet))])
-> X ()
modifySpawnerM forall a b. (a -> b) -> a -> b
$ [(ProcessID, Query (Endo WindowSet))]
-> X [(ProcessID, Query (Endo WindowSet))]
garbageCollect forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> Bool) -> [a] -> [a]
filter ((forall a. Eq a => a -> a -> Bool
/= ProcessID
p) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> a
fst)
mkPrompt :: (String -> X ()) -> XPConfig -> X ()
mkPrompt :: (String -> X ()) -> XPConfig -> X ()
mkPrompt String -> X ()
cb XPConfig
c = do
[String]
cmds <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
io IO [String]
getCommands
forall p.
XPrompt p =>
p -> XPConfig -> ComplFunction -> (String -> X ()) -> X ()
mkXPrompt Shell
Shell XPConfig
c ([String] -> Predicate -> ComplFunction
getShellCompl [String]
cmds forall a b. (a -> b) -> a -> b
$ XPConfig -> Predicate
searchPredicate XPConfig
c) String -> X ()
cb
shellPromptHere :: XPConfig -> X ()
shellPromptHere :: XPConfig -> X ()
shellPromptHere = (String -> X ()) -> XPConfig -> X ()
mkPrompt String -> X ()
spawnHere
shellPromptOn :: WorkspaceId -> XPConfig -> X ()
shellPromptOn :: String -> XPConfig -> X ()
shellPromptOn String
ws = (String -> X ()) -> XPConfig -> X ()
mkPrompt (String -> String -> X ()
spawnOn String
ws)
spawnHere :: String -> X ()
spawnHere :: String -> X ()
spawnHere String
cmd = forall a. (WindowSet -> X a) -> X a
withWindowSet forall a b. (a -> b) -> a -> b
$ \WindowSet
ws -> String -> String -> X ()
spawnOn (forall i l a s sd. StackSet i l a s sd -> i
W.currentTag WindowSet
ws) String
cmd
spawnOn :: WorkspaceId -> String -> X ()
spawnOn :: String -> String -> X ()
spawnOn String
ws = Query (Endo WindowSet) -> String -> X ()
spawnAndDo (String -> Query (Endo WindowSet)
doShift String
ws)
spawnAndDo :: ManageHook -> String -> X ()
spawnAndDo :: Query (Endo WindowSet) -> String -> X ()
spawnAndDo Query (Endo WindowSet)
mh String
cmd = do
ProcessID
p <- forall (m :: * -> *). MonadIO m => String -> m ProcessID
spawnPID forall a b. (a -> b) -> a -> b
$ String -> String
mangle String
cmd
([(ProcessID, Query (Endo WindowSet))]
-> [(ProcessID, Query (Endo WindowSet))])
-> X ()
modifySpawner ((ProcessID
p,Query (Endo WindowSet)
mh) forall a. a -> [a] -> [a]
:)
where
mangle :: String -> String
mangle String
xs | forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` String
metaChars) String
xs Bool -> Bool -> Bool
|| String
"exec" forall a. Eq a => [a] -> [a] -> Bool
`isInfixOf` String
xs = String
xs
| Bool
otherwise = String
"exec " forall a. [a] -> [a] -> [a]
++ String
xs
metaChars :: String
metaChars = String
"&|;"