{-# LANGUAGE CPP #-} module Portage.Dependency.Print ( dep2str , dep2str_noindent ) where import Portage.Version import Portage.Use import Portage.PackageId import qualified Distribution.Pretty as DP (Pretty(..)) import qualified Text.PrettyPrint as Disp import Text.PrettyPrint ( vcat, nest, render ) import Text.PrettyPrint as PP ((<>)) import Portage.Dependency.Types dispSlot :: SlotDepend -> Disp.Doc dispSlot AnySlot = Disp.empty dispSlot AnyBuildTimeSlot = Disp.text ":=" dispSlot (GivenSlot slot) = Disp.text (':' : slot) dispLBound :: PackageName -> LBound -> Disp.Doc dispLBound pn (StrictLB v) = Disp.char '>' PP.<> DP.pretty pn <-> DP.pretty v dispLBound pn (NonstrictLB v) = Disp.text ">=" PP.<> DP.pretty pn <-> DP.pretty v dispLBound _pn ZeroB = error "unhandled 'dispLBound ZeroB'" dispUBound :: PackageName -> UBound -> Disp.Doc dispUBound pn (StrictUB v) = Disp.char '<' PP.<> DP.pretty pn <-> DP.pretty v dispUBound pn (NonstrictUB v) = Disp.text "<=" PP.<> DP.pretty pn <-> DP.pretty v dispUBound _pn InfinityB = error "unhandled 'dispUBound Infinity'" dispDAttr :: DAttr -> Disp.Doc dispDAttr (DAttr s u) = dispSlot s PP.<> dispUses u dep2str :: Int -> Dependency -> String dep2str start_indent = render . nest start_indent . showDepend dep2str_noindent :: Dependency -> String dep2str_noindent = render . showDepend (<->) :: Disp.Doc -> Disp.Doc -> Disp.Doc a <-> b = a PP.<> Disp.char '-' PP.<> b sp :: Disp.Doc sp = Disp.char ' ' sparens :: Disp.Doc -> Disp.Doc sparens doc = Disp.parens (sp PP.<> valign doc PP.<> sp) valign :: Disp.Doc -> Disp.Doc valign d = nest 0 d showDepend :: Dependency -> Disp.Doc showDepend (DependAtom (Atom pn range dattr)) = case range of -- any version DRange ZeroB InfinityB -> DP.pretty pn PP.<> dispDAttr dattr DRange ZeroB ub -> dispUBound pn ub PP.<> dispDAttr dattr DRange lb InfinityB -> dispLBound pn lb PP.<> dispDAttr dattr -- TODO: handle >=foo-0 special case -- TODO: handle =foo-x.y.* special case DRange lb ub -> showDepend (DependAtom (Atom pn (DRange lb InfinityB) dattr)) PP.<> Disp.char ' ' PP.<> showDepend (DependAtom (Atom pn (DRange ZeroB ub) dattr)) DExact v -> Disp.char '~' PP.<> DP.pretty pn <-> DP.pretty v { versionRevision = 0 } PP.<> dispDAttr dattr showDepend (DependIfUse u td fd) = valign $ vcat [td_doc, fd_doc] where td_doc | is_empty_dependency td = Disp.empty | otherwise = DP.pretty u PP.<> Disp.char '?' PP.<> sp PP.<> sparens (showDepend td) fd_doc | is_empty_dependency fd = Disp.empty | otherwise = Disp.char '!' PP.<> DP.pretty u PP.<> Disp.char '?' PP.<> sp PP.<> sparens (showDepend fd) showDepend (DependAnyOf deps) = Disp.text "||" PP.<> sp PP.<> sparens (vcat $ map showDependInAnyOf deps) showDepend (DependAllOf deps) = valign $ vcat $ map showDepend deps -- needs special grouping showDependInAnyOf :: Dependency -> Disp.Doc showDependInAnyOf d@(DependAllOf _deps) = sparens (showDepend d) -- both lower and upper bounds are present thus needs 2 atoms -- TODO: '=foo-x.y.*' will take only one atom, not two showDependInAnyOf d@(DependAtom (Atom _pn (DRange lb ub) _dattr)) | lb /= ZeroB && ub /= InfinityB = sparens (showDepend d) -- rest are fine showDependInAnyOf d = showDepend d