xmonad-entryhelper-0.1.0.0: src/XMonad/Util/EntryHelper/Config.hs
{-|
Copyright : (c) 2015 Javran Cheng
License : MIT
Maintainer : Javran.C@gmail.com
Stability : unstable
Portability : non-portable (requires X11)
Configuration for EntryHelper
-}
module XMonad.Util.EntryHelper.Config
( Config(..)
, defaultConfig
, withHelper
, withCustomHelper
) where
import System.Environment
import System.Exit
import System.Info
import Data.Version (showVersion)
import Graphics.X11.Xinerama (compiledWithXinerama)
import XMonad.Main
import XMonad.Core hiding (recompile)
import qualified XMonad.Config as XMC
import XMonad.Util.EntryHelper.Generated
import XMonad.Util.EntryHelper.Util
import XMonad.Util.EntryHelper.Compile
-- | the configuration for EntryHelper.
--
-- * @run@ should execute XMonad using a customized configuration.
-- * @compile force@ should compile the source file and return a value which
-- will lately be consumed by @postCompile@. @force@ is just a hint about whether
-- the compilation should be forced. @compile@ is free to ignore it and do up-to-date check
-- on its own.
-- * @postCompile val@ should take action according to the @val@, usually produced by @compile@
--
-- Note that:
--
-- * @compile@ should create a new process for compilation, as otherwise things like `executeFile`
-- will replace the current process image with a new process image, make it impossible
-- for @postCompile@ to invoke.
-- * @force@ is just a hint about whether the compilation should be forced.
-- and @compile@ is free to ignore it and do up-to-date checking on its own.
-- * don't remove the binary file when the compilation has failed, as XMonad restart relies
-- on it.
data Config a = Config
{ run :: IO () -- ^ the action for executing XMonad
, compile :: Bool -> IO a -- ^ the action for compiling XMonad
, postCompile :: a -> IO () -- ^ the action after compiling XMonad
}
-- | default config for xmonad-entryhelper,
-- invokes xmonad with its default config file
defaultConfig :: Config ExitCode
defaultConfig = Config
{ run = xmonad XMC.defaultConfig
, compile = defaultCompile
, postCompile = defaultPostCompile
}
{-
-- I don't think this is necessary,
-- as users can use "xmonad config" or just their main entries for "run"
-- depending on their needs.
class Executable r where
execute :: r -> IO ()
instance (LayoutClass l Window, Read (l Window)) => Executable (XConfig l) where
execute = xmonad
instance Executable a => Executable (IO a) where
execute a = a >>= execute
instance Executable () where
execute = const (return ())
-}
-- | @withHelper e@ is the same as calling `withCustomHelper` with default
-- @compile@ and @postCompile actions@
--
-- Either of the following will work:
--
-- * replace your main entry with @main = withHelper yourOldMain@
-- * use @main = withHelper (xmonad cfg)@ if you have only customized your `XConfig`
withHelper :: IO () -> IO ()
withHelper e = withCustomHelper defaultConfig { run = e }
-- | simulates the way that XMonad handles its command line arguments.
--
-- * when called with no argument, the action in @run@ will be used
-- * when called with a string prefixed with @"--resume"@, or when called with
-- @"--replace"@, the action in @run@ will be used
-- * when called with @"--recompile"@ or @"--restart"@, 'compile' will be called. And 'postCompile'
-- will handle the results from compliation.
-- * additionally when called with @"--restart"@ a restart request will be sent to the current
-- XMonad instance after the compilation regardless of the compilation result.
withCustomHelper :: Config a -> IO ()
withCustomHelper cfg = do
-- since XMonad has hard-coded to call "xmonad --resume{..}" on restart
-- I guess there isn't much we can do to have more command line functionalities
-- TODO: a pontential plan might be:
-- try to simulate "xmonad" when the program name is "xmonad",
-- and otherwise an alternative command line argument parsing strategy will be applied.
args <- getArgs
let launch = installSignalHandlers >> run cfg
recompile force = compile cfg force >>= postCompile cfg
case args of
[] -> launch
("--resume":_) -> launch
["--help"] -> printHelp
["--recompile"] -> recompile True
["--replace"] -> launch
["--restart"] -> safeIO () (recompile False) >> sendRestart
["--version"] -> putStrLn $ unwords shortVersion
["--verbose-version"] -> putStrLn . unwords $ shortVersion ++ longVersion
_ -> printHelp >> exitFailure
where
shortVersion = [ "xmonad", xmonadVersion ]
longVersion = [ "compiled by", compilerName, showVersion compilerVersion
, "for", arch ++ "-" ++ os
, "\nXinerama:", show compiledWithXinerama ]
printHelp :: IO ()
printHelp = do
self <- getProgName
putStr . unlines $
[ "xmonad-entryhelper - XMonad config entry point wrapper"
, ""
, "Usage: " ++ self ++ " [OPTION]"
, "Options:"
, " --help Print this message"
, " --version Print XMonad's version number"
, " --recompile Recompile XMonad"
, " --replace Replace the running window manager with XMonad"
, " --restart Request a running XMonad process to restart"
]