hindent-6.3.0: src/HIndent/Pretty/Combinators/String.hs
{-# LANGUAGE CPP #-}
-- | Printer combinators related to print strings.
module HIndent.Pretty.Combinators.String
( string
, space
, newline
, blankline
, comma
, dot
) where
import Control.Monad.RWS
import qualified Data.ByteString.Builder as S
import GHC.Stack
import HIndent.Config
import HIndent.Printer
#if MIN_VERSION_GLASGOW_HASKELL(9,6,0,0)
import Control.Monad
#endif
-- | This function prints the given string.
--
-- The string must not include '\n's. Use 'newline' to print them.
string :: HasCallStack => String -> Printer ()
string x
| '\n' `elem` x =
error
$ "You tried to print " ++ show x ++ ". Use `newline` to print '\\n's."
| otherwise = do
eol <- gets psEolComment
hardFail <- gets psFitOnOneLine
when eol newline
st <- get
let indentSpaces =
if psNewline st
then replicate (fromIntegral $ psIndentLevel st) ' '
else ""
out = indentSpaces <> x
psColumn' = psColumn st + fromIntegral (length out)
columnFits = psColumn' <= configMaxColumns (psConfig st)
when hardFail $ guard columnFits
modify
(\s ->
s
{ psOutput = psOutput st <> S.stringUtf8 out
, psNewline = False
, psEolComment = False
, psColumn = psColumn'
})
-- | Equivalent to 'string " "'.
space :: Printer ()
space = string " "
-- | Equivalent to 'string ","'.
comma :: Printer ()
comma = string ","
-- | Equivalent to 'string "."'.
dot :: Printer ()
dot = string "."
-- | This function prints a '\n'.
--
-- Always call this function to print it because printing it requires
-- special treatment. Do not call 'string' instead.
newline :: Printer ()
newline = do
gets psFitOnOneLine >>= guard . not
modify
(\s ->
s
{ psOutput = psOutput s <> S.stringUtf8 "\n"
, psNewline = True
, psLine = psLine s + 1
, psEolComment = False
, psColumn = 0
})
-- | Equivalent to 'newline >> newline'.
blankline :: Printer ()
blankline = newline >> newline