{-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} -- | This module contains the implementation of the @dhall format@ subcommand module Dhall.Format ( -- * Format Format(..) , format ) where import Data.Monoid ((<>)) import Dhall.Pretty (CharacterSet(..), annToAnsiStyle) import Dhall.Util ( Censor , CheckFailed(..) , Header(..) , Input(..) , OutputMode(..) ) 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 -- | Arguments to the `format` subcommand data Format = Format { characterSet :: CharacterSet , censor :: Censor , input :: Input , outputMode :: OutputMode } -- | Implementation of the @dhall format@ subcommand 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 = do headerAndExpr <- Dhall.Util.getExpressionAndHeader censor input return (layoutHeaderAndExpr headerAndExpr) case outputMode of Write -> do docStream <- layoutInput case input 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 input of InputFile file -> Data.Text.IO.readFile file StandardInput -> Data.Text.IO.getContents docStream <- case input of InputFile _ -> layoutInput StandardInput -> do headerAndExpr <- Dhall.Util.getExpressionAndHeaderFromStdinText censor originalText return (layoutHeaderAndExpr headerAndExpr) let formattedText = Pretty.Text.renderStrict docStream if originalText == formattedText then return () else do let command = "format" let modified = "formatted" Control.Exception.throwIO CheckFailed{..}