#if __GLASGOW_HASKELL__ >= 701
#endif
#ifndef TESTING
module Text.PrettyPrint.Annotated.HughesPJ (
        
        Doc, TextDetails(..), AnnotDetails(..),
        
        
        char, text, ptext, sizedText, zeroWidthText,
        int, integer, float, double, rational,
        
        semi, comma, colon, space, equals,
        lparen, rparen, lbrack, rbrack, lbrace, rbrace,
        
        parens, brackets, braces, quotes, doubleQuotes,
        maybeParens, maybeBrackets, maybeBraces, maybeQuotes, maybeDoubleQuotes,
        
        empty,
        (<>), (<+>), hcat, hsep,
        ($$), ($+$), vcat,
        sep, cat,
        fsep, fcat,
        nest,
        hang, punctuate,
        
        annotate,
        
        isEmpty,
        
        first, reduceDoc,
        
        
        render,
        
        renderSpans, Span(..),
        renderDecorated,
        renderDecoratedM,
        
        Style(..),
        style,
        renderStyle,
        Mode(..),
        
        fullRender,
        fullRenderAnn
    ) where
#endif
import Control.DeepSeq ( NFData(rnf) )
import Data.Function   ( on )
#if __GLASGOW_HASKELL__ >= 803
import Prelude         hiding ( (<>) )
#endif
#if __GLASGOW_HASKELL__ >= 800
import qualified Data.Semigroup as Semi ( Semigroup((<>)) )
#elif __GLASGOW_HASKELL__ < 709
import Data.Monoid     ( Monoid(mempty, mappend)  )
#endif
import Data.String     ( IsString(fromString) )
import GHC.Generics
infixl 6 <>
infixl 6 <+>
infixl 5 $$, $+$
data Doc a
  = Empty                                            
  | NilAbove (Doc a)                                 
  | TextBeside !(AnnotDetails a) (Doc a)             
  | Nest  !Int (Doc a)                 
  | Union (Doc a) (Doc a)                            
  | NoDoc                                            
  | Beside (Doc a) Bool (Doc a)                      
  | Above (Doc a) Bool (Doc a)                       
#if __GLASGOW_HASKELL__ >= 701
  deriving (Generic)
#endif
type RDoc = Doc
data AnnotDetails a = AnnotStart
                    | NoAnnot !TextDetails  !Int
                    | AnnotEnd a
                      deriving (Show,Eq)
instance Functor AnnotDetails where
  fmap _ AnnotStart     = AnnotStart
  fmap _ (NoAnnot d i)  = NoAnnot d i
  fmap f (AnnotEnd a)   = AnnotEnd (f a)
annotSize :: AnnotDetails a -> Int
annotSize (NoAnnot _ l) = l
annotSize _             = 0
data TextDetails = Chr   !Char 
                 | Str  String 
                 | PStr String 
                               
                               
#if __GLASGOW_HASKELL__ >= 701
                 deriving (Show, Eq, Generic)
#endif
#if __GLASGOW_HASKELL__ >= 800
instance Semi.Semigroup (Doc a) where
#ifndef TESTING
    (<>) = (Text.PrettyPrint.Annotated.HughesPJ.<>)
#else
    (<>) = (PrettyTestVersion.<>)
#endif
instance Monoid (Doc a) where
    mempty  = empty
    mappend = (Semi.<>)
#else
instance Monoid (Doc a) where
    mempty  = empty
    mappend = (<>)
#endif
instance IsString (Doc a) where
    fromString = text
instance Show (Doc a) where
  showsPrec _ doc cont = fullRender (mode style) (lineLength style)
                                    (ribbonsPerLine style)
                                    txtPrinter cont doc
instance Eq (Doc a) where
  (==) = (==) `on` render
instance Functor Doc where
  fmap _ Empty               = Empty
  fmap f (NilAbove d)        = NilAbove (fmap f d)
  fmap f (TextBeside td d)   = TextBeside (fmap f td) (fmap f d)
  fmap f (Nest k d)          = Nest k (fmap f d)
  fmap f (Union ur ul)       = Union (fmap f ur) (fmap f ul)
  fmap _ NoDoc               = NoDoc
  fmap f (Beside ld s rd)    = Beside (fmap f ld) s (fmap f rd)
  fmap f (Above ud s ld)     = Above (fmap f ud) s (fmap f ld)
