163 lines
5.1 KiB
Haskell
163 lines
5.1 KiB
Haskell
{-# LANGUAGE RecordWildCards #-}
|
|
{-# LANGUAGE OverloadedStrings #-}
|
|
|
|
module Main where
|
|
|
|
import Control.Applicative ((<|>), optional)
|
|
import Control.Exception (SomeException)
|
|
import Data.Aeson (Value)
|
|
import Data.Monoid ((<>))
|
|
import Data.Version (showVersion)
|
|
import Dhall.JSON (Conversion, SpecialDoubleMode(..))
|
|
import Options.Applicative (Parser, ParserInfo)
|
|
|
|
import qualified Control.Exception
|
|
import qualified Data.Aeson
|
|
import qualified Data.Aeson.Encode.Pretty
|
|
import qualified Data.ByteString.Lazy
|
|
import qualified Data.Text.IO as Text.IO
|
|
import qualified Dhall
|
|
import qualified Dhall.JSON
|
|
import qualified GHC.IO.Encoding
|
|
import qualified Options.Applicative as Options
|
|
import qualified Paths_dhall_json as Meta
|
|
import qualified System.Exit
|
|
import qualified System.IO
|
|
|
|
data Options
|
|
= Options
|
|
{ explain :: Bool
|
|
, pretty :: Bool
|
|
, omission :: Value -> Value
|
|
, conversion :: Conversion
|
|
, approximateSpecialDoubles :: Bool
|
|
, file :: Maybe FilePath
|
|
, output :: Maybe FilePath
|
|
}
|
|
| Version
|
|
|
|
parseOptions :: Parser Options
|
|
parseOptions =
|
|
( Options
|
|
<$> parseExplain
|
|
<*> parsePretty
|
|
<*> Dhall.JSON.parsePreservationAndOmission
|
|
<*> Dhall.JSON.parseConversion
|
|
<*> parseApproximateSpecialDoubles
|
|
<*> optional parseFile
|
|
<*> optional parseOutput
|
|
)
|
|
<|> parseVersion
|
|
where
|
|
parseExplain =
|
|
Options.switch
|
|
( Options.long "explain"
|
|
<> Options.help "Explain error messages in detail"
|
|
)
|
|
|
|
parsePretty =
|
|
prettyFlag <|> compactFlag <|> defaultBehavior
|
|
where
|
|
prettyFlag =
|
|
Options.flag'
|
|
True
|
|
( Options.long "pretty"
|
|
<> Options.help "Deprecated, will be removed soon. Pretty print generated JSON"
|
|
)
|
|
|
|
compactFlag =
|
|
Options.flag'
|
|
False
|
|
( Options.long "compact"
|
|
<> Options.help "Render JSON on one line"
|
|
)
|
|
|
|
defaultBehavior =
|
|
pure True
|
|
|
|
parseVersion =
|
|
Options.flag'
|
|
Version
|
|
( Options.long "version"
|
|
<> Options.help "Display version"
|
|
)
|
|
|
|
parseApproximateSpecialDoubles =
|
|
Options.switch
|
|
( Options.long "approximate-special-doubles"
|
|
<> Options.help "Use approximate representation for NaN/±Infinity"
|
|
)
|
|
|
|
parseFile =
|
|
Options.strOption
|
|
( Options.long "file"
|
|
<> Options.help "Read expression from a file instead of standard input"
|
|
<> Options.metavar "FILE"
|
|
)
|
|
|
|
parseOutput =
|
|
Options.strOption
|
|
( Options.long "output"
|
|
<> Options.help "Write JSON to a file instead of standard output"
|
|
<> Options.metavar "FILE"
|
|
)
|
|
|
|
parserInfo :: ParserInfo Options
|
|
parserInfo =
|
|
Options.info
|
|
(Options.helper <*> parseOptions)
|
|
( Options.fullDesc
|
|
<> Options.progDesc "Compile Dhall to JSON"
|
|
)
|
|
|
|
main :: IO ()
|
|
main = do
|
|
GHC.IO.Encoding.setLocaleEncoding GHC.IO.Encoding.utf8
|
|
|
|
options <- Options.execParser parserInfo
|
|
|
|
case options of
|
|
Version -> do
|
|
putStrLn (showVersion Meta.version)
|
|
|
|
Options {..} -> do
|
|
handle $ do
|
|
let config = Data.Aeson.Encode.Pretty.Config
|
|
{ Data.Aeson.Encode.Pretty.confIndent = Data.Aeson.Encode.Pretty.Spaces 2
|
|
, Data.Aeson.Encode.Pretty.confCompare = compare
|
|
, Data.Aeson.Encode.Pretty.confNumFormat = Data.Aeson.Encode.Pretty.Generic
|
|
, Data.Aeson.Encode.Pretty.confTrailingNewline = False }
|
|
let encode =
|
|
if pretty
|
|
then Data.Aeson.Encode.Pretty.encodePretty' config
|
|
else Data.Aeson.encode
|
|
|
|
let explaining = if explain then Dhall.detailed else id
|
|
|
|
let specialDoubleMode =
|
|
if approximateSpecialDoubles
|
|
then ApproximateWithinJSON
|
|
else ForbidWithinJSON
|
|
|
|
text <- case file of
|
|
Nothing -> Text.IO.getContents
|
|
Just path -> Text.IO.readFile path
|
|
|
|
json <- omission <$> explaining (Dhall.JSON.codeToValue conversion specialDoubleMode file text)
|
|
|
|
let write =
|
|
case output of
|
|
Nothing -> Data.ByteString.Lazy.putStr
|
|
Just file_ -> Data.ByteString.Lazy.writeFile file_
|
|
|
|
write (encode json <> "\n")
|
|
|
|
handle :: IO a -> IO a
|
|
handle = Control.Exception.handle handler
|
|
where
|
|
handler :: SomeException -> IO a
|
|
handler e = do
|
|
System.IO.hPutStrLn System.IO.stderr ""
|
|
System.IO.hPrint System.IO.stderr e
|
|
System.Exit.exitFailure
|