rhbzquery-0.2: src/ParseArg.hs
module ParseArg (
argHelp,
readBzQueryArg,
ArgType(..),
Operator(..),
showOp,
ProductVersion(..),
statusList
)
where
import Control.Applicative ((<|>))
import Data.Char
import Data.List.Extra as L
import Data.Version.Extra
import Numeric.Natural
argHelp :: String
argHelp = "[COMPONENT|STATUS|PRODUCTVERSION|FIELD=VALUE|FIELDopVALUE]..."
data Operator = Equals | NotEqual
| Contains | NotContain
| ContainsCase
| Regexp |NotRegexp
| ContainsAll | NotContainAll
| ContainsWords | NotContainWords
-- | ContentMatches | ContentNotMatch
deriving Eq
showOp :: Operator -> String
showOp Equals = "equals"
showOp NotEqual = "notequals"
showOp Contains = "substring"
showOp NotContain = "notsubstring"
showOp ContainsCase = "casesubstring"
showOp Regexp = "regexp"
showOp NotRegexp = "notregexp"
showOp ContainsAll = "allwordssubstr"
showOp NotContainAll = "nowordssubstr"
showOp ContainsWords = "allwords"
showOp NotContainWords = "nowords"
--showOp IsEmpty = "isempty"
--showOp IsNotEmpty = "isnotempty"
data ArgType = ArgProdVer ProductVersion
| ArgStatusAll
| ArgParameter String Operator String
| ArgParameterEmpty String Bool
| ArgOther String
readBzQueryArg :: String -> Maybe ArgType
readBzQueryArg s =
ArgProdVer <$> readProductVersion s <|>
parseStatus s <|>
parseParam s <|>
pure (ArgOther s)
data ProductVersion = Fedora (Maybe Natural)
| Rawhide
| EPEL (Maybe Natural)
| RHEL Version
readProductVersion :: String -> Maybe ProductVersion
readProductVersion "fedora" = Just (Fedora Nothing)
readProductVersion "rawhide" = Just Rawhide
readProductVersion ('f':ver) | all isDigit ver = Just $ Fedora (Just (read ver :: Natural))
readProductVersion "epel" = Just (EPEL Nothing)
readProductVersion ('e':'p':'e':'l':v) | all isDigit v = Just (EPEL (Just (read v :: Natural)))
readProductVersion ('r':'h':'e':'l':ver) = Just $ RHEL (readVersion ver)
readProductVersion _ = Nothing
statusList :: [String]
statusList = ["NEW", "ASSIGNED", "POST", "MODIFIED", "ON_QA", "VERIFIED", "RELEASE_PENDING", "CLOSED"]
parseStatus :: String -> Maybe ArgType
parseStatus s =
let caps = upper s in
if caps == "ALL"
then Just ArgStatusAll
else
ArgParameter "bug_status" Equals <$> find (== upper s) statusList
parseParam :: String -> Maybe ArgType
parseParam ps =
parseParamWith "!=~" NotRegexp <|>
parseParamWith "=~" Regexp <|>
parseParamWith "!=" NotEqual <|>
parseParamWith "=" Equals <|>
parseParamWith "!~" NotContain <|>
parseParamWith "~a~" ContainsAll <|>
parseParamWith "!a~" NotContainAll <|>
parseParamWith "~c~" ContainsCase <|>
parseParamEmpty "~e~" True <|>
parseParamEmpty "!e~" False <|>
parseParamWith "~w~" ContainsWords <|>
parseParamWith "!w~" NotContainWords <|>
-- parseParamWith "~m~" ContentMatches <|>
-- parseParamWith "!m~" ContentNotMatch <|>
parseParamWith "~" Contains
where
parseParamWith :: String -> Operator -> Maybe ArgType
parseParamWith op oper =
case splitOn op ps of
[a,b] -> if null a || null b
then error $ "bad parameter: " ++ ps
else Just (ArgParameter a oper b)
_ -> Nothing
parseParamEmpty :: String -> Bool -> Maybe ArgType
parseParamEmpty op empty =
case stripSuffix op ps of
Just a -> if null a
then error $ "bad parameter: " ++ ps
else Just (ArgParameterEmpty a empty)
_ -> Nothing