]> gitweb.michael.orlitzky.com - hath.git/blob - src/CommandLine.hs
Add a CommandLine module for parsing command-line options.
[hath.git] / src / CommandLine.hs
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.
4
5 module CommandLine
6 ( help_set,
7 help_text,
8 input_function,
9 parse_errors
10 ) where
11
12 import System.Console.GetOpt
13 import System.Environment (getArgs)
14
15
16 -- A record containing values for all available options.
17 data Options = Options { opt_help :: Bool,
18 opt_input :: IO String }
19
20 -- This constructs an instance of Options, with each of its members
21 -- set to default values.
22 default_options :: Options
23 default_options = Options { opt_help = False,
24 opt_input = getContents }
25
26
27 -- The options list that we construct associates a function with each
28 -- option. This function is responsible for updating an Options record
29 -- with the appropriate value.
30 --
31 -- For more information and an example of this idiom, see,
32 --
33 -- http://www.haskell.org/haskellwiki/High-level_option_handling_with_GetOpt
34 --
35 options :: [OptDescr (Options -> IO Options)]
36 options =
37 [ Option ['h'][] (NoArg set_help) "Prints this help message.",
38 Option ['i'][] (ReqArg set_input "FILE") "Read FILE instead of stdin." ]
39
40 -- Takes an Options as an argument, and sets its opt_help member to
41 -- True.
42 set_help :: Options -> IO Options
43 set_help opts = do
44 return opts { opt_help = True }
45
46 -- If the input file option is set, this function will update the
47 -- passed Options record with a new function for opt_input. The
48 -- default opt_input is to read from stdin, but if this option is set,
49 -- we replace that with readFile.
50 set_input :: String -> Options -> IO Options
51 set_input arg opts = do
52 return opts { opt_input = readFile arg }
53
54 -- The usage header
55 usage :: String
56 usage = "Usage: hath [-h] [-i FILE]"
57
58
59 -- The usage header, and all available flags (as generated by GetOpt)
60 help_text :: String
61 help_text = usageInfo usage options
62
63
64 -- Return a tuple of options and errors.
65 parse_options :: IO (Options, [String])
66 parse_options = do
67 argv <- getArgs
68 let (actions, _, errors) = getOpt Permute options argv
69
70 -- This will execute each of the functions contained in our options
71 -- list, one after another, on a default_options record. The end
72 -- result should be an Options instance with all of its members set
73 -- correctly.
74 opts <- foldl (>>=) (return default_options) actions
75
76 return (opts, errors)
77
78
79 -- Return just the errors from parse_options.
80 parse_errors :: IO [String]
81 parse_errors = do
82 (_, errors) <- parse_options
83 return errors
84
85
86 -- Is the help option set?
87 help_set :: IO Bool
88 help_set = do
89 (opts, _) <- parse_options
90 return (opt_help opts)
91
92
93 -- Return our input function, getContents by default, or readFile if
94 -- the input file option was set.
95 input_function :: IO (IO String)
96 input_function = do
97 (opts, _) <- parse_options
98 return (opt_input opts)