roshask-0.2: src/executable/Main.hs
-- |The main entry point for the roshask executable.
module Main (main) where
import Control.Applicative
import qualified Data.ByteString.Char8 as B
import System.Directory (createDirectoryIfMissing, getCurrentDirectory)
import System.Environment (getArgs)
import System.Exit (exitWith, ExitCode(..))
import System.FilePath (replaceExtension, isRelative, (</>), dropFileName,
takeFileName)
import Ros.Internal.DepFinder (findMessages, findPackageDeps,
findPackageDepsTrans)
import Ros.Internal.PathUtil (codeGenDir, pathToPkgName)
import Analysis (runAnalysis)
import Parse
import Gen
import MD5
import PkgBuilder (buildPkgMsgs)
import Unregister
import PkgInit (initPkg)
generateAndSave :: FilePath -> IO ()
generateAndSave fname = do msgType <- fst <$> generate fname
fname' <- hsName
B.writeFile fname' msgType
where hsName = do d' <- codeGenDir fname
createDirectoryIfMissing True d'
return $ d' </> f
f = replaceExtension (takeFileName fname) ".hs"
-- Generate Haskell code for a message type.
generate :: FilePath -> IO (B.ByteString, String)
generate fname =
do r <- parseMsg fname
pkgMsgs <- map B.pack <$> findMessages dir
case r of
Left err -> do putStrLn $ "ERROR: " ++ err
exitWith (ExitFailure (-2))
Right msg -> runAnalysis $
do hMsg <- generateMsgType pkgHier pkgMsgs msg
md5 <- msgMD5 msg
return (hMsg, md5)
where pkgHier = B.pack $ "Ros." ++ init pkgName ++ "."
dir = dropFileName fname
pkgName = pathToPkgName dir
-- |Run "roshask gen" on all the .msg files in each of the given
-- package directories.
buildDepMsgs :: [FilePath] -> IO ()
buildDepMsgs = runAnalysis . mapM_ buildPkgMsgs
-- When given a relative path, prepend it with the current working
-- directory.
canonicalizeName :: FilePath -> IO FilePath
canonicalizeName fname = if isRelative fname
then (</> fname) <$> getCurrentDirectory
else return fname
help :: [String]
help = [ "Usage: roshask command [[arguments]]"
, "Available commands:"
, " create pkgName [[dependencies]] -- Create a new ROS package with "
, " roshask support"
, ""
, " gen file.msg -- Generate Haskell message code"
, ""
, " dep -- Build all messages this package "
, " depends on"
, ""
, " dep directory -- Build all messages the specified "
, " package depends on"
, ""
, " md5 file.msg -- Generate an MD5 sum for a ROS "
, " message type"
, ""
, " unregister -- Unregister all \"ROS-\"-prefixed"
, " packages using ghc-pkg. This is"
, " useful when you upgrade roshask"
, " and wish to remove all "
, " previously generated message"
, " libraries." ]
main :: IO ()
main = do args <- getArgs
case args of
["gen",name] -> canonicalizeName name >>= generateAndSave
["md5",name] -> canonicalizeName name >>=
generate >>= putStrLn . snd
("create":pkgName:deps) -> initPkg pkgName deps
["unregister"] -> unregisterInteractive
["dep"] -> do d <- getCurrentDirectory
deps <- findPackageDepsTrans d
buildDepMsgs (deps++[d])
["dep",name] -> findPackageDeps name >>= (buildDepMsgs . (++[name]))
_ -> do mapM_ putStrLn help
exitWith (ExitFailure (-1))