-- | -- Module: Main -- Copyright: (c) 2015-2016 Martijn Rijkeboer -- License: MIT -- Maintainer: Martijn Rijkeboer -- -- Main module for the protoc executable. module Main where import Data.Either (lefts, rights) import Parser.FileDesc (FileDesc) import Parser.FileWriter (write) import Parser.Generator (generate) import Parser.ProtoParser (parseProto) import System.Console.GetOpt (OptDescr(..), ArgDescr(..), ArgOrder(..), getOpt, usageInfo) import System.Environment (getArgs) data Options = Options { optHelp :: Bool , optVersion :: Bool } deriving Show data ProtoInfo = ProtoInfo { filePath :: FilePath , content :: String } deriving Show defaultOptions :: Options defaultOptions = Options { optHelp = False , optVersion = False } options :: [OptDescr (Options -> Options)] options = [ Option ['h'] ["help"] (NoArg (\opts -> opts{optHelp = True})) "show usage" , Option ['v'] ["version"] (NoArg (\opts -> opts{optVersion = True})) "show version number" ] parserOpts :: [String] -> Either String (Options, [String]) parserOpts argv = case getOpt Permute options argv of (o,n,[] ) -> Right (foldl (flip id) defaultOptions o, n) (_,_,errs) -> Left (concat errs ++ usage) main :: IO () main = do args <- getArgs case parserOpts args of Right opts -> handleOpts opts Left errs -> putStrLn errs handleOpts :: (Options, [String]) -> IO () handleOpts (Options {optHelp=True}, _) = putStrLn usage handleOpts (Options {optVersion=True}, _) = putStrLn version handleOpts (Options {}, []) = putStrLn noFiles handleOpts (Options {}, fs) = printFiles $ getProtoInfos fs getProtoInfos :: [FilePath] -> IO [ProtoInfo] getProtoInfos = mapM getProtoInfo getProtoInfo :: FilePath -> IO ProtoInfo getProtoInfo fPath = do fData <- readFile fPath return $ ProtoInfo fPath fData printFiles :: IO [ProtoInfo] -> IO () printFiles infos = do is <- infos let parsed = parseFiles is putStr $ unlines $ lefts parsed write $ generate $ rights parsed parseFiles :: [ProtoInfo] -> [Either String FileDesc] parseFiles = map parseFile parseFile :: ProtoInfo -> Either String FileDesc parseFile info = parseProto (filePath info) (content info) noFiles :: String noFiles = "protoc: no file given\n" ++ usage usage :: String usage = usageInfo "Usage: protoc [OPTION]... FILES" options version :: String version = "protoc 0.0.1"