{-# LANGUAGE DeriveDataTypeable #-} -- | The CommandLine module handles parsing of the command-line -- options. It should more or less be a black box, providing Main -- with only the information it requires. -- -- Which is why we're allowed all of this unsafe voodoo. -- module CommandLine ( Args(..), get_args ) where import System.Console.CmdArgs ( Ann, Annotate( (:=) ), Data, (+=), auto, cmdArgs_, def, details, explicit, groupname, help, helpArg, modes_, name, program, record, summary, versionArg ) -- Get the version from Cabal. import Paths_hath (version) import Data.Version (showVersion) -- | The name of our program. program_name :: String program_name = "hath" -- | A brief summary; displays the program name and version. my_summary :: String my_summary = program_name ++ "-" ++ (showVersion version) barriers_help :: String barriers_help = "(regexed mode) place barriers in front/back of the regex " ++ "to prevent e.g. '127.0.0.1' from matching '127.0.0.100'" normalize_help :: String normalize_help = "(reduced mode) normalize the output CIDRs, replacing any " ++ "masked bits by zeros; e.g. '127.0.0.1/8' -> '127.0.0.0/8'" sort_help :: String sort_help = "(reduced mode) sort the output CIDRs by their octets" -- | The Args type represents the possible command-line options. The -- duplication here seems necessary; CmdArgs' magic requires us to -- define some things explicitly. -- -- The application currently has five modes (if this number is wrong, -- it means I forgot to update the comment!), all of which take the -- same options and arguments. -- data Args = Regexed { barriers :: Bool, normalize :: Bool, sort :: Bool } | Reduced { barriers :: Bool, normalize :: Bool, sort :: Bool } | Duped { barriers :: Bool, normalize :: Bool, sort :: Bool } | Diffed { barriers :: Bool, normalize :: Bool, sort :: Bool } | Listed { barriers :: Bool, normalize :: Bool, sort :: Bool } deriving (Data, Show) -- | Description of the 'Regexed' mode. regexed_description :: String regexed_description = "Compute a regular expression matching the input CIDRs." -- | Description of the 'Reduced' mode. reduced_description :: String reduced_description = "Combine any redundant/adjacent CIDR blocks into one." -- | Description of the 'Duped' mode. duped_description :: String duped_description = "Display what would be removed by 'reduced'." -- | Description of the 'Diffed' mode. diffed_description :: String diffed_description = "Display both additions and deletions in a diff-like format." -- | Description of the 'Listed' mode. listed_description :: String listed_description = "Enumerate the IP addresses contained within the input CIDRs." -- | We use explicit annotation here because if we use the magic -- annotation, we have to duplicate the same argument definitions six -- times. -- arg_spec :: Annotate Ann arg_spec = modes_ [regexed += auto, reduced, duped, diffed, listed] += program program_name += summary my_summary += helpArg [explicit, name "help", name "h", groupname "Common flags"] += versionArg [explicit, name "version", name "v", groupname "Common flags"] where make_mode :: (Bool -> Bool -> Bool -> Args) -> String -> (Annotate Ann) make_mode ctor desc = record (ctor def def def) [ barriers := def += groupname "Common flags" += help barriers_help, normalize := def += groupname "Common flags" += help normalize_help, sort := def += groupname "Common flags" += help sort_help ] += details [" " ++ desc] regexed = make_mode Regexed regexed_description reduced = make_mode Reduced reduced_description duped = make_mode Duped duped_description diffed = make_mode Diffed diffed_description listed = make_mode Listed listed_description -- | This is the public interface; i.e. what main() should use to get -- the command-line arguments. get_args :: IO Args get_args = cmdArgs_ arg_spec