content: -- | Printer combinators related to indent.
  module HIndent.Pretty.Combinators.Indent
    ( indentedBlock
    , indentedWithSpace
    , (|=>)
    , indentedWithFixedLevel
    , prefixed
    , getIndentSpaces
    ) where
  
  import Control.Monad.State
  import Data.Int
  import HIndent.Config
  import HIndent.Pretty.Combinators.String
  import HIndent.Printer
  
  -- | This function runs the given printer with an additional indent. The
  -- indent has 'configIndentSpaces' spaces.
  indentedBlock :: Printer a -> Printer a
  indentedBlock p = do
    indentSpaces <- getIndentSpaces
    indentedWithSpace indentSpaces p
  
  -- | This function runs the given printer with an additional indent. The
  -- indent has the specified number of spaces.
  indentedWithSpace :: Int64 -> Printer a -> Printer a
  indentedWithSpace i p = do
    level <- gets psIndentLevel
    indentedWithFixedLevel (level + i) p
  
  -- | This function runs the first printer, fixes the indent, and then runs
  -- the second one.
  --
  -- For example,
  --
  -- > string "foo " |=> lined [string "bar", "baz"]
  --
  -- will print texts as below.
  -- foo bar
  --     baz
  (|=>) :: Printer () -> Printer a -> Printer a
  hd |=> p = do
    hd
    col <- gets psColumn
    indentedWithFixedLevel col p
  
  infixl 1 |=>
  -- | This function runs the given printer with the passed indent level.
  indentedWithFixedLevel :: Int64 -> Printer a -> Printer a
  indentedWithFixedLevel i p = do
    l <- gets psIndentLevel
    modify (\s -> s {psIndentLevel = i})
    m <- p
    modify (\s -> s {psIndentLevel = l})
    return m
  
  -- | Prints the text passed as the first argument before the current
  -- position and then the second argument.
  prefixed :: String -> Printer () -> Printer ()
  prefixed s p = do
    indentedWithSpace (-(fromIntegral $ length s)) $ string s
    p
  
  -- | This function returns the current indent level.
  getIndentSpaces :: Printer Int64
  getIndentSpaces = gets (configIndentSpaces . psConfig)
  