<commit_before>module Mueval.ArgsParse (Options(..), interpreterOpts, getOptions) where

import Control.Monad (liftM)
import System.Console.GetOpt
import System.Environment (getArgs)

import qualified Codec.Binary.UTF8.String as Codec (decodeString)

import Mueval.Context (defaultModules)

-- | See the results of --help for information on what each option means.
data Options = Options
 { timeLimit :: Int
   , modules :: [String]
   , expression :: String
   , loadFile :: String
   , user :: String
   , printType :: Bool
   , extensions :: Bool
   , noimports :: Bool
   , rlimits :: Bool
 } deriving Show

defaultOptions :: Options
defaultOptions = Options { expression = ""
                           , modules = defaultModules
                           , timeLimit = 5
                           , user = ""
                           , loadFile = ""
                           , printType = False
                           , extensions = False
                           , noimports = False
                           , rlimits = False }

options :: [OptDescr (Options -> Options)]
options = [Option "p"     ["password"]
                      (ReqArg (\u opts -> opts {user = u}) "PASSWORD")
                      "The password for the mubot account. If this is set, mueval will attempt to setuid to the mubot user. This is optional, as it requires the mubot user to be set up properly. (Currently a null-op.)",
           Option "t"     ["timelimit"]
                      (ReqArg (\t opts -> opts { timeLimit = (read t :: Int) }) "TIME")
                      "Time limit for compilation and evaluation",

           Option "l"     ["loadfile"]
                      (ReqArg (\e opts -> opts { loadFile = e}) "FILE")
                      "A local file for Mueval to load, providing definitions. Contents are trusted! Do not put anything dubious in it!",

           Option "m"     ["module"]
                      (ReqArg (\m opts -> opts { modules = m:modules opts}) "MODULE")
                      "A module we should import functions from for evaluation. (Can be given multiple times.)",
           Option "n"     ["noimports"]
                      (NoArg (\opts -> opts { noimports = True}))
                      "Whether to import any default modules, such as Prelude; this is useful if you are loading a file which, say, redefines Prelude operators.",
           Option "E"     ["Extensions"]
                      (NoArg (\opts -> opts { extensions = True}))
                      "Whether to enable the Glasgow extensions to Haskell '98. Defaults to false, but enabling is useful for QuickCheck.",
           Option "e"     ["expression"]
                      (ReqArg (\e opts -> opts { expression = e}) "EXPRESSION")
                      "The expression to be evaluated.",
           Option "i"     ["inferred-type"]
                      (NoArg (\opts -> opts { printType = True}))
                      "Whether to enable printing of inferred type and the expression (as Mueval sees it). Defaults to false.",
           Option "r"     ["rlimits"]
                      (NoArg (\opts -> opts { rlimits = True}))
                      "Enable resource limits (using POSIX rlimits). Mueval does not by default since rlimits are broken on many systems." ]

interpreterOpts :: [String] -> IO (Options, [String])
interpreterOpts argv =
       case getOpt Permute options argv of
          (o,n,[]) -> return (foldl (flip id) defaultOptions o, n)
          (_,_,er) -> ioError $ userError (concat er ++ usageInfo header options)
      where header = "Usage: mueval [OPTION...] --expression EXPRESSION..."

-- | Just give us the end result options; this handles I/O and parsing for
-- us. Bonus points for handling UTF.
getOptions :: IO Options
getOptions = do input <- liftM (map Codec.decodeString) getArgs
                (opts,_) <- interpreterOpts $ input
                return opts<commit_msg>Mueval.ArgsParse, main.hs: refactor to push IO further up the stack<commit_after>module Mueval.ArgsParse (Options(..), interpreterOpts, getOptions) where

import System.Console.GetOpt

import qualified Codec.Binary.UTF8.String as Codec (decodeString)

import Mueval.Context (defaultModules)

-- | See the results of --help for information on what each option means.
data Options = Options
 { timeLimit :: Int
   , modules :: [String]
   , expression :: String
   , loadFile :: String
   , user :: String
   , printType :: Bool
   , extensions :: Bool
   , noimports :: Bool
   , rlimits :: Bool
 } deriving Show

defaultOptions :: Options
defaultOptions = Options { expression = ""
                           , modules = defaultModules
                           , timeLimit = 5
                           , user = ""
                           , loadFile = ""
                           , printType = False
                           , extensions = False
                           , noimports = False
                           , rlimits = False }

options :: [OptDescr (Options -> Options)]
options = [Option "p"     ["password"]
                      (ReqArg (\u opts -> opts {user = u}) "PASSWORD")
                      "The password for the mubot account. If this is set, mueval will attempt to setuid to the mubot user. This is optional, as it requires the mubot user to be set up properly. (Currently a null-op.)",
           Option "t"     ["timelimit"]
                      (ReqArg (\t opts -> opts { timeLimit = (read t :: Int) }) "TIME")
                      "Time limit for compilation and evaluation",

           Option "l"     ["loadfile"]
                      (ReqArg (\e opts -> opts { loadFile = e}) "FILE")
                      "A local file for Mueval to load, providing definitions. Contents are trusted! Do not put anything dubious in it!",

           Option "m"     ["module"]
                      (ReqArg (\m opts -> opts { modules = m:modules opts}) "MODULE")
                      "A module we should import functions from for evaluation. (Can be given multiple times.)",
           Option "n"     ["noimports"]
                      (NoArg (\opts -> opts { noimports = True}))
                      "Whether to import any default modules, such as Prelude; this is useful if you are loading a file which, say, redefines Prelude operators.",
           Option "E"     ["Extensions"]
                      (NoArg (\opts -> opts { extensions = True}))
                      "Whether to enable the Glasgow extensions to Haskell '98. Defaults to false, but enabling is useful for QuickCheck.",
           Option "e"     ["expression"]
                      (ReqArg (\e opts -> opts { expression = e}) "EXPRESSION")
                      "The expression to be evaluated.",
           Option "i"     ["inferred-type"]
                      (NoArg (\opts -> opts { printType = True}))
                      "Whether to enable printing of inferred type and the expression (as Mueval sees it). Defaults to false.",
           Option "r"     ["rlimits"]
                      (NoArg (\opts -> opts { rlimits = True}))
                      "Enable resource limits (using POSIX rlimits). Mueval does not by default since rlimits are broken on many systems." ]

interpreterOpts :: [String] -> (Options, [String])
interpreterOpts argv =
       case getOpt Permute options argv of
          (o,n,[]) -> (foldl (flip id) defaultOptions o, n)
          (_,_,er) -> error $ (concat er ++ usageInfo header options)
      where header = "Usage: mueval [OPTION...] --expression EXPRESSION..."

-- | Just give us the end result options; this parsing for
--   us. Bonus points for handling UTF.
getOptions :: [String] -> Options
getOptions = fst . interpreterOpts . map Codec.decodeString
{'fraction_non_alphanumeric': 0.1022020725388601, 'fraction_numerical': 0.0010362694300518134, 'mean_word_length': 1.804576825281511, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 30, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3919764', 'n_tokens_mistral': 1962, 'n_tokens_neox': 1880, 'n_words': 775}