Skip to content
Snippets Groups Projects

Refactor hpcmain

Merged BinderDavid requested to merge refactor-hpcmain into master
1 file
+ 86
93
Compare changes
  • Side-by-side
  • Inline
+ 86
93
@@ -8,30 +8,35 @@ import Data.Bifunctor (bimap)
@@ -8,30 +8,35 @@ import Data.Bifunctor (bimap)
import Data.List (intercalate, partition, uncons)
import Data.List (intercalate, partition, uncons)
import Data.List.NonEmpty (NonEmpty((:|)))
import Data.List.NonEmpty (NonEmpty((:|)))
import Data.Maybe (catMaybes, isJust)
import Data.Maybe (catMaybes, isJust)
import Data.Version
import Data.Version ( showVersion )
import System.Environment
import System.Environment ( getArgs )
import System.Exit
import System.Exit ( exitFailure, exitWith, ExitCode(ExitSuccess) )
import System.Console.GetOpt
import System.Console.GetOpt ( getOpt, ArgOrder(Permute) )
import System.Directory (doesPathExist)
import System.Directory (doesPathExist)
import HpcFlags
import HpcFlags
import HpcReport
( Plugin(..),
import HpcMarkup
Flags,
import HpcCombine
default_flags,
import HpcShowTix
default_final_flags,
import HpcDraft
command_usage )
import HpcOverlay
import HpcReport ( report_plugin )
import Paths_hpc_bin
import HpcMarkup ( markup_plugin )
 
import HpcCombine ( sum_plugin, combine_plugin, map_plugin )
 
import HpcShowTix ( showtix_plugin )
 
import HpcDraft ( draft_plugin )
 
import HpcOverlay ( overlay_plugin )
 
import Paths_hpc_bin ( version )
helpList :: IO ()
helpList :: IO ()
helpList = do
helpList = do
putStrLn $
putStrLn $
"Usage: hpc COMMAND ...\n\n" ++
"Usage: hpc COMMAND ...\n\n" <>
section "Commands" help ++
section "Commands" [help_plugin] <>
section "Reporting Coverage" reporting ++
section "Reporting Coverage" [report_plugin, markup_plugin] <>
section "Processing Coverage files" processing ++
section "Processing Coverage files" [sum_plugin, combine_plugin, map_plugin] <>
section "Coverage Overlays" overlays ++
section "Coverage Overlays" [overlay_plugin, draft_plugin] <>
section "Others" other ++
section "Others" [showtix_plugin, version_plugin] <>
""
""
putStrLn ""
putStrLn ""
putStrLn "or: hpc @response_file_1 @response_file_2 ..."
putStrLn "or: hpc @response_file_1 @response_file_2 ..."
@@ -42,35 +47,31 @@ helpList = do
@@ -42,35 +47,31 @@ helpList = do
putStrLn "example:"
putStrLn "example:"
putStrLn "report my_library.tix --include=ModuleA \\"
putStrLn "report my_library.tix --include=ModuleA \\"
putStrLn "--include=ModuleB"
putStrLn "--include=ModuleB"
 
 
-- | Print the summaries of all plugins belonging to a given section.
 
section :: String -- ^ Name of the section.
 
-> [Plugin] -- ^ Plugins belonging to that section.
 
-> String
 
section msg plugins = msg <> ":\n" <> unlines summaries
where
where
help = ["help"]
summaries = [ take 14 (" " <> name plugin <> repeat ' ') <> summary plugin | plugin <- plugins ]
reporting = ["report","markup"]
overlays = ["overlay","draft"]
main :: IO ()
processing = ["sum","combine","map"]
main = do
other = [ name hook
args <- getArgs
| hook <- hooks
dispatch args
, name hook `notElem`
(concat [help,reporting,processing,overlays])
]
section :: String -> [String] -> String
section _ [] = ""
section msg cmds = msg ++ ":\n"
++ unlines [ take 14 (" " ++ cmd ++ repeat ' ') ++ summary hook
| cmd <- cmds
, hook <- hooks
, name hook == cmd
]
 
-- | The main dispatch function. It either accepts a valid command followed by a list of its arguments,
 
