jsonnet-0.3.0.0: app/Main.hs
{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TemplateHaskell #-}
module Main where
import Control.Monad.Except
import qualified Data.Aeson as JSON
import Data.ByteString.Builder (toLazyByteString)
import qualified Data.ByteString.Lazy as L
import Data.ByteString.Lazy.Char8 as LC (putStrLn)
import Data.Maybe
import Data.Text (Text)
import qualified Data.Text as T
import Data.Text.Encoding (encodeUtf8Builder)
import qualified Data.Text.IO as TIO
import Data.Version (showVersion)
import Language.Jsonnet
import Language.Jsonnet.Annotate
import Language.Jsonnet.Desugar
import Language.Jsonnet.Error
import Language.Jsonnet.Eval
-- import Language.Jsonnet.Value
import Options.Applicative
import Paths_jsonnet (version)
import Text.PrettyPrint.ANSI.Leijen (Pretty, pretty)
main :: IO ()
main = do
runProgram =<< execParser options
return ()
runProgram ::
-- |
Options ->
IO ()
runProgram opts@Options {..} = do
src <- readSource input
conf <- mkConfig opts
outp <- interpret conf src
either printError (printResult output format) outp
printResult :: Output -> Format -> JSON.Value -> IO ()
printResult outp Json val =
writeOutput (JSON.encode val) outp
printResult outp Plaintext (JSON.String s) =
writeOutput (encodeToLazyByteString s) outp
where
encodeToLazyByteString =
toLazyByteString . encodeUtf8Builder
printResult _ Plaintext _ =
print "Runtime error: expected string result"
writeOutput :: L.ByteString -> Output -> IO ()
writeOutput bs = \case
FileOutput path -> L.writeFile path bs
Stdout -> LC.putStrLn bs
printError :: Error -> IO ()
printError = print . pretty
readSource :: Input -> IO Text
readSource = \case
Stdin -> TIO.getContents
FileInput path -> TIO.readFile path
ExecInput str -> pure (T.pack str)
mkConfig :: Options -> IO Config
mkConfig Options {..} = do
let fname = case input of
Stdin -> ""
FileInput path -> path
ExecInput _ -> ""
pure Config {..}
fileOutput :: Parser Output
fileOutput =
fromMaybe Stdout
<$> ( optional $
FileOutput
<$> strOption
( long "output-file"
<> short 'o'
<> metavar "<filename>"
<> help "Write to the output file rather than stdout"
)
)
fileInput :: Parser (Maybe String)
fileInput =
optional $
strArgument
( metavar "<filename>"
<> help "Jsonnet source file or stdin"
)
parseOpts :: Parser Options
parseOpts = do
input <- mkInput <$> exec <*> fileInput
output <- fileOutput
format <-
flag
Json
Plaintext
( long "string"
<> short 'S'
<> help "Expect a string, manifest as plain text"
)
pure Options {..}
mkInput :: Bool -> Maybe String -> Input
mkInput exec = \case
Nothing -> Stdin
Just e | exec -> ExecInput e
Just p | otherwise -> FileInput p
exec :: Parser Bool
exec =
switch
( long "exec"
<> short 'e'
<> help "Treat filename as code"
)
ver :: Parser (a -> a)
ver =
infoOption
verStr
( long "version"
<> short 'v'
<> help "Print version of the program"
)
where
verStr = "Jsonnet command line " <> showVersion version
options :: ParserInfo Options
options =
info
(ver <*> helper <*> parseOpts)
( fullDesc
<> noIntersperse
)
data Options = Options
{ output :: Output,
format :: Format,
input :: Input
}
data Input
= FileInput FilePath
| ExecInput String
| Stdin
deriving (Eq, Show)
data Output
= FileOutput FilePath
| Stdout
deriving (Eq, Show)
data Format = Json | Plaintext
deriving (Eq, Show)