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.Maybe (isJust, isNothing)
15 import System.Console.GetOpt
16 import System.Environment (getArgs)
20 -- A record containing values for all available options.
21 data Options = Options { opt_help :: Bool,
22 opt_from :: Maybe String,
23 opt_to :: Maybe String }
26 -- This constructs an instance of Options, with each of its members
27 -- set to default values.
28 default_options :: Options
29 default_options = Options { opt_help = False,
34 -- The options list that we construct associates a function with each
35 -- option. This function is responsible for updating an Options record
36 -- with the appropriate value.
38 -- For more information and an example of this idiom, see,
40 -- http://www.haskell.org/haskellwiki/High-level_option_handling_with_GetOpt
42 options :: [OptDescr (Options -> IO Options)]
44 [ Option ['h'][] (NoArg set_help) "Prints this help message.",
45 Option ['t'][] (ReqArg set_to "email_address") "Send tweets TO email_address.",
46 Option ['f'][] (ReqArg set_from "email_address") "Send tweets FROM email_address."
50 set_help :: Options -> IO Options
52 return opts { opt_help = True }
54 set_to :: String -> Options -> IO Options
56 return opts { opt_to = Just arg }
58 set_from :: String -> Options -> IO Options
59 set_from arg opts = do
60 return opts { opt_from = Just arg }
65 usage = "Usage: twat [-t to_address] [-f from_address] <username1> [username2, [username3]...]"
68 -- The usage header, and all available flags (as generated by GetOpt)
70 help_text = usageInfo usage options
73 -- Return a list of options.
74 parse_options :: IO Options
77 let (actions, _, _) = getOpt Permute options argv
79 -- This will execute each of the functions contained in our options
80 -- list, one after another, on a default_options record. The end
81 -- result should be an Options instance with all of its members set
83 opts <- foldl (>>=) (return default_options) actions
88 username_errors :: IO [String]
91 let (_, usernames, _) = getOpt Permute options argv
94 then return ["No usernames provided."]
98 to_errors :: IO [String]
100 toaddr <- to_email_address
101 fromaddr <- from_email_address
102 if (isNothing toaddr) && (isJust fromaddr)
103 then return ["\"From\" address specified without \"To\" address."]
106 from_errors :: IO [String]
108 toaddr <- to_email_address
109 fromaddr <- from_email_address
110 if (isJust toaddr) && (isNothing fromaddr)
111 then return ["\"To\" address specified without \"From\" address."]
115 format_error :: String -> String
116 format_error err = "ERROR: " ++ err ++ "\n"
119 -- Return a list of errors.
120 parse_errors :: IO [String]
123 let (_, _, errors) = getOpt Permute options argv
124 errs_username <- username_errors
126 errs_from <- from_errors
127 return $ map format_error (errors ++ errs_username ++ errs_to ++ errs_from)
129 -- Is the help option set?
132 opts <- parse_options
133 return (opt_help opts)
136 to_email_address :: IO (Maybe String)
137 to_email_address = do
138 opts <- parse_options
141 from_email_address :: IO (Maybe String)
142 from_email_address = do
143 opts <- parse_options
144 return (opt_from opts)
147 parse_usernames :: IO [String]
150 let (_, usernames, _) = getOpt Permute options argv