<commit_before>
module System.Console.CmdArgs.Explicit.Type where

import Control.Arrow
import Control.Monad
import Data.Char
import Data.List
import Data.Maybe
import Data.Monoid


-- | A name, either the name of a flag (@--/foo/@) or the name of a mode.
type Name = String

-- | A help message that goes with either a flag or a mode.
type Help = String

-- | The type of a flag, i.e. @--foo=/TYPE/@.
type FlagHelp = String


---------------------------------------------------------------------
-- UTILITY

-- | Parse a boolean, accepts as True: true yes on enabled 1. 
parseBool :: String -> Maybe Bool
parseBool s | ls `elem` true  = Just True
            | ls `elem` false = Just False
            | otherwise = Nothing
    where
        ls = map toLower s
        true = ["true","yes","on","enabled","1"]
        false = ["false","no","off","disabled","0"]


---------------------------------------------------------------------
-- GROUPS

-- | A group of items (modes or flags). The items are treated as a list, but the
--   group structure is used when displaying the help message.
data Group a = Group
    {groupUnnamed :: [a] -- ^ Normal items.
    ,groupHidden :: [a] -- ^ Items that are hidden (not displayed in the help message).
    ,groupNamed :: [(Help, [a])] -- ^ Items that have been grouped, along with a description of each group.
    } deriving Show 

instance Functor Group where
    fmap f (Group a b c) = Group (map f a) (map f b) (map (second $ map f) c)

instance Monoid (Group a) where
    mempty = Group [] [] []
    mappend (Group x1 x2 x3) (Group y1 y2 y3) = Group (x1++y1) (x2++y2) (x3++y3)

-- | Convert a group into a list.
fromGroup :: Group a -> [a]
fromGroup (Group x y z) = x ++ y ++ concatMap snd z

-- | Convert a list into a group, placing all fields in 'groupUnnamed'.
toGroup :: [a] -> Group a
toGroup x = Group x [] []


---------------------------------------------------------------------
-- TYPES

showRecord x ys = x ++ " {" ++ intercalate ", " ys ++ "}"
a *= b = a ++ " = " ++ show b


-- | A mode. Each mode has three main features:
--
--   * A list of submodes ('modeGroupModes')
--
--   * A list of flags ('modeGroupFlags')
--
--   * Optionally an unnamed argument ('modeArgs')
data Mode a = Mode
    {modeGroupModes :: Group (Mode a) -- ^ The available sub-modes
    ,modeNames :: [Name] -- ^ The names assigned to this mode (for the root mode, this name is used as the program name)
    ,modeValue :: a -- ^ Value to start with
    ,modeCheck :: a -> Either String a -- checking a value is correct
    ,modeHelp :: Help -- ^ Help text
    ,modeHelpSuffix :: [String] -- ^ A longer help suffix displayed after a mode
    ,modeArgs :: Maybe (Arg a) -- ^ An unnamed argument
    ,modeGroupFlags :: Group (Flag a) -- ^ Groups of flags
    }

-- | Extract the modes from a 'Mode'
modeModes :: Mode a -> [Mode a]
modeModes = fromGroup . modeGroupModes

-- | Extract the flags from a 'Mode'
modeFlags :: Mode a -> [Flag a]
modeFlags = fromGroup . modeGroupFlags

-- | The 'FlagInfo' type has the following meaning:
--
--
-- >              FlagReq     FlagOpt      FlagOptRare/FlagNone
-- > -xfoo        -x=foo      -x=foo       -x= -foo
-- > -x foo       -x=foo      -x foo       -x= foo
-- > -x=foo       -x=foo      -x=foo       -x=foo
-- > --xx foo     --xx=foo    --xx foo     --xx foo
-- > --xx=foo     --xx=foo    --xx=foo     --xx=foo
data FlagInfo
    = FlagReq             -- ^ Required argument
    | FlagOpt String      -- ^ Optional argument
    | FlagOptRare String  -- ^ Optional argument that requires an = before the value
    | FlagNone            -- ^ No argument
      deriving (Eq,Ord,Show)<commit_msg>Improve the documentation for modeCheck<commit_after>
module System.Console.CmdArgs.Explicit.Type where

import Control.Arrow
import Control.Monad
import Data.Char
import Data.List
import Data.Maybe
import Data.Monoid


