{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
module Dhall.Format
(
Format(..)
, FormatMode(..)
, format
) where
import Control.Exception (Exception)
import Data.Monoid ((<>))
import Dhall.Pretty (CharacterSet(..), annToAnsiStyle, layoutOpts)
import Dhall.Util (Censor, Input(..))
import qualified Data.Text.Prettyprint.Doc as Pretty
import qualified Data.Text.Prettyprint.Doc.Render.Terminal as Pretty.Terminal
import qualified Data.Text.Prettyprint.Doc.Render.Text as Pretty.Text
import qualified Control.Exception
import qualified Data.Text.IO
import qualified Dhall.Pretty
import qualified Dhall.Util
import qualified System.Console.ANSI
import qualified System.IO
data NotFormatted = NotFormatted
deriving (Exception)
instance Show NotFormatted where
show _ = ""
data Format = Format
{ characterSet :: CharacterSet
, censor :: Censor
, formatMode :: FormatMode
}
data FormatMode
= Modify { inplace :: Input }
| Check { path :: Input }
format
:: Format
-> IO ()
format (Format {..}) =
case formatMode of
Modify {..} ->
case inplace of
InputFile file -> do
(header, expr) <- Dhall.Util.getExpressionAndHeader censor (InputFile file)
let doc = Pretty.pretty header
<> Pretty.unAnnotate (Dhall.Pretty.prettyCharacterSet characterSet expr)
<> "\n"
System.IO.withFile file System.IO.WriteMode (\handle -> do
Pretty.Terminal.renderIO handle (Pretty.layoutSmart layoutOpts doc))
StandardInput -> do
(header, expr) <- Dhall.Util.getExpressionAndHeader censor StandardInput
let doc = Pretty.pretty header
<> Dhall.Pretty.prettyCharacterSet characterSet expr
<> "\n"
supportsANSI <- System.Console.ANSI.hSupportsANSI System.IO.stdout
if supportsANSI
then
Pretty.Terminal.renderIO
System.IO.stdout
(fmap annToAnsiStyle (Pretty.layoutSmart layoutOpts doc))
else
Pretty.Terminal.renderIO
System.IO.stdout
(Pretty.layoutSmart layoutOpts (Pretty.unAnnotate doc))
Check {..} -> do
originalText <- case path of
InputFile file -> Data.Text.IO.readFile file
StandardInput -> Data.Text.IO.getContents
(header, expr) <- Dhall.Util.getExpressionAndHeader censor path
let doc = Pretty.pretty header
<> Pretty.unAnnotate (Dhall.Pretty.prettyCharacterSet characterSet expr)
<> "\n"
let formattedText =
Pretty.Text.renderStrict (Pretty.layoutSmart layoutOpts doc)
if originalText == formattedText
then return ()
else Control.Exception.throwIO NotFormatted