-- or a list of response files of the form '@filename'.
dispatch :: [String] -> IO ()
dispatch :: [String] -> IO ()
dispatch [] = do
dispatch [] = do
helpList
helpList
exitWith ExitSuccess
exitWith ExitSuccess
dispatch (txt:args0) = do
dispatch (txt:args0) = do
case lookup txt hooks' of
case lookup txt hooks' of
Just plugin -> parse plugin args0
Just plugin -> dispatchOnPlugin plugin args0
_ -> case getResponseFileName txt of
_ -> case getResponseFileName txt of
Nothing -> parse help_plugin (txt:args0)
Nothing -> dispatchOnPlugin help_plugin (txt:args0)
Just firstResponseFileName -> do
Just firstResponseFileName -> do
let
let
(responseFileNames', nonResponseFileNames) = partitionFileNames args0
(responseFileNames', nonResponseFileNames) = partitionFileNames args0
@@ -82,38 +83,7 @@ dispatch (txt:args0) = do
@@ -82,38 +83,7 @@ dispatch (txt:args0) = do
putStrLn $ "When first argument is a Response File, " <>
putStrLn $ "When first argument is a Response File, " <>
"all arguments should be Response Files."
"all arguments should be Response Files."
exitFailure
exitFailure
let
dispatchOnResponseFiles (firstResponseFileName :| responseFileNames')
responseFileNames :: NonEmpty FilePath
responseFileNames = firstResponseFileName :| responseFileNames'
forM_ responseFileNames $ \responseFileName -> do
exists <- doesPathExist responseFileName
when (not exists) $ do
putStrLn $ "Response File '" <> responseFileName <> "' does not exist"
exitFailure
-- read all Response Files
responseFileNamesAndText :: NonEmpty (FilePath, String) <-
forM responseFileNames $ \responseFileName ->
fmap (responseFileName, ) (readFile responseFileName)
forM_ responseFileNamesAndText $ \(responseFileName, responseFileText) ->
-- parse first word of Response File, which should be a command
case uncons $ words responseFileText of
Nothing -> do
putStrLn $ "Response File '" <> responseFileName <> "' has no command"
exitFailure
Just (responseFileCommand, args1) -> case lookup responseFileCommand hooks' of
-- check command for validity
-- It is important than a Response File cannot specify another Response File;
-- this is prevented
Nothing -> do
putStrLn $ "Response File '" <> responseFileName <>
"' command '" <> responseFileCommand <> "' invalid"
exitFailure
Just plugin -> do
putStrLn $ "Response File '" <> responseFileName <> "':"
parse plugin args1
where
where
getResponseFileName :: String -> Maybe FilePath
getResponseFileName :: String -> Maybe FilePath
getResponseFileName s = do
getResponseFileName s = do
@@ -132,26 +102,52 @@ dispatch (txt:args0) = do
@@ -132,26 +102,52 @@ dispatch (txt:args0) = do
bimap (fmap snd) (fmap fst) $ partition (isJust . snd) hasFileName
bimap (fmap snd) (fmap fst) $ partition (isJust . snd) hasFileName
in (catMaybes fileNames, nonFileNames)
in (catMaybes fileNames, nonFileNames)
parse plugin args =
-- | Dispatch on a given list of response files.
case getOpt Permute (options plugin []) args of
dispatchOnResponseFiles :: NonEmpty FilePath -> IO ()
(_,_,errs) | not (null errs)
dispatchOnResponseFiles fps = do
-> do putStrLn "hpc failed:"
forM_ fps $ \responseFileName -> do
sequence_ [ putStr (" " ++ err)
exists <- doesPathExist responseFileName
| err <- errs
when (not exists) $ do
]
putStrLn $ "Response File '" <> responseFileName <> "' does not exist"
putStrLn $ "\n"
exitFailure
command_usage plugin
exitFailure
-- read all Response Files
(o,ns,_) -> do
responseFileNamesAndText :: NonEmpty (FilePath, String) <-
let flags = final_flags plugin
forM fps $ \responseFileName ->
. foldr (.) id o
fmap (responseFileName, ) (readFile responseFileName)
$ init_flags plugin
forM_ responseFileNamesAndText $ \(responseFileName, responseFileText) ->
implementation plugin flags ns
-- parse first word of Response File, which should be a command
case uncons $ words responseFileText of
main :: IO ()
Nothing -> do
main = do
putStrLn $ "Response File '" <> responseFileName <> "' has no command"
args <- getArgs
exitFailure
dispatch args
Just (responseFileCommand, args1) -> case lookup responseFileCommand hooks' of
 
-- check command for validity
 
-- It is important than a Response File cannot specify another Response File;
 
-- this is prevented
 
Nothing -> do
 
putStrLn $ "Response File '" <> responseFileName <>
 
"' command '" <> responseFileCommand <> "' invalid"
 
exitFailure
 
Just plugin -> do
 
putStrLn $ "Response File '" <> responseFileName <> "':"
 
dispatchOnPlugin plugin args1
 
 
-- | Dispatch on a given plugin and its arguments.
 
dispatchOnPlugin :: Plugin -> [String] -> IO ()
 
dispatchOnPlugin plugin args =
 
case getOpt Permute (options plugin []) args of
 
(_,_,errs) | not (null errs) -> do
 
putStrLn "hpc failed:"
 
sequence_ [ putStr (" " <> err) | err <- errs ]
 
putStrLn $ "\n"
 
command_usage plugin
 
exitFailure
 
(o,ns,_) -> do
 
let flags = final_flags plugin
 
. foldr (.) id o
 
$ init_flags plugin
 
implementation plugin flags ns
------------------------------------------------------------------------------
------------------------------------------------------------------------------
@@ -177,7 +173,7 @@ help_plugin :: Plugin
@@ -177,7 +173,7 @@ help_plugin :: Plugin
help_plugin = Plugin { name = "help"
help_plugin = Plugin { name = "help"
, usage = "[<HPC_COMMAND>]"
, usage = "[<HPC_COMMAND>]"
, summary = "Display help for hpc or a single command"
, summary = "Display help for hpc or a single command"
, options = help_options
, options = id
, implementation = help_main
, implementation = help_main
, init_flags = default_flags
, init_flags = default_flags
, final_flags = default_final_flags
, final_flags = default_final_flags
@@ -196,9 +192,6 @@ help_main _ (sub_txt:_) = do
@@ -196,9 +192,6 @@ help_main _ (sub_txt:_) = do
command_usage plugin'
command_usage plugin'
exitWith ExitSuccess
exitWith ExitSuccess
help_options :: FlagOptSeq
help_options = id
------------------------------------------------------------------------------
------------------------------------------------------------------------------
version_plugin :: Plugin
version_plugin :: Plugin
Loading