FPretty 1.0 → 1.1
raw patch · 2 files changed
+49/−11 lines, 2 filesdep ~basePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base
API changes (from Hackage documentation)
+ Text.PrettyPrint.FPretty: instance GHC.Show.Show Text.PrettyPrint.FPretty.Doc
Files
- FPretty.cabal +1/−1
- Text/PrettyPrint/FPretty.hs +48/−10
FPretty.cabal view
@@ -1,5 +1,5 @@ name: FPretty-version: 1.0+version: 1.1 synopsis: Efficient simple pretty printing combinators description: A pretty printer turns a tree structure into indented text, such that the indentation reflects the tree structure. To keep
Text/PrettyPrint/FPretty.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE Safe #-}+{-# LANGUAGE Safe, CPP #-} -- | -- Module : Text.PrettyPrint.FPretty@@ -73,6 +73,10 @@ -- Also FPretty provides both relative and absolute indentation via -- nest and align, whereas HughesPJ provides only relative indentation. --+-- FPretty uses far less space than other pretty printing libraries for large documents.+-- It does require space linear in the nesting depth of nest/align combinators;+-- however, having these deeply nested leads to a bad layout anyway.+-- -- Unlike other libraries, FPretty does not provide several rendering modes, -- but could be extended to do so. --@@ -106,6 +110,12 @@ -- * Combining many documents ,hsep,vsep,fillSep,sep,hcat,vcat,fillCat,cat) where +#if __GLASGOW_HASKELL__ >= 710+-- The base libraries from GHC 7.10 onwards export <$> as synonym for fmap.+import Prelude hiding ((<$>))+#endif++import Data.Maybe (fromJust) import Data.Sequence as Dequeue (Seq, (<|), viewl, viewr, ViewL(..), ViewR(..)) import qualified Data.Sequence as Dequeue (empty) -- Originally used Banker's dequeue from Okasaki's book @@ -236,6 +246,7 @@ | Group Doc | Nest Int Doc -- increase current indentation | Align Int Doc -- set indentation to current column plus increment+ deriving Show empty = Nil text t = Text (length t) t@@ -245,11 +256,13 @@ group = Group nest = Nest align = Align 0-pretty w d = interpret (normalise d) w (\p dq r i -> "") 0 Dequeue.empty w 0+pretty w d = interpret (normalise d) w (\p dq r i -> "") 0 Dequeue.empty w [0] -- semantic-preserving transformation that ensures that between every end -- of group and a subsequent line there is no text+-- It introduces many superfluous Nils, but it avoids being too strict.+-- Thus e.g. prop3 succeeds. normalise :: Doc -> Doc normalise d = td :<> sd where@@ -269,6 +282,7 @@ go (Nest i d) tt = let (td,sd) = go d tt in (td,Nest i sd) go (Align i d) tt = let (td,sd) = go d tt in (td,Align (i - docLength td) sd) + -- Determine length of a document consisting only of text,nil and <>. -- To ensure linear complexity for align should actually keep track -- of document length within go function itself.@@ -282,8 +296,9 @@ type Indentation = Int type Horizontal = Bool type Remaining = Int-type Out = Remaining -> Indentation -> String +type Out = Remaining -> [Indentation] -> String -- indentation needed here because of align combinator+ -- need list to reset indentation to old value at end of a Nest or Align type OutGroup = Horizontal -> Out -> Out type TreeCont = Position -> Dequeue.Seq (Position,OutGroup) -> Out @@ -294,28 +309,32 @@ extendFrontGroup id prune outText tc (p+l) ds where outText :: OutGroup- outText h c r i = t ++ c (r-l) i+ outText h c r is = t ++ c (r-l) is interpret (Line l t) w tc p ds = extendFrontGroup id prune outLine tc (p+l) ds where outLine :: OutGroup- outLine h c r i = if h then t ++ c (r-l) i- else '\n' : replicate i ' ' ++ c (w-i) i+ outLine h c r is = if h then t ++ c (r-l) is+ else '\n' : replicate i ' ' ++ c (w-i) is+ where+ i = head is interpret (dl :<> dr) w tc p ds = interpret dl w (interpret dr w tc) p ds interpret (Group d) w tc p ds = interpret d w (leaveGroup tc) p ((p,\h c -> c) <| ds) interpret (Nest j d) w tc p ds =- extendFrontGroup (interpret d w) (interpret d w) outNest tc p ds+ extendFrontGroup (interpret d w) (interpret d w) outNest (extendFrontGroup id id outResetIndent tc) p ds where outNest :: OutGroup- outNest h c r i = c r (i+j)+ outNest h c r is = let i = head is in c r (max 0 (i+j) : is) -- max ensures reasonable behaviour if increment is negative interpret (Align j d) w tc p ds = - extendFrontGroup (interpret d w) (interpret d w) outAlign tc p ds+ extendFrontGroup (interpret d w) (interpret d w) outAlign (extendFrontGroup id id outResetIndent tc) p ds where outAlign :: OutGroup- outAlign h c r i = c r (w-r+j)+ outAlign h c r is = c r (max 0 (w-r+j) : is) -- max ensures reasonable behaviour if increment is negative +outResetIndent :: OutGroup+outResetIndent h c r (i:is) = c r is -- If no pending groups, then do out directly, -- otherwise add out to pending group, applying given prune function.@@ -352,6 +371,9 @@ -- ------------------------------------------- -- Properties for testing. All should be True. +prop = prop0 && prop1 && prop2 && prop3 && prop4 && prop5 && prop6 && + prop7 && prop8 && prop9 && prop10 && prop11 && prop12+ prop0 = pretty 6 (group (text "Hi" <> line <> text "you") <> text "!") == "Hi\nyou!" prop1 = pretty 4 (group (text "hi" <> line <> text "world")) ==@@ -389,3 +411,19 @@ pretty 10 (group (text "one " <> (nest 2 (line <> text "two" <> nest 3 (line <> text "three"))))) == "one \n two\n three"++prop10 =+ pretty 5 (group (nest 2 (text "one" <> line <> text "two")) <>+ group (line <> text "three")) ==+ "one\n two\nthree"++prop11 =+ pretty 10 (text "one" <> softline <> (align (group (text "two" <> line <> text "three"))) <>+ softline <> text "four") ==+ "one two\n three\nfour"++prop12 =+ pretty 15 (group ( text "this"+ <> nest 9 (line <> group (text "takes" <> line <> text "four")) + <> line <> text "lines")) ==+ "this\n takes\n four\nlines"