on master help sign in
Merge pull request #200 from andreasabel/option-o

Fix #199: adding option -o to the converters

commit52b5c516b1c222e774f39bc1c2959c88b81fed8c authorMichael Snoyman <michael@snoyman.com> dateSat 18 Sep 2021, 19:40 (5 years ago) parent81e9b29aeeddf1
3 files changed+89−32
yaml/exe/Common.hs+11−3 yaml/exe/json2yaml.hs+35−7 yaml/exe/yaml2json.hs+43−22
yaml/exe/Common.hs+11−3
@@ -28,6 +28,16 @@ homepage = "https://github.com/snoyberg/yaml/"
2828version :: String
2929version = intercalate "." $ map show $ versionBranch Paths.version
3030
31+-- | The version header including given program name and 'homepage'.
32+
33+versionText :: String -> String
34+versionText self = unwords
35+ [ self
36+ , "version"
37+ , version
38+ , homepage -- concat [ "<", homepage, ">" ]
39+ ]
40+
3141-- | Option @--numeric-version@.
3242
3343numericVersionOption :: Parser (a -> a)
@@ -41,13 +51,11 @@ numericVersionOption =
4151
4252versionOption :: String -> Parser (a -> a)
4353versionOption self =
44− infoOption (unwords versionWords)
54+ infoOption (versionText self)
4555 $ long "version"
4656 <> short 'V'
4757 <> hidden
4858 <> help "Show version info."
49− where
50− versionWords = [ self, "version", version, homepage ]
5159
5260-- * Misc
5361---------------------------------------------------------------------------
yaml/exe/json2yaml.hs+35−7
@@ -10,14 +10,16 @@ import Data.Semigroup ( Semigroup(..) )
1010#endif
1111
1212import Options.Applicative
13− ( Parser
14− , action, execParser, header, help, helper, info
15− , metavar, strArgument, value
13+ ( Parser, (<|>)
14+ , action, execParser, footerDoc, headerDoc, help, helper, hidden, info
15+ , long, metavar, short, strArgument, strOption, value
1616 )
17+import Options.Applicative.Help.Pretty
18+ ( vcat, text )
1719
1820import System.Exit ( die )
1921
20−import Common ( dashToNothing, versionOption, numericVersionOption )
22+import Common ( dashToNothing, versionText, versionOption, numericVersionOption )
2123
2224data Options = Options
2325 { optInput :: Maybe FilePath
@@ -37,9 +39,21 @@ options :: IO Options
3739options =
3840 execParser $
3941 info (helper <*> versionOption self <*> numericVersionOption <*> programOptions)
40− (header "Reads a JSON document and writes it out as YAML document.")
42+ $ headerDoc hdoc
43+ <> footerDoc fdoc
4144
4245 where
46+ hdoc = Just $ vcat $ map text
47+ [ versionText self
48+ , "Convert JSON to YAML."
49+ ]
50+ fdoc = Just $ text $ concat
51+ [ "The old call pattern '"
52+ , self
53+ , " IN OUT' is also accepted, but deprecated."
54+ ]
55+
56+ programOptions :: Parser Options
4357 programOptions = Options <$> oInput <*> oOutput
4458
4559 oInput :: Parser (Maybe FilePath)
@@ -48,15 +62,29 @@ options =
4862 $ metavar "IN"
4963 <> value "-"
5064 <> action "file"
51− <> help "The input file containing the JSON document; use '-' for stdin."
65+ <> help "The input file containing the JSON document; use '-' for stdin (default)."
5266
5367 oOutput :: Parser (Maybe FilePath)
5468 oOutput = dashToNothing <$> do
69+ oOutputExplicit <|> oOutputImplicit
70+
71+ oOutputExplicit :: Parser FilePath
72+ oOutputExplicit =
73+ strOption
74+ $ long "output"
75+ <> short 'o'
76+ <> metavar "OUT"
77+ <> action "file"
78+ -- <> help "The file to hold the produced YAML document; use '-' for stdout (default)."
79+
80+ oOutputImplicit :: Parser FilePath
81+ oOutputImplicit =
5582 strArgument
5683 $ metavar "OUT"
5784 <> value "-"
5885 <> action "file"
59− <> help "The file to hold the produced YAML document; use '-' for stdout."
86+ <> hidden
87+ <> help "The file to hold the produced YAML document; use '-' for stdout (default)."
6088
6189-- | Exit with 'self'-stamped error message.
6290
yaml/exe/yaml2json.hs+43−22
@@ -2,31 +2,31 @@
22{-# LANGUAGE LambdaCase #-}
33{-# LANGUAGE NamedFieldPuns #-}
44
5−import Prelude hiding (putStr, getContents)
6−
75import Data.Aeson (encode, Value)
8−import Data.ByteString (getContents)
9−import Data.ByteString.Lazy (putStr)
6+import qualified Data.ByteString as S (getContents)
7+import qualified Data.ByteString.Lazy as L (putStr, writeFile)
108#if !MIN_VERSION_base(4,11,0)
119import Data.Semigroup (Semigroup(..))
1210#endif
1311import Data.Yaml (decodeFileEither, decodeEither')
12+import System.Exit (die)
1413
1514import Options.Applicative
1615 ( Parser
17− , action, execParser, header, help, helper, info
18− , metavar, strArgument
16+ , action, execParser, headerDoc, help, helper, info
17+ , long, metavar, short, strArgument, strOption, value
1918 )
20−
21−import System.Exit
22−import System.IO (stderr, hPrint)
19+import Options.Applicative.Help.Pretty
20+ ( vcat, text )
2321
2422import Common
25− ( versionOption, numericVersionOption, dashToNothing )
23+ ( versionText, versionOption, numericVersionOption, dashToNothing )
2624
27−newtype Options = Options
25+data Options = Options
2826 { optInput :: Maybe FilePath
2927 -- ^ 'Nothing' means @stdin@.
28+ , optOutput :: Maybe FilePath
29+ -- ^ 'Nothing' means @stdout@.
3030 }
3131
3232-- | Name of the executable.
@@ -40,27 +40,48 @@ options :: IO Options
4040options =
4141 execParser $
4242 info (helper <*> versionOption self <*> numericVersionOption <*> programOptions)
43− (header "Reads given YAML document and prints it in JSON format to standard out.")
43+ (headerDoc hdoc)
4444
4545 where
46− programOptions = Options <$> oInput
46+ hdoc = Just $ vcat $ map text
47+ [ versionText self
48+ , "Convert YAML to JSON."
49+ ]
50+
51+ programOptions = Options <$> oInput <*> oOutput
4752
4853 oInput :: Parser (Maybe FilePath)
4954 oInput = dashToNothing <$> do
5055 strArgument
51− $ metavar "FILE"
56+ $ metavar "IN"
57+ <> value "-"
5258 <> action "file"
53− <> help "The input file containing the YAML document; use '-' for stdin."
59+ <> help "The input file containing the YAML document; use '-' for stdin (default)."
60+
61+ oOutput :: Parser (Maybe FilePath)
62+ oOutput = dashToNothing <$> do
63+ strOption
64+ $ long "output"
65+ <> short 'o'
66+ <> value "-"
67+ <> metavar "OUT"
68+ <> action "file"
69+ <> help "The file to hold the produced JSON document; use '-' for stdout (default)."
5470
55−showJSON :: Show a => Either a Value -> IO b
56−showJSON = \case
57− Left err -> hPrint stderr err >> exitFailure
58− Right res -> putStr (encode (res :: Value)) >> exitSuccess
5971
6072main :: IO ()
6173main = do
62− Options{ optInput } <- options
63− showJSON =<< case optInput of
74+ Options{ optInput, optOutput } <- options
75+
76+ -- Input YAML.
77+ result <- case optInput of
6478 -- strict getContents will read in all of stdin at once
65− Nothing -> decodeEither' <$> getContents
79+ Nothing -> decodeEither' <$> S.getContents
6680 Just f -> decodeFileEither f
81+
82+ -- Output JSON.
83+ case result of
84+ Left err -> die $ show err
85+ Right val -> do
86+ let json = encode (val :: Value)
87+ maybe L.putStr L.writeFile optOutput json