{-# 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)
import Dhall.Util (Censor, Input(..), Header(..))
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.AtomicWrite.Writer.LazyText as AtomicWrite.LazyText
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 {..}) = do
let layoutHeaderAndExpr (Header header, expr) =
Dhall.Pretty.layout
( Pretty.pretty header
<> Dhall.Pretty.prettyCharacterSet characterSet expr
<> "\n")
let layoutInput input = do
headerAndExpr <- Dhall.Util.getExpressionAndHeader censor input
return (layoutHeaderAndExpr headerAndExpr)
case formatMode of
Modify {..} -> do
docStream <- layoutInput inplace
case inplace of
InputFile file -> do
AtomicWrite.LazyText.atomicWriteFile
file
(Pretty.Text.renderLazy docStream)
StandardInput -> do
supportsANSI <- System.Console.ANSI.hSupportsANSI System.IO.stdout
Pretty.Terminal.renderIO
System.IO.stdout
(if supportsANSI
then (fmap annToAnsiStyle docStream)
else (Pretty.unAnnotateS docStream))
Check {..} -> do
originalText <- case path of
InputFile file -> Data.Text.IO.readFile file
StandardInput -> Data.Text.IO.getContents
docStream <- case path of
InputFile _ -> layoutInput path
StandardInput -> do
headerAndExpr <- Dhall.Util.getExpressionAndHeaderFromStdinText censor originalText
return (layoutHeaderAndExpr headerAndExpr)
let formattedText = Pretty.Text.renderStrict docStream
if originalText == formattedText
then return ()
else Control.Exception.throwIO NotFormatted