packages feed

scfg-1.0.0: src/Data/Scfg/Formatter.hs

{-# LANGUAGE OverloadedStrings #-}

-- | Canonical formatter for scfg configurations.
module Data.Scfg.Formatter (format) where

import Data.Scfg.Types
import Data.Text (Text)
import qualified Data.Text as T

{- | Format a 'Config' as canonical scfg text. All words are
double-quoted and blocks are indented with tabs.
-}
format :: [Directive] -> Text
format = foldMap (formatDirective 0)

formatDirective :: Int -> Directive -> Text
formatDirective depth d =
  indent
    <> quoteWord (directiveName d)
    <> params
    <> block
    <> "\n"
 where
  indent = T.replicate depth "\t"
  params = case directiveParams d of
    [] -> ""
    ps -> " " <> T.unwords (map quoteWord ps)
  block = case directiveChildren d of
    [] -> ""
    cs ->
      " {\n"
        <> foldMap (formatDirective (depth + 1)) cs
        <> indent
        <> "}"

quoteWord :: Text -> Text
quoteWord t = "\"" <> T.concatMap escape t <> "\""
 where
  escape '"' = "\\\""
  escape '\\' = "\\\\"
  escape c = T.singleton c