renderPretty :: Float -> Int -> Doc -> SimpleDoc
renderPretty rfrac w x
    = best 0 0 0 (Cons 0 x Nil)
    where
      -- r :: the ribbon width in characters
      r  = max 0 (min w (round (fromIntegral w * rfrac)))

      -- best :: b = base nesting
      --         n = indentation of current line
      --         k = current column
      --        (ie. (k >= n) && (k - n == count of inserted characters)
      best b n k Nil           = SEmpty
      best b n k (Cons i d ds)
        = case d of
            Empty       -> best b n k ds
            Char c      -> let k' = k+1 in seq k' (SChar b c (best b n k' ds))
            Text l s    -> let k' = k+l in seq k' (SText b l s (best b n k' ds))
            Line _      -> SLine i (best b i i ds)
            Cat x y     -> best b n k (Cons i x (Cons i y ds))
            Nest j x    -> let i' = i+j in seq i' (best (if b==0 then i' else b) n k (Cons i' x ds))
            Union x y   -> nicest n k (best b n k (Cons i x ds))
                                      (best b n k (Cons i y ds))

            Column f    -> best b n k (Cons i (f k) ds)
            Nesting f   -> best b n k (Cons i (f i) ds)
            Colored f c x -> SColorOpen f c (best b n k (Cons i x (Cons i ColoredEnd ds)))
            ColoredEnd    -> SColorClose (best b n k ds)

      --nicest :: r = ribbon width, w = page width,
      --          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
                        | otherwise     = y
                        where
                          width = min (w - k) (r - k + n)
renderPretty :: Float -> Int -> Doc -> SimpleDoc
renderPretty rfrac w x
    = best 0 0 0 (Cons 0 x Nil)
    where
      -- r :: the ribbon width in characters
      r  = max 0 (min w (round (fromIntegral w * rfrac)))

      -- best :: b = base nesting
      --         n = indentation of current line
      --         k = current column
      --        (ie. (k >= n) && (k - n == count of inserted characters)
      best b n k Nil           = SEmpty
      best b n k (Cons i d ds)
        = case d of
            Empty       -> best b n k ds
            Char c      -> let k' = k+1 in seq k' (SChar b c (best b n k' ds))
            Text l s    -> let k' = k+l in seq k' (SText b l s (best b n k' ds))
            Line _      -> SLine i (best b i i ds)
            Cat x y     -> best b n k (Cons i x (Cons i y ds))
            Nest j x    -> let i' = i+j in seq i' (best (if b==0 then i' else b) n k (Cons i' x ds))
            Union x y   -> nicest n k (best b n k (Cons i x ds))
                                      (best b n k (Cons i y ds))

            Column f    -> best b n k (Cons i (f k) ds)
            Nesting f   -> best b n k (Cons i (f i) ds)
            Colored f c x -> SColorOpen f c (best b n k (Cons i x (Cons i ColoredEnd ds)))
            ColoredEnd    -> SColorClose (best b n k ds)

      --nicest :: r = ribbon width, w = page width,
      --          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
                        | otherwise     = y
                        where
                          width = min (w - k) (r - k + n)
renderPretty rfrac w x
    = best 0 0 0 (Cons 0 x Nil)
    where
      -- r :: the ribbon width in characters
      r  = max 0 (min w (round (fromIntegral w * rfrac)))

      -- best :: b = base nesting
      --         n = indentation of current line
      --         k = current column
      --        (ie. (k >= n) && (k - n == count of inserted characters)
      best b n k Nil           = SEmpty
      best b n k (Cons i d ds)
        = case d of
            Empty       -> best b n k ds
            Char c      -> let k' = k+1 in seq k' (SChar b c (best b n k' ds))
            Text l s    -> let k' = k+l in seq k' (SText b l s (best b n k' ds))
            Line _      -> SLine i (best b i i ds)
            Cat x y     -> best b n k (Cons i x (Cons i y ds))
            Nest j x    -> let i' = i+j in seq i' (best (if b==0 then i' else b) n k (Cons i' x ds))
            Union x y   -> nicest n k (best b n k (Cons i x ds))
                                      (best b n k (Cons i y ds))

            Column f    -> best b n k (Cons i (f k) ds)
            Nesting f   -> best b n k (Cons i (f i) ds)
            Colored f c x -> SColorOpen f c (best b n k (Cons i x (Cons i ColoredEnd ds)))
            ColoredEnd    -> SColorClose (best b n k ds)

      --nicest :: r = ribbon width, w = page width,
      --          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
                        | otherwise     = y
                        where
                          width = min (w - k) (r - k + n)