-
-
Notifications
You must be signed in to change notification settings - Fork 20
/
XMonadCmd.hs
82 lines (73 loc) · 2.83 KB
/
XMonadCmd.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
-- Utility for sending a command to xmonad and have
-- it immediately executed even when xmonad isn't built
-- with -threaded.
module Main () where
import Control.Concurrent
import Control.Monad
import Data.List
import Data.Monoid
import Data.Word
import Graphics.X11.Xlib
import Graphics.X11.Xlib.Event
import Graphics.X11.Xlib.Extras
import Network
import System.Console.GetOpt
import System.Environment
import System.IO
data Options = Options { optPort :: PortID
, optHost :: HostName
, optWait :: Bool
, optHelp :: Bool
}
defaultOptions :: Options
defaultOptions = Options { optPort = PortNumber 4242
, optHost = "localhost"
, optWait = False
, optHelp = False
}
readPort :: String -> Options -> Options
readPort str opts = opts { optPort = portNum }
where portNum = PortNumber . fromIntegral $ (read str :: Word16)
options :: [OptDescr (Endo Options)]
options = [ Option ['p'] ["port"]
(ReqArg (Endo . readPort) "<port>")
("Port on which to connect. <port> is expected to be an integer"
++ " between 0 and 65535. (Defaults to 4242)")
, Option ['h'] ["host"]
(ReqArg (\s -> Endo $ \opts -> opts { optHost = s }) "<hostname>")
"Which host to connect to. (Defaults to \"localhost\")"
, Option ['w'] ["wait"]
(NoArg . Endo $ \opts -> opts { optWait = True })
"Wait until the command is executed and print the result. (Default: False)"
, Option [] ["help"]
(NoArg . Endo $ \opts -> opts { optHelp = True })
"Show usage information."
]
getOptions :: [String] -> IO (Options,String)
getOptions args =
case getOpt Permute options args of
(o,rest,[]) -> return (mconcat o `appEndo` defaultOptions, intercalate " " rest)
(_,_,errs) -> ioError . userError $ concat errs ++ usageInfo header options
header :: String
header = "USAGE: xmonadcmd [OPTIONS] <string to send>"
sendCommand :: Options -> String -> IO ()
sendCommand opts cmd = openDisplay "" >>= \dpy -> do
putStrLn cmd
h <- connectTo (optHost opts) (optPort opts)
hSetBuffering h LineBuffering
hPutStrLn h cmd
rootw <- rootWindow dpy $ defaultScreen dpy
atom <- internAtom dpy "TEST" True
forkIO $ allocaXEvent $ \e -> do
setEventType e clientMessage
setClientMessageEvent e rootw atom 32 0 currentTime
sendEvent dpy rootw False structureNotifyMask e
sync dpy False
when (optWait opts) $ putStrLn =<< hGetLine h
hClose h
main :: IO ()
main = do
(opts,cmd) <- getOptions =<< getArgs
if optHelp opts
then putStrLn $ usageInfo header options
else sendCommand opts cmd