aboutsummaryrefslogtreecommitdiffstats
path: root/app/Issue
diff options
context:
space:
mode:
Diffstat (limited to 'app/Issue')
-rw-r--r--app/Issue/Filter.hs23
-rw-r--r--app/Issue/Sort.hs32
-rw-r--r--app/Issue/TypedValue.hs33
3 files changed, 57 insertions, 31 deletions
diff --git a/app/Issue/Filter.hs b/app/Issue/Filter.hs
index c30a8e2..7501e35 100644
--- a/app/Issue/Filter.hs
+++ b/app/Issue/Filter.hs
@@ -9,11 +9,10 @@ import Control.Applicative (liftA2, (<|>))
import Data.Attoparsec.Text qualified as A
import Data.Text (Text)
import Data.Text qualified as T
-import Data.Time.Calendar (Day)
import Issue (Issue (..))
import Issue.Tag (tagKey, tagValue)
+import Issue.TypedValue (castDef)
import Options.Applicative qualified as O
-import Text.Read (readMaybe)
-- TODO Revise filter negation
--
@@ -121,7 +120,7 @@ simpleFilterPredicate (ByTag k v) i = any ((&&) <$> matchKey <*> matchValue) (i.
matchKey = (==) k . tagKey
matchValue t =
case (v, tagValue t) of
- (Just (o, v'), Just w') -> cast (op o) v' w'
+ (Just (o, v'), Just w') -> castDef False (op o) v' w'
(Just _, Nothing) -> False
(Nothing, _) -> True
@@ -131,21 +130,3 @@ op (Ge) = flip (>=)
op (Gt) = flip (>)
op (Le) = flip (<=)
op (Lt) = flip (<)
-
-data Type a where
- Date :: Type Day
- Int :: Type Int
- String :: Type Text
-
-cast :: (forall a. Ord a => a -> a -> Bool) -> (Text -> Text -> Bool)
-cast eq x y
- | Just x' <- castTo Date x, Just y' <- castTo Date y = eq x' y'
- | Just _ <- castTo Date x, Nothing <- castTo Date y = False
- | Just x' <- castTo Int x, Just y' <- castTo Int y = eq x' y'
- | Just _ <- castTo Int x, Nothing <- castTo Int y = False
- | otherwise = eq x y
-
-castTo :: Type a -> Text -> Maybe a
-castTo Date = readMaybe . T.unpack
-castTo Int = readMaybe . T.unpack
-castTo String = Just
diff --git a/app/Issue/Sort.hs b/app/Issue/Sort.hs
index 46f4a19..5499f9c 100644
--- a/app/Issue/Sort.hs
+++ b/app/Issue/Sort.hs
@@ -8,12 +8,12 @@ module Issue.Sort
where
import Data.List (sort, sortBy)
-import Data.Maybe (mapMaybe)
-import Data.Ord (comparing)
+import Data.Maybe (fromMaybe, mapMaybe)
import Data.Text (Text)
import Data.Text qualified as T
import Issue (Issue (..))
import Issue.Tag (Tag (..))
+import Issue.TypedValue (cast)
import Options.Applicative qualified as O
data Sort = Sort Order SortBy
@@ -57,12 +57,24 @@ applySorts cs = compose (defaultSort : cs)
toSort :: Sort -> ([Issue] -> [Issue])
toSort (Sort order sortBy') =
(if order == Desc then reverse else id)
- . sortBy (comparing (applySortBy sortBy'))
+ . sortBy (sortByCompare sortBy')
-applySortBy :: SortBy -> Issue -> [Text]
-applySortBy (SortByTag k) i =
- sort
- ( mapMaybe
- (\(Tag k' v) -> if k' == k then v else Nothing)
- (i.tags ++ i.internalTags)
- )
+sortByCompare :: SortBy -> (Issue -> Issue -> Ordering)
+sortByCompare (SortByTag k) i1 i2 =
+ compareList
+ (incomparableFirst (cast compare))
+ (sort $ tagValues k (i1.tags ++ i1.internalTags))
+ (sort $ tagValues k (i2.tags ++ i2.internalTags))
+
+tagValues :: Text -> [Tag] -> [Text]
+tagValues k = mapMaybe (\(Tag k' v) -> if k' == k then v else Nothing)
+
+compareList :: (a -> a -> Ordering) -> ([a] -> [a] -> Ordering)
+compareList _ [] _ = LT
+compareList _ _ [] = GT
+compareList g (a : as) (b : bs)
+ | g a b == EQ = compareList g as bs
+ | otherwise = g a b
+
+incomparableFirst :: (a -> a -> Maybe Ordering) -> (a -> a -> Ordering)
+incomparableFirst cmp a b = fromMaybe LT (cmp a b)
diff --git a/app/Issue/TypedValue.hs b/app/Issue/TypedValue.hs
new file mode 100644
index 0000000..9af04bb
--- /dev/null
+++ b/app/Issue/TypedValue.hs
@@ -0,0 +1,33 @@
+module Issue.TypedValue
+ ( Type (..),
+ cast,
+ castDef,
+ )
+where
+
+import Data.Maybe (fromMaybe)
+import Data.Text (Text)
+import Data.Text qualified as T
+import Data.Time.Calendar (Day)
+import Text.Read (readMaybe)
+
+data Type a where
+ Date :: Type Day
+ Int :: Type Int
+ String :: Type Text
+
+cast :: (forall a. Ord a => a -> a -> b) -> (Text -> Text -> Maybe b)
+cast eq x y
+ | Just x' <- castTo Date x, Just y' <- castTo Date y = Just (eq x' y')
+ | Just _ <- castTo Date x, Nothing <- castTo Date y = Nothing
+ | Just x' <- castTo Int x, Just y' <- castTo Int y = Just (eq x' y')
+ | Just _ <- castTo Int x, Nothing <- castTo Int y = Nothing
+ | otherwise = Just (eq x y)
+
+castDef :: b -> (forall a. Ord a => a -> a -> b) -> (Text -> Text -> b)
+castDef def eq x y = fromMaybe def (cast eq x y)
+
+castTo :: Type a -> Text -> Maybe a
+castTo Date = readMaybe . T.unpack
+castTo Int = readMaybe . T.unpack
+castTo String = Just