-- Stability : provisional
-- Portability : portable
--
--- John Hughes\'s and Simon Peyton Jones\'s Pretty Printer Combinators
+-- John Hughes's and Simon Peyton Jones's Pretty Printer Combinators
--
-- Based on /The Design of a Pretty-printing Library/
-- in Advanced Functional Programming,
nest k empty = empty
which wasn't true before.
- * Fixed an obscure bug in sep that occassionally gave very wierd behaviour
+ * Fixed an obscure bug in sep that occassionally gave very weird behaviour
* Added $+$
It is Really Useful in practice.
2. There is a paragraph-fill combinator, fsep, that's much like sep,
- only it keeps fitting things on one line until itc can't fit any more.
+ only it keeps fitting things on one line until it can't fit any more.
3. Some random useful extra combinators are provided.
<+> puts its arguments beside each other with a space between them,
sep (separate) is either like hsep or like vcat, depending on what fits
- cat is behaves like sep, but it uses <> for horizontal conposition
- fcat is behaves like fsep, but it uses <> for horizontal conposition
+ cat behaves like sep, but it uses <> for horizontal conposition
+ fcat behaves like fsep, but it uses <> for horizontal conposition
These new ones do the obvious things:
char, semi, comma, colon, space,
isEmpty :: Doc -> Bool; -- ^ Returns 'True' if the document is empty
empty :: Doc; -- ^ An empty document
-semi :: Doc; -- ^ A \';\' character
-comma :: Doc; -- ^ A \',\' character
-colon :: Doc; -- ^ A \':\' character
+semi :: Doc; -- ^ A ';' character
+comma :: Doc; -- ^ A ',' character
+colon :: Doc; -- ^ A ':' character
space :: Doc; -- ^ A space character
-equals :: Doc; -- ^ A \'=\' character
-lparen :: Doc; -- ^ A \'(\' character
-rparen :: Doc; -- ^ A \')\' character
-lbrack :: Doc; -- ^ A \'[\' character
-rbrack :: Doc; -- ^ A \']\' character
-lbrace :: Doc; -- ^ A \'{\' character
-rbrace :: Doc; -- ^ A \'}\' character
+equals :: Doc; -- ^ A '=' character
+lparen :: Doc; -- ^ A '(' character
+rparen :: Doc; -- ^ A ')' character
+lbrack :: Doc; -- ^ A '[' character
+rbrack :: Doc; -- ^ A ']' character
+lbrace :: Doc; -- ^ A '{' character
+rbrace :: Doc; -- ^ A '}' character
text :: String -> Doc
ptext :: String -> Doc
-- Combining @Doc@ values
(<>) :: Doc -> Doc -> Doc; -- ^Beside
-hcat :: [Doc] -> Doc; -- ^List version of '\<>'
+hcat :: [Doc] -> Doc; -- ^List version of '<>'
(<+>) :: Doc -> Doc -> Doc; -- ^Beside, separated by space
-hsep :: [Doc] -> Doc; -- ^List version of '\<+>'
+hsep :: [Doc] -> Doc; -- ^List version of '<+>'
($$) :: Doc -> Doc -> Doc; -- ^Above; if there is no
-- overlap it \"dovetails\" the two
+($+$) :: Doc -> Doc -> Doc; -- ^Above, without dovetailing.
vcat :: [Doc] -> Doc; -- ^List version of '$$'
cat :: [Doc] -> Doc; -- ^ Either hcat or vcat
-- ---------------------------------------------------------------------------
-- Displaying the best layout
-{-
-renderStyle Style{mode, lineLength, ribbonsPerLine} doc
- = fullRender mode lineLength ribbonsPerLine doc ""
--}
+renderStyle style doc
+ = fullRender (mode style)
+ (lineLength style)
+ (ribbonsPerLine style)
+ string_txt
+ ""
+ doc
render doc = showDoc doc ""
showDoc doc rest = fullRender PageMode 100 1.5 string_txt rest doc
multi_ch 0 ch = ""
multi_ch n ch = ch : multi_ch (n - 1) ch
-spaces 0 = ""
-spaces n = ' ' : spaces (n - 1)
-
+-- (spaces n) generates a list of n spaces
+--
+-- It should never be called with 'n' < 0, but that can happen for reasons I don't understand
+-- Here's a test case:
+-- ncat x y = nest 4 $ cat [ x, y ]
+-- d1 = foldl1 ncat $ take 50 $ repeat $ char 'a'
+-- d2 = parens $ sep [ d1, text "+" , d1 ]
+-- main = print d2
+-- I don't feel motivated enough to find the Real Bug, so meanwhile we just test for n<=0
+spaces n | n <= 0 = ""
+ | otherwise = ' ' : spaces (n - 1)
+
+{- Comments from Johannes Waldmann about what the problem might be:
+
+ In the example above, d2 and d1 are deeply nested, but `text "+"' is not,
+ so the layout function tries to "out-dent" it.
+
+ when I look at the Doc values that are generated, there are lots of
+ Nest constructors with negative arguments. see this sample output of
+ d1 (obtained with hugs, :s -u)
+
+ tBeside (TextDetails_Chr 'a') 1 Doc_Empty) (Doc_NilAbove (Doc_Nest
+ (-241) (Doc_TextBeside (TextDetails_Chr 'a') 1 Doc_Empty)))))
+ (Doc_NilAbove (Doc_Nest (-236) (Doc_TextBeside (TextDetails_Chr 'a') 1
+ (Doc_NilAbove (Doc_Nest (-5) (Doc_TextBeside (TextDetails_Chr 'a') 1
+ Doc_Empty)))))))) (Doc_NilAbove (Doc_Nest (-231) (Doc_TextBeside
+ (TextDetails_Chr 'a') 1 (Doc_NilAbove (Doc_Nest (-5) (Doc_TextBeside
+ (TextDetails_Chr 'a') 1 (Doc_NilAbove (Doc_Nest (-5) (Doc_TextBeside
+ (TextDetails_Chr 'a') 1 Doc_Empty))))))))))) (Doc_NilAbove (Doc_Nest
+-}