instance NFData a => NFData (Doc a) where
  rnf Empty               = ()
  rnf (NilAbove d)        = rnf d
  rnf (TextBeside td d)   = rnf td `seq` rnf d
  rnf (Nest k d)          = rnf k  `seq` rnf d
  rnf (Union ur ul)       = rnf ur `seq` rnf ul
  rnf NoDoc               = ()
  rnf (Beside ld s rd)    = rnf ld `seq` rnf s `seq` rnf rd
  rnf (Above ud s ld)     = rnf ud `seq` rnf s `seq` rnf ld
instance NFData a => NFData (AnnotDetails a) where
  rnf AnnotStart     = ()
  rnf (NoAnnot d sl) = rnf d `seq` rnf sl
  rnf (AnnotEnd a)   = rnf a
instance NFData TextDetails where
  rnf (Chr c)    = rnf c
  rnf (Str str)  = rnf str
  rnf (PStr str) = rnf str
annotate :: a -> Doc a -> Doc a
annotate a d = TextBeside AnnotStart
             $ beside (reduceDoc d) False
             $ TextBeside (AnnotEnd a) Empty
char :: Char -> Doc a
char c = textBeside_ (NoAnnot (Chr c) 1) Empty
text :: String -> Doc a
text s = case length s of {sl -> textBeside_ (NoAnnot (Str s) sl) Empty}
ptext :: String -> Doc a
ptext s = case length s of {sl -> textBeside_ (NoAnnot (PStr s) sl) Empty}
sizedText :: Int -> String -> Doc a
sizedText l s = textBeside_ (NoAnnot (Str s) l) Empty
zeroWidthText :: String -> Doc a
zeroWidthText = sizedText 0
empty :: Doc a
empty = Empty
isEmpty :: Doc a -> Bool
isEmpty Empty = True
isEmpty _     = False
indent :: Int -> String
indent !n = replicate n ' '
semi   :: Doc a 
comma  :: Doc a 
colon  :: Doc a 
space  :: Doc a 
equals :: Doc a 
lparen :: Doc a 
rparen :: Doc a 
lbrack :: Doc a 
rbrack :: Doc a 
lbrace :: Doc a 
rbrace :: Doc a 
semi   = char ';'
comma  = char ','
colon  = char ':'
space  = char ' '
equals = char '='
lparen = char '('
rparen = char ')'
lbrack = char '['
rbrack = char ']'
lbrace = char '{'
rbrace = char '}'
spaceText, nlText :: AnnotDetails a
spaceText = NoAnnot (Chr ' ') 1
nlText    = NoAnnot (Chr '\n') 1
int      :: Int      -> Doc a 
integer  :: Integer  -> Doc a 
float    :: Float    -> Doc a 
double   :: Double   -> Doc a 
rational :: Rational -> Doc a 
int      n = text (show n)
integer  n = text (show n)
float    n = text (show n)
double   n = text (show n)
rational n = text (show n)
parens       :: Doc a -> Doc a 
brackets     :: Doc a -> Doc a 
braces       :: Doc a -> Doc a 
quotes       :: Doc a -> Doc a 
doubleQuotes :: Doc a -> Doc a 
quotes p       = char '\'' <> p <> char '\''
doubleQuotes p = char '"' <> p <> char '"'
parens p       = char '(' <> p <> char ')'
brackets p     = char '[' <> p <> char ']'
braces p       = char '{' <> p <> char '}'
maybeParens :: Bool -> Doc a -> Doc a
maybeParens False = id
maybeParens True = parens
maybeBrackets :: Bool -> Doc a -> Doc a
maybeBrackets False = id
maybeBrackets True = brackets
maybeBraces :: Bool -> Doc a -> Doc a
maybeBraces False = id
maybeBraces True = braces
maybeQuotes :: Bool -> Doc a -> Doc a
maybeQuotes False = id
maybeQuotes True = quotes
maybeDoubleQuotes :: Bool -> Doc a -> Doc a
maybeDoubleQuotes False = id
maybeDoubleQuotes True = doubleQuotes
reduceDoc :: Doc a -> RDoc a
reduceDoc (Beside p g q) = beside p g (reduceDoc q)
reduceDoc (Above  p g q) = above  p g (reduceDoc q)
reduceDoc p              = p
hcat :: [Doc a] -> Doc a
hcat = snd . reduceHoriz . foldr (\p q -> Beside p False q) empty
hsep :: [Doc a] -> Doc a
hsep = snd . reduceHoriz . foldr (\p q -> Beside p True q)  empty
vcat :: [Doc a] -> Doc a
vcat = snd . reduceVert . foldr (\p q -> Above p False q) empty
nest :: Int -> Doc a -> Doc a
nest k p = mkNest k (reduceDoc p)
hang :: Doc a -> Int -> Doc a -> Doc a
hang d1 n d2 = sep [d1, nest n d2]
punctuate :: Doc a -> [Doc a] -> [Doc a]
punctuate _ []     = []
punctuate p (x:xs) = go x xs
                   where go y []     = [y]
                         go y (z:zs) = (y <> p) : go z zs
