module Issue.Sort ( Sort, Order, SortBy, applySort, sortArg, ) where import Data.List (sort, sortBy) import Data.Maybe (mapMaybe) import Data.Ord (comparing) import Data.Text (Text) import Data.Text qualified as T import Issue (Issue (..)) import Issue.Tag (Tag (..)) import Options.Applicative qualified as O data Sort = Sort Order SortBy deriving (Show) data Order = Asc | Desc deriving (Show, Eq) data SortBy = SortByTag Text deriving (Show) defaultSort :: Sort defaultSort = Sort Asc (SortByTag "@createdAt") sortArg :: O.Parser [Sort] sortArg = O.many ( O.option (O.maybeReader (parse . T.pack)) ( O.long "sort" <> O.short 's' <> O.metavar "SORT" <> O.help "Sort selected issues. (Defaults: `-@createdAt`)" ) ) where parse s | "@" `T.isPrefixOf` s = Just (Sort Asc (SortByTag (T.drop 1 s))) | "-@" `T.isPrefixOf` s = Just (Sort Desc (SortByTag (T.drop 2 s))) | otherwise = Nothing applySort :: [Sort] -> [Issue] -> [Issue] applySort cs = compose (defaultSort : cs) where compose :: [Sort] -> ([Issue] -> [Issue]) compose = foldr (.) id . map toSort toSort :: Sort -> ([Issue] -> [Issue]) toSort (Sort order sortBy') = (if order == Desc then reverse else id) . sortBy (comparing (applySortBy 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) )