module Sindre.Formatting( Format(..)
, FormatString
, textContents
, startBg
, parseFormatString
, unparseFormatString
)
where
import Sindre.Sindre hiding (string)
import Sindre.Runtime (Mold(..))
import Data.Attoparsec.Text
import Control.Applicative hiding (many)
import Control.Monad
import Data.Maybe
import qualified Data.Text as T
import Prelude hiding (takeWhile)
data Format = Fg String
| DefFg
| Bg String
| DefBg
| Text T.Text
deriving (Show, Eq, Ord)
type FormatString = [Format]
instance Mold FormatString where
mold v = either (const Nothing) Just . parseFormatString =<< mold v
unmold = StringV . unparseFormatString
textContents :: FormatString -> T.Text
textContents = T.concat . map txt
where txt (Text s) = s
txt _ = T.empty
startBg :: FormatString -> Maybe String
startBg = getBg <=< listToMaybe . dropWhile ign
where ign (Text _) = False
ign DefBg = False
ign (Bg _) = False
ign _ = True
getBg (Bg bg) = Just bg
getBg _ = Nothing
unparseFormatString :: FormatString -> T.Text
unparseFormatString = T.concat . map f
where f (Fg s) = T.pack $ "fg(" ++ s ++ ")"
f DefFg = T.pack "fg()"
f (Bg s) = T.pack $ "bg(" ++ s ++ ")"
f DefBg = T.pack "bg()"
f (Text s) = T.replace (T.pack "^") (T.pack "^^") s
parseFormatString :: T.Text -> Either String FormatString
parseFormatString s =
eitherResult $ parse (many format <* endOfInput) s `feed` T.empty
format :: Parser Format
format = char '^' *> command <|> text
text :: Parser Format
text = Text <$> takeWhile1 (/='^')
command :: Parser Format
command = Text <$> string (T.pack "^")
<|> string (T.pack "fg(")
*> (Fg <$> T.unpack <$> takeWhile1 (/=')') <|> pure DefFg)
<* string (T.pack ")")
<|> string (T.pack "bg(")
*> (Bg <$> T.unpack <$> takeWhile1 (/=')') <|> pure DefBg)
<* string (T.pack ")")