ansi-wl-pprint 0.6.6 → 0.6.7
raw patch · 2 files changed
+98/−19 lines, 2 files
Files
- Text/PrettyPrint/ANSI/Leijen.hs +97/−18
- ansi-wl-pprint.cabal +1/−1
Text/PrettyPrint/ANSI/Leijen.hs view
@@ -79,7 +79,7 @@ -- * Basic combinators empty, char, text, (<>), nest, line, linebreak, group, softline,- softbreak,+ softbreak, hardline, flatAlt, renderSmart, -- * Alignment --@@ -728,10 +728,13 @@ -- hello -- world -- @-data Doc = Empty+data Doc = Fail+ | Empty | Char Char -- invariant: char is not '\n' | Text !Int String -- invariant: text doesn't contain '\n'- | Line !Bool -- True <=> when undone by group, do not insert a space+ | Line+ | FlatAlt Doc Doc -- Render the first doc, but when+ -- flattened, render the second. | Cat Doc Doc | Nest !Int Doc | Union Doc Doc -- invariant: first lines of first doc longer than the first lines of the second doc@@ -758,7 +761,8 @@ -- provides two default display functions 'displayS' and -- 'displayIO'. You can provide your own display function by writing a -- function from a @SimpleDoc@ to your own output format.-data SimpleDoc = SEmpty+data SimpleDoc = SFail+ | SEmpty | SChar Char SimpleDoc | SText !Int String SimpleDoc | SLine !Int SimpleDoc@@ -802,14 +806,19 @@ -- current nesting level. Document @line@ behaves like @(text \" \")@ -- if the line break is undone by 'group'. line :: Doc-line = Line False+line = FlatAlt Line space -- | The @linebreak@ document advances to the next line and indents to -- the current nesting level. Document @linebreak@ behaves like -- 'empty' if the line break is undone by 'group'. linebreak :: Doc-linebreak = Line True+linebreak = FlatAlt Line empty +-- | A linebreak that will never be flattened; it is guaranteed to render+-- as a newline.+hardline :: Doc+hardline = Line+ beside x y = Cat x y -- | The document @(nest i x)@ renders document @x@ with the current@@ -843,10 +852,16 @@ group :: Doc -> Doc group x = Union (flatten x) x +-- | A document that is normally rendered as the first argument, but+-- when flattened, is rendered as the second document.+flatAlt :: Doc -> Doc -> Doc+flatAlt = FlatAlt+ flatten :: Doc -> Doc+flatten (FlatAlt x y) = y flatten (Cat x y) = Cat (flatten x) (flatten y) flatten (Nest i x) = Nest i (flatten x)-flatten (Line break) = if break then Empty else Text 1 " "+flatten Line = Fail flatten (Union x y) = flatten x flatten (Column f) = Column (flatten . f) flatten (Columns f) = Columns (flatten . f)@@ -1024,7 +1039,7 @@ plain e@Empty = e plain c@(Char _) = c plain t@(Text _ _) = t-plain l@(Line _) = l+plain l@Line = l plain (Cat x y) = Cat (plain x) (plain y) plain (Nest i x) = Nest i (plain x) plain (Union x y) = Union (plain x) (plain y)@@ -1058,7 +1073,45 @@ -- @ribbonfrac@ should be between @0.0@ and @1.0@. If it is lower or -- higher, the ribbon width will be 0 or @width@ respectively. renderPretty :: Float -> Int -> Doc -> SimpleDoc-renderPretty rfrac w x+renderPretty = renderFits fits1++-- | A slightly smarter rendering algorithm with more lookahead. It provides+-- provide earlier breaking on deeply nested structures+-- For example, consider this python-ish pseudocode:+-- @fun(fun(fun(fun(fun([abcdefg, abcdefg])))))@+-- If we put a softbreak (+ nesting 2) after each open parenthesis, and align+-- the elements of the list to match the opening brackets, this will render with+-- @renderPretty@ and a page width of 20 as:+-- @+-- fun(fun(fun(fun(fun([+-- | abcdef,+-- | abcdef,+-- ]+-- ))))) |+-- @+-- Where the 20c. boundary has been marked with |.+-- Because @renderPretty@ only uses one-line lookahead, it sees that the first+-- line fits, and is stuck putting the second and third lines after the 20-c+-- mark. In contrast, @renderSmart@ will continue to check that the potential+-- document up to the end of the indentation level. Thus, it will format the+-- document as:+--+-- @+-- fun( |+-- fun( |+-- fun( |+-- fun( |+-- fun([ |+-- abcdef,+-- abcdef,+-- ] |+-- ))))) |+-- @+-- Which fits within the 20c. boundary.+renderSmart :: Float -> Int -> Doc -> SimpleDoc+renderSmart = renderFits fitsR++renderFits fits rfrac w x -- I used to do a @SSGR [Reset]@ here, but if you do that it will result -- in any rendered @Doc@ containing at least some ANSI control codes. This -- may be undesirable if you want to render to non-ANSI devices by simply@@ -1078,10 +1131,12 @@ best n k mb_fc mb_bc mb_in mb_it mb_un Nil = SEmpty best n k mb_fc mb_bc mb_in mb_it mb_un (Cons i d ds) = case d of+ Fail -> SFail Empty -> best_typical n k ds Char c -> let k' = k+1 in seq k' (SChar c (best_typical n k' ds)) Text l s -> let k' = k+l in seq k' (SText l s (best_typical n k' ds))- Line _ -> SLine i (best_typical i i ds)+ Line -> SLine i (best_typical i i ds)+ FlatAlt x _ -> best_typical n k (Cons i x ds) Cat x y -> best_typical n k (Cons i x (Cons i y ds)) Nest j x -> let i' = i+j in seq i' (best_typical n k (Cons i' x ds)) Union x y -> nicest n k (best_typical n k (Cons i x ds))@@ -1116,18 +1171,36 @@ -- n = indentation of current line, k = current column -- x and y, the (simple) documents to chose from. -- precondition: first lines of x are longer than the first lines of y.- nicest n k x y | fits width x = x+ nicest n k x y | fits w (min n k) width x = x | otherwise = y where width = min (w - k) (r - k + n) -fits w x | w < 0 = False-fits w SEmpty = True-fits w (SChar c x) = fits (w - 1) x-fits w (SText l s x) = fits (w - l) x-fits w (SLine i x) = True-fits w (SSGR s x) = fits w x+-- @fits1@ does 1 line lookahead.+fits1 _ _ w x | w < 0 = False+fits1 _ _ w SFail = False+fits1 _ _ w SEmpty = True+fits1 p m w (SChar c x) = fits1 p m (w - 1) x+fits1 p m w (SText l s x) = fits1 p m (w - l) x+fits1 _ _ w (SLine i x) = True +-- @fitsR@ has a little more lookahead: assuming that nesting roughly+-- corresponds to syntactic depth, @fitsR@ checks that not only the current line+-- fits, but the entire syntactic structure being formatted at this level of+-- indentation fits. If we were to remove the second case for @SLine@, we would+-- check that not only the current structure fits, but also the rest of the+-- document, which would be slightly more intelligent but would have exponential+-- runtime (and is prohibitively expensive in practice).+-- p = pagewidth+-- m = minimum nesting level to fit in+-- w = the width in which to fit the first line+fitsR p m w x | w < 0 = False+fitsR p m w SFail = False+fitsR p m w SEmpty = True+fitsR p m w (SChar c x) = fitsR p m (w - 1) x+fitsR p m w (SText l s x) = fitsR p m (w - l) x+fitsR p m w (SLine i x) | m < i = fitsR p m (p - i) x+ | otherwise = True ----------------------------------------------------------- -- renderCompact: renders documents without indentation@@ -1148,10 +1221,12 @@ where scan k [] = SEmpty scan k (d:ds) = case d of+ Fail -> SFail Empty -> scan k ds Char c -> let k' = k+1 in seq k' (SChar c (scan k' ds)) Text l s -> let k' = k+l in seq k' (SText l s (scan k' ds))- Line _ -> SLine 0 (scan 0 ds)+ FlatAlt x _ -> scan k (x:ds)+ Line -> SLine 0 (scan 0 ds) Cat x y -> scan k (x:y:ds) Nest j x -> scan k (x:ds) Union x y -> scan k (y:ds)@@ -1182,6 +1257,8 @@ -- you are running on a Unix-like operating system. This is due to -- a technical limitation in Windows ANSI support. displayS :: SimpleDoc -> ShowS+displayS SFail = error $ "@SFail@ can not appear uncaught in a " +++ "rendered @SimpleDoc@" displayS SEmpty = id displayS (SChar c x) = showChar c . displayS x displayS (SText l s x) = showString s . displayS x@@ -1199,6 +1276,8 @@ displayIO handle simpleDoc = display simpleDoc where+ display SFail = error $ "@SFail@ can not appear uncaught in a " +++ "rendered @SimpleDoc@" display SEmpty = return () display (SChar c x) = do{ hPutChar handle c; display x} display (SText l s x) = do{ hPutStr handle s; display x}
ansi-wl-pprint.cabal view
@@ -1,5 +1,5 @@ Name: ansi-wl-pprint-Version: 0.6.6+Version: 0.6.7 Cabal-Version: >= 1.2 Category: User Interfaces, Text Synopsis: The Wadler/Leijen Pretty Printer for colored ANSI terminal output