mkNest :: Int -> Doc a -> Doc a
mkNest k _ | k `seq` False = undefined
mkNest k (Nest k1 p)       = mkNest (k + k1) p
mkNest _ NoDoc             = NoDoc
mkNest _ Empty             = Empty
mkNest 0 p                 = p
mkNest k p                 = nest_ k p
mkUnion :: Doc a -> Doc a -> Doc a
mkUnion Empty _ = Empty
mkUnion p q     = p `union_` q
data IsEmpty = IsEmpty | NotEmpty
reduceHoriz :: Doc a -> (IsEmpty, Doc a)
reduceHoriz (Beside p g q) = eliminateEmpty Beside (snd (reduceHoriz p)) g (reduceHoriz q)
reduceHoriz doc            = (NotEmpty, doc)
reduceVert :: Doc a -> (IsEmpty, Doc a)
reduceVert (Above  p g q) = eliminateEmpty Above  (snd (reduceVert p)) g (reduceVert q)
reduceVert doc            = (NotEmpty, doc)
eliminateEmpty ::
  (Doc a -> Bool -> Doc a -> Doc a) ->
  Doc a -> Bool -> (IsEmpty, Doc a) -> (IsEmpty, Doc a)
eliminateEmpty _    Empty _ q          = q
eliminateEmpty cons p     g q          =
  (NotEmpty,
   
   
   
   
   
   
   
   case q of
     (NotEmpty, q') -> cons p g q'
     (IsEmpty, _) -> p)
nilAbove_ :: RDoc a -> RDoc a
nilAbove_ = NilAbove
textBeside_ :: AnnotDetails a -> RDoc a -> RDoc a
textBeside_  = TextBeside
nest_ :: Int -> RDoc a -> RDoc a
nest_ = Nest
union_ :: RDoc a -> RDoc a -> RDoc a
union_ = Union
($$) :: Doc a -> Doc a -> Doc a
p $$  q = above_ p False q
($+$) :: Doc a -> Doc a -> Doc a
p $+$ q = above_ p True q
above_ :: Doc a -> Bool -> Doc a -> Doc a
above_ p _ Empty = p
above_ Empty _ q = q
above_ p g q     = Above p g q
above :: Doc a -> Bool -> RDoc a -> RDoc a
above (Above p g1 q1)  g2 q2 = above p g1 (above q1 g2 q2)
above p@(Beside{})     g  q  = aboveNest (reduceDoc p) g 0 (reduceDoc q)
above p g q                  = aboveNest p             g 0 (reduceDoc q)
aboveNest :: RDoc a -> Bool -> Int -> RDoc a -> RDoc a
aboveNest _                   _ k _ | k `seq` False = undefined
aboveNest NoDoc               _ _ _ = NoDoc
aboveNest (p1 `Union` p2)     g k q = aboveNest p1 g k q `union_`
                                      aboveNest p2 g k q
aboveNest Empty               _ k q = mkNest k q
aboveNest (Nest k1 p)         g k q = nest_ k1 (aboveNest p g (k  k1) q)
                                  
aboveNest (NilAbove p)        g k q = nilAbove_ (aboveNest p g k q)
aboveNest (TextBeside s p)    g k q = TextBeside s rest
                                    where
                                      !k1  = k  annotSize s
                                      rest = case p of
                                                Empty -> nilAboveNest g k1 q
                                                _     -> aboveNest  p g k1 q
aboveNest (Above {})          _ _ _ = error "aboveNest Above"
aboveNest (Beside {})         _ _ _ = error "aboveNest Beside"
nilAboveNest :: Bool -> Int -> RDoc a -> RDoc a
nilAboveNest _ k _           | k `seq` False = undefined
nilAboveNest _ _ Empty       = Empty
                               
nilAboveNest g k (Nest k1 q) = nilAboveNest g (k + k1) q
nilAboveNest g k q           | not g && k > 0      
                             = textBeside_ (NoAnnot (Str (indent k)) k) q
                             | otherwise           
                             = nilAbove_ (mkNest k q)
(<>) :: Doc a -> Doc a -> Doc a
p <>  q = beside_ p False q
(<+>) :: Doc a -> Doc a -> Doc a
p <+> q = beside_ p True  q
beside_ :: Doc a -> Bool -> Doc a -> Doc a
beside_ p _ Empty = p
beside_ Empty _ q = q
beside_ p g q     = Beside p g q
beside :: Doc a -> Bool -> RDoc a -> RDoc a
beside NoDoc               _ _   = NoDoc
beside (p1 `Union` p2)     g q   = beside p1 g q `union_` beside p2 g q
beside Empty               _ q   = q
beside (Nest k p)          g q   = nest_ k $! beside p g q
beside p@(Beside p1 g1 q1) g2 q2
         | g1 == g2              = beside p1 g1 $! beside q1 g2 q2
         | otherwise             = beside (reduceDoc p) g2 q2
beside p@(Above{})         g q   = let !d = reduceDoc p in beside d g q
beside (NilAbove p)        g q   = nilAbove_ $! beside p g q
beside (TextBeside t p)    g q   = TextBeside t rest
                               where
                                  rest = case p of
                                           Empty -> nilBeside g q
                                           _     -> beside p g q
nilBeside :: Bool -> RDoc a -> RDoc a
nilBeside _ Empty         = Empty 
nilBeside g (Nest _ p)    = nilBeside g p
nilBeside g p | g         = textBeside_ spaceText p
              | otherwise = p
sep  :: [Doc a] -> Doc a
sep = sepX True   
cat :: [Doc a] -> Doc a
cat = sepX False  
sepX :: Bool -> [Doc a] -> Doc a
sepX _ []     = empty
sepX x (p:ps) = sep1 x (reduceDoc p) 0 ps
sep1 :: Bool -> RDoc a -> Int -> [Doc a] -> RDoc a
sep1 _ _                   k _  | k `seq` False = undefined
sep1 _ NoDoc               _ _  = NoDoc
sep1 g (p `Union` q)       k ys = sep1 g p k ys `union_`
                                  aboveNest q False k (reduceDoc (vcat ys))
sep1 g Empty               k ys = mkNest k (sepX g ys)
sep1 g (Nest n p)          k ys = nest_ n (sep1 g p (k  n) ys)
sep1 _ (NilAbove p)        k ys = nilAbove_
                                  (aboveNest p False k (reduceDoc (vcat ys)))
sep1 g (TextBeside s p) k ys    = textBeside_ s (sepNB g p (k  annotSize s) ys)
sep1 _ (Above {})          _ _  = error "sep1 Above"
sep1 _ (Beside {})         _ _  = error "sep1 Beside"
sepNB :: Bool -> Doc a -> Int -> [Doc a] -> Doc a
sepNB g (Nest _ p) k ys
  = sepNB g p k ys 
sepNB g Empty k ys
  = oneLiner (nilBeside g (reduceDoc rest)) `mkUnion`
    
    nilAboveNest False k (reduceDoc (vcat ys))
  where
    rest | g         = hsep ys
         | otherwise = hcat ys
sepNB g p k ys
  = sep1 g p k ys
fcat :: [Doc a] -> Doc a
fcat = fill False
fsep :: [Doc a] -> Doc a
fsep = fill True
fill :: Bool -> [Doc a] -> RDoc a
fill _ []     = empty
fill g (p:ps) = fill1 g (reduceDoc p) 0 ps
fill1 :: Bool -> RDoc a -> Int -> [Doc a] -> Doc a
fill1 _ _                   k _  | k `seq` False = undefined
fill1 _ NoDoc               _ _  = NoDoc
fill1 g (p `Union` q)       k ys = fill1 g p k ys `union_`
                                   aboveNest q False k (fill g ys)
fill1 g Empty               k ys = mkNest k (fill g ys)
fill1 g (Nest n p)          k ys = nest_ n (fill1 g p (k  n) ys)
fill1 g (NilAbove p)        k ys = nilAbove_ (aboveNest p False k (fill g ys))
fill1 g (TextBeside s p)    k ys = textBeside_ s (fillNB g p (k  annotSize s) ys)
fill1 _ (Above {})          _ _  = error "fill1 Above"
fill1 _ (Beside {})         _ _  = error "fill1 Beside"
fillNB :: Bool -> Doc a -> Int -> [Doc a] -> Doc a
fillNB _ _           k _  | k `seq` False = undefined
fillNB g (Nest _ p)  k ys   = fillNB g p k ys
                              
fillNB _ Empty _ []         = Empty
fillNB g Empty k (Empty:ys) = fillNB g Empty k ys
fillNB g Empty k (y:ys)     = fillNBE g k y ys
fillNB g p k ys             = fill1 g p k ys
fillNBE :: Bool -> Int -> Doc a -> [Doc a] -> Doc a
fillNBE g k y ys
  = nilBeside g (fill1 g ((elideNest . oneLiner . reduceDoc) y) k' ys)
    
    `mkUnion` nilAboveNest False k (fill g (y:ys))
  where k' = if g then k  1 else k
elideNest :: Doc a -> Doc a
elideNest (Nest _ d) = d
elideNest d          = d
best :: Int   
     -> Int   
     -> RDoc a
     -> RDoc a  
best w0 r = get w0
  where
    get w _ | w == 0 && False = undefined
    get _ Empty               = Empty
    get _ NoDoc               = NoDoc
    get w (NilAbove p)        = nilAbove_ (get w p)
    get w (TextBeside s p)    = textBeside_ s (get1 w (annotSize s) p)
    get w (Nest k p)          = nest_ k (get (w  k) p)
    get w (p `Union` q)       = nicest w r (get w p) (get w q)
    get _ (Above {})          = error "best get Above"
    get _ (Beside {})         = error "best get Beside"
    get1 w _ _ | w == 0 && False  = undefined
    get1 _ _  Empty               = Empty
    get1 _ _  NoDoc               = NoDoc
    get1 w sl (NilAbove p)        = nilAbove_ (get (w  sl) p)
    get1 w sl (TextBeside s p)    = textBeside_ s (get1 w (sl + annotSize s) p)
    get1 w sl (Nest _ p)          = get1 w sl p
    get1 w sl (p `Union` q)       = nicest1 w r sl (get1 w sl p)
                                                   (get1 w sl q)
    get1 _ _  (Above {})          = error "best get1 Above"
    get1 _ _  (Beside {})         = error "best get1 Beside"
nicest :: Int -> Int -> Doc a -> Doc a -> Doc a
nicest !w !r = nicest1 w r 0
nicest1 :: Int -> Int -> Int -> Doc a -> Doc a -> Doc a
nicest1 !w !r !sl p q | fits ((w `min` r)  sl) p = p
                      | otherwise                 = q
fits :: Int  
     -> Doc a
     -> Bool 
fits n _ | n < 0           = False
fits _ NoDoc               = False
fits _ Empty               = True
fits _ (NilAbove _)        = True
fits n (TextBeside s p)    = fits (n  annotSize s) p
fits _ (Above {})          = error "fits Above"
fits _ (Beside {})         = error "fits Beside"
fits _ (Union {})          = error "fits Union"
fits _ (Nest {})           = error "fits Nest"
first :: Doc a -> Doc a -> Doc a
first p q | nonEmptySet p = p 
          | otherwise     = q
nonEmptySet :: Doc a -> Bool
nonEmptySet NoDoc              = False
nonEmptySet (_ `Union` _)      = True
nonEmptySet Empty              = True
nonEmptySet (NilAbove _)       = True
nonEmptySet (TextBeside _ p)   = nonEmptySet p
nonEmptySet (Nest _ p)         = nonEmptySet p
nonEmptySet (Above {})         = error "nonEmptySet Above"
nonEmptySet (Beside {})        = error "nonEmptySet Beside"
oneLiner :: Doc a -> Doc a
oneLiner NoDoc               = NoDoc
oneLiner Empty               = Empty
oneLiner (NilAbove _)        = NoDoc
oneLiner (TextBeside s p)    = textBeside_ s (oneLiner p)
oneLiner (Nest k p)          = nest_ k (oneLiner p)
oneLiner (p `Union` _)       = oneLiner p
oneLiner (Above {})          = error "oneLiner Above"
oneLiner (Beside {})         = error "oneLiner Beside"
data Style
  = Style { mode           :: Mode
            
          , lineLength     :: Int
            
          , ribbonsPerLine :: Float
            
            
            
            
            
          }
#if __GLASGOW_HASKELL__ >= 701
  deriving (Show, Eq, Generic)
#endif
style :: Style
style = Style { lineLength = 100, ribbonsPerLine = 1.5, mode = PageMode }
data Mode = PageMode    
            
            
          | ZigZagMode  
            
          | LeftMode    
            
            
            
          | OneLineMode 
            
            
#if __GLASGOW_HASKELL__ >= 701
          deriving (Show, Eq, Generic)
#endif
render :: Doc a -> String
render = fullRender (mode style) (lineLength style) (ribbonsPerLine style)
                    txtPrinter ""
renderStyle :: Style -> Doc a -> String
renderStyle s = fullRender (mode s) (lineLength s) (ribbonsPerLine s)
                txtPrinter ""
txtPrinter :: TextDetails -> String -> String
txtPrinter (Chr c)   s  = c:s
txtPrinter (Str s1)  s2 = s1 ++ s2
txtPrinter (PStr s1) s2 = s1 ++ s2
fullRender :: Mode                    
           -> Int                     
           -> Float                   
           -> (TextDetails -> a -> a) 
           -> a                       
           -> Doc b                   
           -> a                       
fullRender m l r txt = fullRenderAnn m l r annTxt
  where
  annTxt (NoAnnot s _) = txt s
  annTxt _             = id
fullRenderAnn :: Mode                       
              -> Int                        
              -> Float                      
              -> (AnnotDetails b -> a -> a) 
              -> a                          
              -> Doc b                      
              -> a                          
fullRenderAnn OneLineMode _ _ txt end doc
  = easyDisplay spaceText (\_ y -> y) txt end (reduceDoc doc)
fullRenderAnn LeftMode    _ _ txt end doc
  = easyDisplay nlText first txt end (reduceDoc doc)
fullRenderAnn m lineLen ribbons txt rest doc
  = display m lineLen ribbonLen txt rest doc'
  where
    doc' = best bestLineLen ribbonLen (reduceDoc doc)
    bestLineLen, ribbonLen :: Int
    ribbonLen   = round (fromIntegral lineLen / ribbons)
    bestLineLen = case m of
                      ZigZagMode -> maxBound
                      _          -> lineLen
easyDisplay :: AnnotDetails b
             -> (Doc b -> Doc b -> Doc b)
             -> (AnnotDetails b -> a -> a)
             -> a
             -> Doc b
             -> a
easyDisplay nlSpaceText choose txt end
  = lay
  where
    lay NoDoc              = error "easyDisplay: NoDoc"
    lay (Union p q)        = lay (choose p q)
    lay (Nest _ p)         = lay p
    lay Empty              = end
    lay (NilAbove p)       = nlSpaceText `txt` lay p
    lay (TextBeside s p)   = s `txt` lay p
    lay (Above {})         = error "easyDisplay Above"
    lay (Beside {})        = error "easyDisplay Beside"
display :: Mode -> Int -> Int -> (AnnotDetails b -> a -> a) -> a -> Doc b -> a
display m !page_width !ribbon_width txt end doc
  = case page_width  ribbon_width of { gap_width ->
    case gap_width `quot` 2 of { shift ->
    let
        lay k _            | k `seq` False = undefined
        lay k (Nest k1 p)  = lay (k + k1) p
        lay _ Empty        = end
        lay k (NilAbove p) = nlText `txt` lay k p
        lay k (TextBeside s p)
            = case m of
                    ZigZagMode |  k >= gap_width
                               -> nlText `txt` (
                                  NoAnnot (Str (replicate shift '/')) shift `txt` (
                                  nlText `txt`
                                  lay1 (k  shift) s p ))
                               |  k < 0
                               -> nlText `txt` (
                                  NoAnnot (Str (replicate shift '\\')) shift `txt` (
                                  nlText `txt`
                                  lay1 (k + shift) s p ))
                    _ -> lay1 k s p
        lay _ (Above {})   = error "display lay Above"
        lay _ (Beside {})  = error "display lay Beside"
        lay _ NoDoc        = error "display lay NoDoc"
        lay _ (Union {})   = error "display lay Union"
        lay1 !k s p        = let !r = k + annotSize s
                             in NoAnnot (Str (indent k)) k `txt` (s `txt` lay2 r p)
        lay2 k _ | k `seq` False   = undefined
        lay2 k (NilAbove p)        = nlText `txt` lay k p
        lay2 k (TextBeside s p)    = s `txt` lay2 (k + annotSize s) p
        lay2 k (Nest _ p)          = lay2 k p
        lay2 _ Empty               = end
        lay2 _ (Above {})          = error "display lay2 Above"
        lay2 _ (Beside {})         = error "display lay2 Beside"
        lay2 _ NoDoc               = error "display lay2 NoDoc"
        lay2 _ (Union {})          = error "display lay2 Union"
    in
    lay 0 doc
    }}
data Span a = Span { spanStart      :: !Int
                   , spanLength     :: !Int
                   , spanAnnotation :: a
                   } deriving (Show,Eq)
instance Functor Span where
  fmap f (Span x y a) = Span x y (f a)
data Spans a = Spans { sOffset :: !Int
                       
                     , sStack  :: [Int -> Span a]
                       
                     , sSpans  :: [Span a]
                       
                     , sOutput :: String
                       
                     }
renderSpans :: Doc ann -> (String,[Span ann])
renderSpans  = finalize
             . fullRenderAnn (mode style) (lineLength style) (ribbonsPerLine style)
                  spanPrinter
                  Spans { sOffset = 0, sStack = [], sSpans = [], sOutput = "" }
  where
  finalize (Spans size _ spans out) = (out, map adjust spans)
    where
    adjust s = s { spanStart = size  spanStart s }
  mkSpan a end start = Span { spanStart      = start
                            , spanLength     = start  end
                              
                              
                            , spanAnnotation = a }
  
  
  spanPrinter AnnotStart s =
    case sStack s of
      sp : rest -> s { sSpans = sp (sOffset s) : sSpans s, sStack = rest }
      _         -> error "renderSpans: stack underflow"
  spanPrinter (AnnotEnd a) s =
    s { sStack = mkSpan a (sOffset s) : sStack s }
  spanPrinter (NoAnnot td l) s =
    case td of
      Chr  c -> s { sOutput = c  : sOutput s, sOffset = sOffset s + l }
      Str  t -> s { sOutput = t ++ sOutput s, sOffset = sOffset s + l }
      PStr t -> s { sOutput = t ++ sOutput s, sOffset = sOffset s + l }
renderDecorated :: (ann -> String) 
                -> (ann -> String) 
                -> Doc ann -> String
renderDecorated startAnn endAnn =
  finalize . fullRenderAnn (mode style) (lineLength style) (ribbonsPerLine style)
                 annPrinter
                 ("", [])
  where
  annPrinter AnnotStart (rest,stack) =
    case stack of
      a : as -> (startAnn a ++ rest, as)
      _      -> error "renderDecorated: stack underflow"
  annPrinter (AnnotEnd a) (rest,stack) =
    (endAnn a ++ rest, a : stack)
  annPrinter (NoAnnot s _) (rest,stack) =
    (txtPrinter s rest, stack)
  finalize (str,_) = str
renderDecoratedM :: Monad m
                 => (ann    -> m r) 
                 -> (ann    -> m r) 
                 -> (String -> m r) 
                 -> m r             
                 -> Doc ann -> m r
renderDecoratedM startAnn endAnn txt docEnd =
  finalize . fullRenderAnn (mode style) (lineLength style) (ribbonsPerLine style)
                 annPrinter
                 (docEnd, [])
  where
  annPrinter AnnotStart (rest,stack) =
    case stack of
      a : as -> (startAnn a >> rest, as)
      _      -> error "renderDecorated: stack underflow"
  annPrinter (AnnotEnd a) (rest,stack) =
    (endAnn a >> rest, a : stack)
  annPrinter (NoAnnot td _) (rest,stack) =
    case td of
      Chr  c -> (txt [c] >> rest, stack)
      Str  s -> (txt s   >> rest, stack)
      PStr s -> (txt s   >> rest, stack)
  finalize (m,_) = m