-- | A name, either the name of a flag (@--/foo/@) or the name of a mode.
type Name = String

-- | A help message that goes with either a flag or a mode.
type Help = String

-- | The type of a flag, i.e. @--foo=/TYPE/@.
type FlagHelp = String


---------------------------------------------------------------------
-- UTILITY

-- | Parse a boolean, accepts as True: true yes on enabled 1. 
parseBool :: String -> Maybe Bool
parseBool s | ls `elem` true  = Just True
            | ls `elem` false = Just False
            | otherwise = Nothing
    where
        ls = map toLower s
        true = ["true","yes","on","enabled","1"]
        false = ["false","no","off","disabled","0"]


---------------------------------------------------------------------
-- GROUPS

-- | A group of items (modes or flags). The items are treated as a list, but the
--   group structure is used when displaying the help message.
data Group a = Group
    {groupUnnamed :: [a] -- ^ Normal items.
    ,groupHidden :: [a] -- ^ Items that are hidden (not displayed in the help message).
    ,groupNamed :: [(Help, [a])] -- ^ Items that have been grouped, along with a description of each group.
    } deriving Show 

instance Functor Group where
    fmap f (Group a b c) = Group (map f a) (map f b) (map (second $ map f) c)

instance Monoid (Group a) where
    mempty = Group [] [] []
    mappend (Group x1 x2 x3) (Group y1 y2 y3) = Group (x1++y1) (x2++y2) (x3++y3)

-- | Convert a group into a list.
fromGroup :: Group a -> [a]
fromGroup (Group x y z) = x ++ y ++ concatMap snd z

-- | Convert a list into a group, placing all fields in 'groupUnnamed'.
toGroup :: [a] -> Group a
toGroup x = Group x [] []


---------------------------------------------------------------------
-- TYPES

showRecord x ys = x ++ " {" ++ intercalate ", " ys ++ "}"
a *= b = a ++ " = " ++ show b


-- | A mode. Each mode has three main features:
--
--   * A list of submodes ('modeGroupModes')
--
--   * A list of flags ('modeGroupFlags')
--
--   * Optionally an unnamed argument ('modeArgs')
data Mode a = Mode
    {modeGroupModes :: Group (Mode a) -- ^ The available sub-modes
    ,modeNames :: [Name] -- ^ The names assigned to this mode (for the root mode, this name is used as the program name)
    ,modeValue :: a -- ^ Value to start with
    ,modeCheck :: a -> Either String a -- ^ Check a mode is correct, after it has been constructed
    ,modeHelp :: Help -- ^ Help text
    ,modeHelpSuffix :: [String] -- ^ A longer help suffix displayed after a mode
    ,modeArgs :: Maybe (Arg a) -- ^ An unnamed argument
    ,modeGroupFlags :: Group (Flag a) -- ^ Groups of flags
    }

-- | Extract the modes from a 'Mode'
modeModes :: Mode a -> [Mode a]
modeModes = fromGroup . modeGroupModes

-- | Extract the flags from a 'Mode'
modeFlags :: Mode a -> [Flag a]
modeFlags = fromGroup . modeGroupFlags

-- | The 'FlagInfo' type has the following meaning:
--
--
-- >              FlagReq     FlagOpt      FlagOptRare/FlagNone
-- > -xfoo        -x=foo      -x=foo       -x= -foo
-- > -x foo       -x=foo      -x foo       -x= foo
-- > -x=foo       -x=foo      -x=foo       -x=foo
-- > --xx foo     --xx=foo    --xx foo     --xx foo
-- > --xx=foo     --xx=foo    --xx=foo     --xx=foo
data FlagInfo
    = FlagReq             -- ^ Required argument
    | FlagOpt String      -- ^ Optional argument
    | FlagOptRare String  -- ^ Optional argument that requires an = before the value
    | FlagNone            -- ^ No argument
      deriving (Eq,Ord,Show)
{'fraction_non_alphanumeric': 0.18346637802733054, 'fraction_numerical': 0.004058990664321472, 'mean_word_length': 1.9205847491110233, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 27, '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': '5202374', 'n_tokens_mistral': 2239, 'n_tokens_neox': 2182, 'n_words': 890}