dhall-yaml-1.2.9: yaml-to-dhall/Main.hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Main where
import Control.Applicative (optional, (<|>))
import Control.Exception (SomeException)
import Data.Text (Text)
import Data.Version (showVersion)
import Dhall.JSONToDhall (Conversion, parseConversion)
import Dhall.Pretty (CharacterSet (..))
import Dhall.YamlToDhall (Options (..), dhallFromYaml)
import Options.Applicative (Parser, ParserInfo)
import qualified Control.Exception
import qualified Data.ByteString.Char8 as BSL8
import qualified Dhall.Util
import qualified Dhall.YamlToDhall as YamlToDhall
import qualified GHC.IO.Encoding
import qualified Options.Applicative as Options
import qualified Paths_dhall_yaml as Meta
import qualified System.Exit
import qualified System.IO as IO
-- ---------------
-- Command options
-- ---------------
data CommandOptions
= Default
{ schema :: Maybe Text
, conversion :: Conversion
, file :: Maybe FilePath
, output :: Maybe FilePath
, ascii :: Bool
, plain :: Bool
}
| Type
{ file :: Maybe FilePath
, output :: Maybe FilePath
, ascii :: Bool
, plain :: Bool
}
| Version
deriving (Show)
-- | Command info and description
parserInfo :: ParserInfo CommandOptions
parserInfo = Options.info
( Options.helper <*> parseOptions)
( Options.fullDesc
<> Options.progDesc "Convert a YAML expression to a Dhall expression, given the expected Dhall type"
)
-- | Parser for all the command arguments and options
parseOptions :: Parser CommandOptions
parseOptions =
typeCommand
<|> ( Default
<$> optional parseSchema
<*> parseConversion
<*> optional parseFile
<*> optional parseOutput
<*> parseASCII
<*> parsePlain
)
<|> parseVersion
where
typeCommand =
Options.hsubparser
(Options.command "type" info <> Options.metavar "type")
where
info = Options.info parser (Options.progDesc "Output the inferred Dhall type from a YAML value")
parser =
Type
<$> optional parseFile
<*> optional parseOutput
<*> parseASCII
<*> parsePlain
parseSchema =
Options.strArgument
( Options.metavar "SCHEMA"
<> Options.help "Dhall type expression (schema)"
)
parseVersion =
Options.flag'
Version
( Options.long "version"
<> Options.short 'V'
<> Options.help "Display version"
)
parseFile =
Options.strOption
( Options.long "file"
<> Options.help "Read YAML expression from a file instead of standard input"
<> Options.metavar "FILE"
<> Options.action "file"
)
parseOutput =
Options.strOption
( Options.long "output"
<> Options.help "Write Dhall expression to a file instead of standard output"
<> Options.metavar "FILE"
<> Options.action "file"
)
parseASCII =
Options.switch
( Options.long "ascii"
<> Options.help "Format code using only ASCII syntax"
)
parsePlain =
Options.switch
( Options.long "plain"
<> Options.help "Disable syntax highlighting"
)
-- ----------
-- Main
-- ----------
main :: IO ()
main = do
GHC.IO.Encoding.setLocaleEncoding GHC.IO.Encoding.utf8
options <- Options.execParser parserInfo
let toCharacterSet ascii = case ascii of
True -> ASCII
False -> Unicode
let toBytes file = case file of
Nothing -> BSL8.getContents
Just path -> BSL8.readFile path
case options of
Version ->
putStrLn (showVersion Meta.version)
Default{..} -> do
let characterSet = toCharacterSet ascii
handle $ do
yaml <- toBytes file
expression <- dhallFromYaml (Options schema conversion) yaml
Dhall.Util.renderExpression characterSet plain output expression
Type{..} -> do
let characterSet = toCharacterSet ascii
handle $ do
yaml <- toBytes file
schema <- YamlToDhall.schemaFromYaml yaml
Dhall.Util.renderExpression characterSet plain output schema
handle :: IO a -> IO a
handle = Control.Exception.handle handler
where
handler :: SomeException -> IO a
handler e = do
IO.hPutStrLn IO.stderr ""
IO.hPrint IO.stderr e
System.Exit.exitFailure