1 -- The CommandLine module handles parsing of the command-line options.
2 -- It should more or less be a black box, providing Main with only the
3 -- information it requires.
14 import Data.Char(toLower)
15 import System.Console.GetOpt
16 import System.Environment (getArgs)
20 lowercase :: String -> String
21 lowercase = map toLower
24 -- The application currently has three modes. The default, Regex, will
25 -- compute a regular expression matching the input CIDRs. Reduce, on
26 -- the other hand, will combine any redundant/adjacent CIDR blocks
27 -- into one. Dupe will show you what would be removed by Reduce.
28 data Mode = Regex | Reduce | Dupe
31 -- A record containing values for all available options.
32 data Options = Options { opt_help :: Bool,
33 opt_input :: IO String }
36 -- This constructs an instance of Options, with each of its members
37 -- set to default values.
38 default_options :: Options
39 default_options = Options { opt_help = False,
40 opt_input = getContents }
43 -- The options list that we construct associates a function with each
44 -- option. This function is responsible for updating an Options record
45 -- with the appropriate value.
47 -- For more information and an example of this idiom, see,
49 -- http://www.haskell.org/haskellwiki/High-level_option_handling_with_GetOpt
51 options :: [OptDescr (Options -> IO Options)]
53 [ Option ['h'][] (NoArg set_help) "Prints this help message.",
54 Option ['i'][] (ReqArg set_input "FILE") "Read FILE instead of stdin." ]
56 -- Takes an Options as an argument, and sets its opt_help member to
58 set_help :: Options -> IO Options
60 return opts { opt_help = True }
63 -- If the input file option is set, this function will update the
64 -- passed Options record with a new function for opt_input. The
65 -- default opt_input is to read from stdin, but if this option is set,
66 -- we replace that with readFile.
67 set_input :: String -> Options -> IO Options
68 set_input arg opts = do
69 return opts { opt_input = readFile arg }
74 usage = "Usage: hath [regexed|reduced|duplicated] [-h] [-i FILE]"
77 -- The usage header, and all available flags (as generated by GetOpt)
79 help_text = usageInfo usage options
82 -- Return a list of options.
83 parse_options :: IO Options
86 let (actions, _, _) = getOpt Permute options argv
88 -- This will execute each of the functions contained in our options
89 -- list, one after another, on a default_options record. The end
90 -- result should be an Options instance with all of its members set
92 opts <- foldl (>>=) (return default_options) actions
97 -- Return the mode if one was given.
101 let (_, non_options, _) = getOpt Permute options argv
102 if (null non_options)
107 -- Some non-option was given, but were any of them modes?
108 case (lowercase (non_options !! 0)) of
109 "regex" -> return Regex
110 "regexed" -> return Regex
111 "reduce" -> return Reduce
112 "reduced" -> return Reduce
113 "dupe" -> return Dupe
114 "duplicated" -> return Dupe
120 -- Return a list of errors.
121 parse_errors :: IO [String]
124 let (_, _, errors) = getOpt Permute options argv
129 -- Is the help option set?
132 opts <- parse_options
133 return (opt_help opts)
136 -- Return our input function, getContents by default, or readFile if
137 -- the input file option was set.
138 input_function :: IO (IO String)
140 opts <- parse_options
141 return (opt_input opts)