@@ -1,31 +1,96 @@
2+{-# LANGUAGE LambdaCase #-}
3+{-# LANGUAGE NamedFieldPuns #-}
1import Prelude hiding (putStr, getContents)
5import Prelude hiding (putStr, getContents)
3−import Data.Aeson (encode, Value)
7+import Data.Aeson (encode, Value)
4−import Data.ByteString (getContents)
8+import Data.ByteString (getContents)
5import Data.ByteString.Lazy (putStr)
9import Data.ByteString.Lazy (putStr)
6−import System.Environment (getArgs)
10+import Data.List (intercalate)
11+#if !MIN_VERSION_base(4,11,0)
12+import Data.Semigroup (Semigroup(..))
14+import Data.Version (Version(versionBranch))
15+import Data.Yaml (decodeFileEither, decodeEither')
17+import Options.Applicative
19+ , action, execParser, header, help, helper, hidden
20+ , info, infoOption, long, metavar, short, strArgument
7import System.Exit
23import System.Exit
8−import System.IO (stderr, hPutStrLn)
24+import System.IO (stderr, hPrint)
26+import qualified Paths_yaml as Paths
28+newtype Options = Options
29+ { optInput :: Maybe FilePath
30+ -- ^ Nothing means @stdin@.
33+-- | Name of the executable.
38+-- | Homepage for this program.
10−import Data.Yaml (decodeFileEither, decodeEither')
40+homepage :: String
41+homepage = "https://github.com/snoyberg/yaml/"
12−helpMessage :: IO ()
43+-- | Version in @x.y.z@ format.
13−helpMessage = putStrLn "Usage: yaml2json FILE\n\nuse '-' as FILE to indicate stdin" >> exitFailure
44+
46+version = intercalate "." $ map show $ versionBranch Paths.version
48+-- | Parse options; handle parse errors, @--help@, @--version@.
53+ info (helper <*> versionOption <*> numericVersionOption <*> programOptions)
54+ (header "Reads given YAML document and prints it JSON format to standard out.")
58+ infoOption (unwords versionWords)
62+ <> help "Show version info."
63+ versionWords = [ self, "version", version, homepage ]
65+ numericVersionOption =
67+ $ long "numeric-version"
69+ <> help "Show just version number."
71+ programOptions = Options <$> oInput
73+ oInput :: Parser (Maybe FilePath)
74+ oInput = dashToStdin <$> do
78+ <> help "The input file containing the YAML document; use '-' for stdin."
80+ -- dash is interpreted as stdin
15showJSON :: Show a => Either a Value -> IO b
85showJSON :: Show a => Either a Value -> IO b
16−showJSON ejson =
86+showJSON = \case
18− Left err -> hPutStrLn stderr (show err) >> exitFailure
87+ Left err -> hPrint stderr err >> exitFailure
19− Right res -> putStr (encode (res :: Value)) >> exitSuccess
88+ Right res -> putStr (encode (res :: Value)) >> exitSuccess
21main :: IO ()
90main :: IO ()
23− args <- getArgs
92+ Options{ optInput } <- options
24− case args of
93+ showJSON =<< case optInput of
25− -- strict getContents will read in all of stdin at once
94+ -- strict getContents will read in all of stdin at once
26− (["-h"]) -> helpMessage
95+ Nothing -> decodeEither' <$> getContents
27− (["--help"]) -> helpMessage
28− (["-"]) -> getContents >>= showJSON . decodeEither'
29− ([f]) -> decodeFileEither f >>= showJSON
96+ Just f -> decodeFileEither f