{-# 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") originalText <- case input of InputFile file -> Data.Text.IO.readFile file StandardInput -> Data.Text.IO.getContents headerAndExpr <- Dhall.Util.getExpressionAndHeaderFromStdinText censor originalText let docStream = layoutHeaderAndExpr headerAndExpr let formattedText = Pretty.Text.renderStrict docStream case outputMode of Write -> do case input of InputFile file -> do if originalText == formattedText then return () else 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 if originalText == formattedText then return () else do let command = "format" let modified = "formatted" Control.Exception.throwIO CheckFailed{..}