module Issue.Filter ( Filter, filterArg, applyFilter, ) where import Control.Arrow (second) import Data.Text (Text) import Data.Text qualified as T import Issue (Issue (..)) import Issue.Tag (Tag (..)) import Options.Applicative qualified as O data Filter = ExcludeByTag Text (Maybe Text) | IncludeByTag Text (Maybe Text) deriving (Show) filterArg :: O.Parser [Filter] filterArg = O.many ( O.option (O.maybeReader (parse . T.pack)) ( O.long "filter" <> O.short 'f' <> O.metavar "FILTER" <> O.help "Filters selected issues. Examples: @assigned, !@assigned joe" ) ) where parse s | "@" `T.isPrefixOf` s = Just (uncurry IncludeByTag (splitValue (T.drop 1 s))) | "!@" `T.isPrefixOf` s = Just (uncurry ExcludeByTag (splitValue (T.drop 2 s))) | otherwise = Nothing splitValue :: Text -> (Text, Maybe Text) splitValue s = case second T.strip (T.breakOn " " s) of (k, "") -> (k, Nothing) (k, v) -> (k, Just v) applyFilter :: [Filter] -> Issue -> Bool applyFilter [] _ = True applyFilter (IncludeByTag k v : fs) i = applyByTag k v i && applyFilter fs i applyFilter (ExcludeByTag k v : fs) i = not (applyByTag k v i) && applyFilter fs i applyByTag :: Text -> Maybe Text -> Issue -> Bool applyByTag k v i = any ((&&) <$> matchKey <*> matchValue) i.tags where matchKey (Tag k' _) = k' == k matchValue (Tag _ v') = maybe True ((==) v') v