{-# 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