\subsection{Option handling}
You know the drill...
\begin{code}
module RBR.Options (version,usage,getOptions,Opts(..),parseargs,MaskWith(..)) where
import System.Environment (getArgs)
import System.Console.GetOpt
import System.Exit
version, usagemsg :: String
version = "0.8.4"
usagemsg = "Usage: rbr [-k <k>] [options] FILE.."
getOptions :: IO ([Opts -> IO Opts], [String], [String])
getOptions = getArgs >>= (return . getOpt Permute options)
usage :: [String] -> String
usage errs = usageInfo (concat errs ++ usagemsg) options
data MaskWith = Lower | Ns | Xs
options :: [OptDescr (Opts -> IO Opts)]
options = [Option ['k'] ["word-size"] (ReqArg (\arg opt -> return opt { kval = read arg }) "Int") "Word size"
,Option [] ["sparse-keys"] (ReqArg (\arg opt -> return opt { skip = read arg }) "Int") "Skip length"
,Option ['N'] ["no-stats"] (NoArg (\opt -> return opt { stats = False })) "Omit statistical masking"
,Option ['g'] ["gapclosing"] (ReqArg (\arg opt -> return opt { gap = read arg }) "Int") "Close gaps"
,Option ['s'] ["stringency"] (ReqArg (\arg opt -> return opt { string = read arg }) "Float") "Mask stringecy"
,Option ['t'] ["threshold"] (ReqArg (\arg opt -> return opt { thresh = read arg }) "Float") "Mask threshold"
,Option [] ["preserve-lower-case"] (NoArg (\opt -> return opt { preserve_lower = True })) "Preserve lower case in input sequences"
,Option ['D'] ["distribution"] (NoArg (\opt -> return opt { distr = True })) "Distribution output"
,Option ['l'] ["library"] (ReqArg (\arg opt -> return opt {lib = Just arg}) "file") "Mask words from library"
,Option ['L'] ["lower-case"] (NoArg (\opt -> return opt { lower = Lower })) "Mask using lower case letters"
,Option ['n'] ["n-mask"] (NoArg (\opt -> return opt { lower = Ns })) "Mask using 'n's"
,Option ['x'] ["x-mask"] (NoArg (\opt -> return opt { lower = Xs })) "Mask using 'X's"
,Option [] ["server"] (NoArg (\opt -> return opt { server = True })) "Run in server mode"
,Option ['o'] ["output-file"] (ReqArg (\arg opt -> return opt { ofile = Just arg }) "file") "Output file"
,Option ['v'] ["verbose"] (NoArg (\opt -> return opt { verb = True })) "Display progress"
,Option ['h'] ["help"] (NoArg (\_ -> do {putStrLn $ usage []; exitWith ExitSuccess })) "Display help"
,Option ['V'] ["version"] (NoArg (\_ -> do {putStrLn $ "rbr version "++version; exitWith ExitSuccess })) "Display version"
]
data Opts = Opts { kval :: Int, ofile :: Maybe FilePath
, stats, preserve_lower :: Bool
, thresh, string :: Double
, gap :: Int
, lower :: MaskWith
, distr, verb, server :: Bool
, lib :: Maybe FilePath
, skip :: Int
}
defaultopts :: Opts
defaultopts = Opts 16 Nothing True False 0 0 0 Lower False False False Nothing 0
parseargs :: [Opts -> IO Opts] -> IO Opts
parseargs args = foldl (>>=) (return defaultopts) args >>= fixS >>= fixT
where fixS opts = return $ case (string opts,lower opts) of
(0,Ns) -> opts { string = 2.0 }
(0,Xs) -> opts { string = 2.0 }
(0,Lower) -> opts { string = 1.1 }
_ -> opts
fixT opts = return $ case (thresh opts,lower opts) of
(0,Ns) -> opts { thresh = 8.0 }
(0,Xs) -> opts { thresh = 8.0 }
(0,Lower) -> opts { thresh = 5.0 }
_ -> opts
\end{code}