hsdev-0.1.3.0: tools/hsdev.hs
{-# LANGUAGE TemplateHaskell #-}
module Main (
main
) where
import Control.Applicative
import Control.Exception
import Control.Monad
import Network.Socket (withSocketsDo)
import System.Environment (getArgs)
import System.Exit
import System.IO
import Text.Read (readMaybe)
import Control.Apply.Util (chain)
import System.Console.Cmd
import qualified System.Console.Cmd as C (brief)
import qualified HsDev.Client.Commands as Client (commands)
import qualified HsDev.Server.Commands as Server
import HsDev.Version
main :: IO ()
main = handle logErr' $ withSocketsDo $ do
hSetBuffering stdout LineBuffering
hSetEncoding stdout utf8
as <- getArgs
when (null as) $ do
printUsage
exitSuccess
let
asr = if last as == "-?" then "help" : init as else as
run mainCommands (onError "Unknown command") onError asr
where
onError :: String -> IO ()
onError errs = putStrLn errs >> exitFailure
logErr' (SomeException e) = putStrLn $ "exception " ++ show e
mainCommands :: [Cmd (IO ())]
mainCommands = withHelp "hsdev" (printWith putStrLn) $ concat [
[cmd "version" [] [] "hsdev version" version'],
map (chain [validateOpts, noArgs]) Server.commands,
map Server.clientCmd Client.commands]
where
version' _ = putStrLn $cabalVersion
printUsage :: IO ()
printUsage = mapM_ (putStrLn . ('\t':) . ("hsdev " ++) . C.brief) mainCommands
-- | Check that specified options are numbers
validateNums :: [String] -> Cmd a -> Cmd a
validateNums ns = validateArgs (check . namedArgs) where
check os = forM_ ns $ \n -> case (readMaybe :: String -> Maybe Int) <$> arg n os of
Just Nothing -> failMatch "Must be a number"
_ -> return ()
-- | Check, that 'port' and 'timeout' are numbers
validateOpts :: Cmd a -> Cmd a
validateOpts = validateNums ["port", "timeout"]
-- | Ensure no positional arguments provided
noArgs :: Cmd a -> Cmd a
noArgs = validateArgs (noPos . posArgs) where
noPos ps =
guard (null ps)
`mplus`
failMatch "positional arguments are not expected"