diff options
Diffstat (limited to 'app/Issue/Filter.hs')
-rw-r--r-- | app/Issue/Filter.hs | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/app/Issue/Filter.hs b/app/Issue/Filter.hs new file mode 100644 index 0000000..0ce945d --- /dev/null +++ b/app/Issue/Filter.hs @@ -0,0 +1,59 @@ +{-# LANGUAGE OverloadedRecordDot #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE ViewPatterns #-} + +module Issue.Filter + ( Filter, + filterOption, + 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) + +filterOption :: O.Parser [Filter] +filterOption = + 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 |