11{-# LANGUAGE TupleSections #-}
22{-# LANGUAGE OverloadedStrings #-}
3+ {-# LANGUAGE TypeApplications #-}
34
45module Cli
56 ( Args (.. )
@@ -13,7 +14,9 @@ import Data.Bifunctor (bimap)
1314import qualified Data.Text as T
1415import qualified Expr as E
1516import Options.Applicative hiding (Const )
16- import Text.Read (readMaybe )
17+ import qualified Text.Parsec as P
18+ import qualified Text.Parsec.String as P
19+ import Data.Functor (($>) )
1720
1821
1922type Field = (T. Text , E. Expr )
@@ -31,13 +34,32 @@ data Amount = Const Int
3134 deriving (Show )
3235
3336
34- parseNum :: ReadM Amount
35- parseNum = eitherReader parseNum'
37+ mapLeft :: (a -> c ) -> Either a b -> Either c b
38+ mapLeft f = either (Left . f) Right
39+
40+
41+ -- >>> P.parse numParser "<num>" "Inf"
42+ -- Right Infinite
43+ --
44+ -- >>> P.parse numParser "<num>" "200"
45+ -- Right (Const 200)
46+ --
47+ -- >>> P.parse numParser "<num>" "5e4"
48+ -- Right (Const 50000)
49+ numParser :: P. Parser Amount
50+ numParser = inf <|> integer
3651 where
37- parseNum' " Inf" = Right Infinite
38- parseNum' s = case readMaybe s of
39- (Just n) -> Right (Const n)
40- Nothing -> Left " Expected a number or `Inf` for infinite records"
52+ inf = P. string " Inf" $> Infinite
53+ integer = do
54+ digits <- read @ Int <$> P. many1 P. digit
55+ power <- P. optionMaybe eNotation
56+ pure . Const $ digits * maybe 1 (10 ^ ) power
57+ eNotation :: P. Parser Int
58+ eNotation = read @ Int <$> (P. oneOf " eE" >> P. many1 P. digit)
59+
60+
61+ parseNum :: ReadM Amount
62+ parseNum = eitherReader $ \ s -> mapLeft show $ P. parse numParser s s
4163
4264
4365parseExpr :: String -> Either String Field
@@ -52,7 +74,7 @@ parseExpr s =
5274
5375args :: Parser Args
5476args = Args
55- <$> optional
77+ <$> optional
5678 ( option auto
5779 ( long " seed"
5880 <> help " A seed for the random data generator"
@@ -62,12 +84,11 @@ args = Args
6284 <> value (Const 1 )
6385 <> help " Number of records to generate. Use `Inf` for infinite records" )
6486 <*> many (argument (eitherReader parseExpr) (metavar " FIELDS..." ))
65-
6687
6788
6889parseArgs :: [String ] -> IO Args
6990parseArgs cliArgs = handleParseResult $ execParserPure defaultPrefs opts cliArgs
7091 where
7192 opts = info (args <**> helper)
72- ( fullDesc <> progDesc
93+ ( fullDesc <> progDesc
7394 " Generate random JSON records. Use <field>=<provider> pairs to specify the fields the records should have." )
0 commit comments