[project @ 2003-08-30 23:01:48 by ross]
[haskell-directory.git] / Text / PrettyPrint / HughesPJ.hs
index a5e7346..7e1efe2 100644 (file)
@@ -8,7 +8,7 @@
 -- 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,
@@ -86,7 +86,7 @@ Version 2.0     24 April 1997
         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 $+$
 
@@ -102,7 +102,7 @@ Relative to John's original paper, there are the following new features:
     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,
@@ -115,8 +115,8 @@ Relative to John's original paper, there are the following new features:
 
         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,
@@ -226,17 +226,17 @@ infixl 5 $$, $+$
 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
@@ -257,12 +257,13 @@ doubleQuotes :: Doc -> Doc;       -- ^ Wrap document in @\"...\"@
 -- 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
@@ -798,10 +799,13 @@ oneLiner (p `Union` q)       = oneLiner p
 -- ---------------------------------------------------------------------------
 -- 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
@@ -878,6 +882,33 @@ indent n | n >= 8 = '\t' : indent (n - 8)
 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
+-}