{-# OPTIONS_GHC -fno-warn-orphans #-} module Issue.Render ( IssueTitle (..), IssueDescription (..), IssueTags (..), IssueComments (..), IssueOpenedOn (..), IssueOpenedBy (..), ) where import Data.List (intersperse) import Data.List.NonEmpty qualified as N import Data.Map qualified as M import Data.Text qualified as T import Data.Time.Clock (UTCTime (utctDay)) import Issue (Issue (..)) import Issue.Provenance (Author (..), Commit (..), Provenance (..)) import Render ((<<<)) import Render qualified as P -- TODO Easily separate renderables by newlines -- -- For convenience, the (<<<) combinator adds spaces between renderable entities, **if** those renderables are non-empty. -- -- We should similarly allow for a combinator that similarly adds empty lines between renderable entities. -- -- @topic rendering instance P.Render (P.Detailed Issue) where render (P.Detailed issue) = IssueTitle issue <<< P.hardline @P.AnsiStyle <<< IssueDescription issue <<< P.hardline @P.AnsiStyle <<< IssueTags issue <<< P.hardline @P.AnsiStyle <<< IssueComments issue instance P.Render Issue where render = P.render . P.Detailed newtype IssueTitle = IssueTitle {unIssueTitle :: Issue} instance P.Render IssueTitle where render (IssueTitle issue) | issue.closed = P.styled [P.colorDull P.Red] $ P.render issue.title | otherwise = P.styled [(P.color P.Green)] $ P.render issue.title newtype IssueDescription = IssueDescription {unIssueDescription :: Issue} instance P.Render IssueDescription where render (IssueDescription issue) = maybe P.emptyDoc (P.render . N.toList) $ issue.description instance P.Render (P.Linked Issue) where render (P.Linked issue) | issue.closed = P.styled [P.underlined, P.colorDull P.Red] $ ("(closed)" :: T.Text) <<< P.render issue.id | otherwise = P.styled [P.underlined, (P.color P.Green)] $ P.render issue.id instance P.Render (P.Summarized Issue) where render (P.Summarized issue) = P.nest 4 $ IssueTitle issue <<< IssueTags issue <<< IssueOpenedOn issue <<< IssueOpenedBy issue newtype IssueTags = IssueTags {unIssueTags :: Issue} instance P.Render IssueTags where render (IssueTags issue) = P.render issue.tags newtype IssueComments = IssueComments {unIssueComments :: Issue} instance P.Render IssueComments where render (IssueComments issue) = maybe P.emptyDoc (P.vsep . map P.render . N.toList) $ issue.comments newtype IssueOpenedBy = IssueOpenedBy {unIssueOpenedBy :: Issue} instance P.Render IssueOpenedBy where render (IssueOpenedBy issue) = ("by" :: T.Text) <<< issue.provenance.first.author.name newtype IssueOpenedOn = IssueOpenedOn {unIssueOpenedOn :: Issue} instance P.Render IssueOpenedOn where render (IssueOpenedOn issue) = ("on" :: T.Text) <<< utctDay issue.provenance.first.date instance P.Render (T.Text, M.Map T.Text [Issue]) where render (tagKey, groupedIssues) = (P.vsep . intersperse ("" :: P.Doc ann)) $ concatMap ( \(name, issues) -> ( P.styled [P.underlined] $ ("@" <> tagKey) <<< name <<< P.parens @P.AnsiStyle (P.pretty (length issues)) ) : map (P.indent 4) ( map (P.render . IssueTitle) issues ) ) (M.toList groupedIssues)