1 module Language.Symantic.Document.Term.Dimension
 
   2  ( module Language.Symantic.Document.Sym
 
   3  , module Language.Symantic.Document.Term.Dimension
 
   6 import Control.Applicative (Applicative(..))
 
   8 import Data.Eq (Eq(..))
 
   9 import Data.Function (($), (.), id)
 
  10 import Data.Maybe (Maybe(..))
 
  11 import Data.Monoid (Monoid(..))
 
  12 import Data.Ord (Ord(..))
 
  13 import Data.Semigroup (Semigroup(..))
 
  14 import Data.String (IsString(..))
 
  15 import GHC.Exts (IsList(..))
 
  17 import Text.Show (Show(..))
 
  19 import Language.Symantic.Document.Sym
 
  24  {   dim_width       :: Nat -- ^ Maximun line length.
 
  25  ,   dim_height      :: Nat -- ^ Number of newlines.
 
  26  ,   dim_width_first :: Nat -- ^ Nat of the first line.
 
  27  ,   dim_width_last  :: Nat -- ^ Nat of the last line.
 
  29 instance Semigroup Dim where
 
  30         Dim{dim_width=wx, dim_height=hx, dim_width_first=wfx, dim_width_last=wlx} <>
 
  31          Dim{dim_width=wy, dim_height=hy, dim_width_first=wfy, dim_width_last=wly} =
 
  34                  (0, 0) -> let w = wx  + wy  in Dim w h w w
 
  35                  (0, _) -> let v = wfx + wfy in Dim (max v (wx + wy)) h v wly
 
  36                  (_, 0) -> let v = wlx + wfy in Dim (max v (wx + wy)) h wfx v
 
  37                  _      -> Dim (max wx wy) h wfx wly
 
  38 instance Monoid Dim where
 
  45  {   reader_indent    :: !Indent         -- ^ Current indentation level, used by 'newline'.
 
  46  ,   reader_newline   :: Dimension       -- ^ How to display 'newline'.
 
  47  ,   reader_breakable :: !(Maybe Column) -- ^ 'Column' after which to break, or 'Nothing'
 
  48  ,   reader_colorable :: !Bool           -- ^ Whether colors are activated or not.
 
  49  ,   reader_decorable :: !Bool           -- ^ Whether decorations are activated or not.
 
  52 -- | Default 'Reader'.
 
  56  , reader_newline   = newlineWithIndent
 
  57  , reader_breakable = Nothing
 
  58  , reader_colorable = True
 
  59  , reader_decorable = True
 
  71  {    unDimension :: Reader ->
 
  73                      (State -> Dim -> Dim) -> -- normal continuation
 
  74                      (State -> Dim -> Dim) -> -- should-break continuation
 
  77 dim :: Dimension -> Dim
 
  78 dim (Dimension p) = p defReader defState oko oko
 
  81 instance IsList Dimension where
 
  82         type Item Dimension = Dimension
 
  85 instance Semigroup Dimension where
 
  86         x <> y = Dimension $ \ro st ok ko ->
 
  88                  (\sx tx -> unDimension y ro sx
 
  89                          (\sy ty -> ok sy (tx<>ty))
 
  90                          (\sy ty -> ko sy (tx<>ty)))
 
  91                  (\sx tx -> unDimension y ro sx
 
  92                          (\sy ty -> ko sy (tx<>ty))
 
  93                          (\sy ty -> ko sy (tx<>ty)))
 
  94 instance Monoid Dimension where
 
  97 instance IsString Dimension where
 
 100 writeH :: Column -> Dimension
 
 102         Dimension $ \ro col ok ko ->
 
 103                 let newCol = col + len in
 
 104                 (case reader_breakable ro of
 
 105                  Just breakCol | breakCol < newCol -> ko
 
 110                  , dim_width_last  = newCol
 
 111                  , dim_width_first = newCol
 
 114 instance Textable Dimension where
 
 115         empty     = Dimension $ \_ro st ok _ko -> ok st mempty
 
 117         stringH   = writeH . length
 
 118         textH     = writeH . length
 
 119         ltextH    = writeH . length
 
 120         newline   = Dimension $ \ro -> unDimension (reader_newline ro) ro
 
 121 instance Indentable Dimension where
 
 122         align p = Dimension $ \ro st -> unDimension p ro{reader_indent=st} st
 
 123         withNewline nl  p = Dimension $ \ro -> unDimension p ro{reader_newline=nl}
 
 124         withIndent  ind p = Dimension $ \ro -> unDimension p ro{reader_indent=ind}
 
 125         incrIndent  ind p = Dimension $ \ro -> unDimension p ro{reader_indent=reader_indent ro + ind}
 
 126         column f = Dimension $ \ro st -> unDimension (f st) ro st
 
 127         indent f = Dimension $ \ro -> unDimension (f (reader_indent ro)) ro
 
 128         newlineWithoutIndent = Dimension $ \_ro _st ok _ko ->
 
 132                  , dim_width_first = 0
 
 135         newlineWithIndent = Dimension $ \ro _st ok _ko ->
 
 136                 let ind = reader_indent ro in
 
 140                  , dim_width_first = 0
 
 141                  , dim_width_last  = ind
 
 144 instance Breakable Dimension where
 
 145         breakable f = Dimension $ \ro -> unDimension (f (reader_breakable ro)) ro
 
 146         withBreakable col p = Dimension $ \ro -> unDimension p ro{reader_breakable=col}
 
 147         ifBreak y x = Dimension $ \ro st ok ko ->
 
 148                 unDimension x ro st ok $
 
 149                 case reader_breakable ro of
 
 151                  Just{} -> (\_sx _tx -> unDimension y ro st ok ko)
 
 152         breakpoint onNoBreak onBreak t = Dimension $ \ro st ok ko ->
 
 153                 unDimension (onNoBreak <> t) ro st ok $
 
 154                 case reader_breakable ro of
 
 156                  Just{} -> (\_sp _tp -> unDimension (onBreak <> t) ro st ok ko)
 
 157 instance Colorable Dimension where
 
 158         colorable f       = Dimension $ \ro -> unDimension (f (reader_colorable ro)) ro
 
 159         withColorable b t = Dimension $ \ro -> unDimension t ro{reader_colorable=b}
 
 193 instance Decorable Dimension where
 
 194         decorable f       = Dimension $ \ro -> unDimension (f (reader_decorable ro)) ro
 
 195         withDecorable b t = Dimension $ \ro -> unDimension t ro{reader_decorable=b}