aboutsummaryrefslogtreecommitdiffstats
path: root/app/Issue
diff options
context:
space:
mode:
authorLibravatar Alexander Foremny <aforemny@posteo.de>2023-10-04 16:23:30 +0200
committerLibravatar Alexander Foremny <aforemny@posteo.de>2023-10-04 16:23:30 +0200
commitc7225c15870f6a365f8435166b9113f66393e7c1 (patch)
treed53583c1f81e3c16303c8927c27c53686551da9f /app/Issue
parent2b93e0bce102d7ccf8402b4506be9e55698f2ea9 (diff)
add --filter, filter by tags
Diffstat (limited to 'app/Issue')
-rw-r--r--app/Issue/Filter.hs59
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