{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NoFieldSelectors #-}
{-# LANGUAGE RecordWildCards #-}
module EVP
( Name
, Error(..)
, Scan
, Var(..)
, string
, yaml
, parse
, secret
, group
, defaultsTo
, Settings(..)
, def
, scan
, scanWith
, enumerate
, help
, GroupStack
, renderError
, assumePrefix
, obsolete
, modifyError
) where
import Control.Applicative
import Control.Monad
import Data.Bifunctor
import Data.Default.Class
import Data.List (isPrefixOf, intercalate)
import Data.Map.Strict qualified as Map
import Data.Set qualified as Set
import Data.String
import Data.Yaml qualified as Yaml
import Data.Text qualified as T
import Data.Text.Lazy qualified as TL
import Data.Text.Encoding
import Data.Typeable
import EVP.Internal
import System.Environment
import System.Exit
import System.IO
data Var a = Var
{ forall a. Var a -> Name
name :: Name
, forall a. Var a -> Maybe a
defaultValue :: Maybe a
, forall a. Var a -> Maybe Name
metavar :: Maybe String
} deriving (Int -> Var a -> ShowS
forall a. Show a => Int -> Var a -> ShowS
forall a. Show a => [Var a] -> ShowS
forall a. Show a => Var a -> Name
forall a.
(Int -> a -> ShowS) -> (a -> Name) -> ([a] -> ShowS) -> Show a
showList :: [Var a] -> ShowS
$cshowList :: forall a. Show a => [Var a] -> ShowS
show :: Var a -> Name
$cshow :: forall a. Show a => Var a -> Name
showsPrec :: Int -> Var a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Var a -> ShowS
Show, Var a -> Var a -> Bool
forall a. Eq a => Var a -> Var a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Var a -> Var a -> Bool
$c/= :: forall a. Eq a => Var a -> Var a -> Bool
== :: Var a -> Var a -> Bool
$c== :: forall a. Eq a => Var a -> Var a -> Bool
Eq)
defaultsTo :: Var a -> a -> Var a
defaultsTo :: forall a. Var a -> a -> Var a
defaultsTo Var a
v a
a = Var a
v { $sel:defaultValue:Var :: Maybe a
defaultValue = forall a. a -> Maybe a
Just a
a }
infixl 1 `defaultsTo`
instance Typeable a => IsString (Var a) where
fromString :: Name -> Var a
fromString Name
name = forall a. Name -> Maybe a -> Maybe Name -> Var a
Var Name
name forall a. Maybe a
Nothing forall a. Maybe a
Nothing
string :: (IsString a, Show a, Typeable a) => Var a -> Scan a
string :: forall a. (IsString a, Show a, Typeable a) => Var a -> Scan a
string Var{Name
Maybe a
Maybe Name
metavar :: Maybe Name
defaultValue :: Maybe a
name :: Name
$sel:metavar:Var :: forall a. Var a -> Maybe Name
$sel:defaultValue:Var :: forall a. Var a -> Maybe a
$sel:name:Var :: forall a. Var a -> Name
..} = forall a b. ScanF a -> Scan (a -> b) -> Scan b
Scan ScanF
{ Name
name :: Name
name :: Name
name
, parser :: Maybe Name -> Either Error (Name, a)
parser = \case
Maybe Name
Nothing -> case Maybe a
defaultValue of
Maybe a
Nothing -> forall a b. a -> Either a b
Left (Name -> Error
Missing Name
name)
Just a
d -> forall a b. b -> Either a b
Right (forall a. Show a => a -> Name
show a
d forall a. Semigroup a => a -> a -> a
<> Name
" (default)", a
d)
Just Name
x -> forall a b. b -> Either a b
Right (Name
x, forall a. IsString a => Name -> a
fromString Name
x)
, metavar :: Maybe Name
metavar = Maybe Name
metavar forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall a. (Typeable a, Show a) => a -> Name
toString forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe a
defaultValue
} (forall a. a -> Scan a
Pure forall a. a -> a
id)
toString :: (Typeable a, Show a) => a -> String
toString :: forall a. (Typeable a, Show a) => a -> Name
toString a
val
| Just Name
str <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
val = Name
str
| Just Text
str <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
val = Text -> Name
T.unpack Text
str
| Just Text
str <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
val = Text -> Name
TL.unpack Text
str
| Just ByteString
str <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
val = Text -> Name
T.unpack forall a b. (a -> b) -> a -> b
$ ByteString -> Text
decodeUtf8 ByteString
str
| Bool
otherwise = forall a. Show a => a -> Name
show a
val
yaml :: forall a. (Show a, Typeable a, Yaml.FromJSON a, Yaml.ToJSON a) => Var a -> Scan a
yaml :: forall a.
(Show a, Typeable a, FromJSON a, ToJSON a) =>
Var a -> Scan a
yaml Var{Name
Maybe a
Maybe Name
metavar :: Maybe Name
defaultValue :: Maybe a
name :: Name
$sel:metavar:Var :: forall a. Var a -> Maybe Name
$sel:defaultValue:Var :: forall a. Var a -> Maybe a
$sel:name:Var :: forall a. Var a -> Name
..} = forall a. Show a => Var a -> (Name -> Either Name a) -> Scan a
parse Var
{ $sel:metavar:Var :: Maybe Name
metavar = Maybe Name
metavar
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Text -> Name
T.unpack forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
T.strip forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Text
decodeUtf8 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. ToJSON a => a -> ByteString
Yaml.encode) Maybe a
defaultValue
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall a. a -> Maybe a
Just (forall a. Show a => a -> Name
show forall a b. (a -> b) -> a -> b
$ forall {k} (proxy :: k -> *) (a :: k).
Typeable a =>
proxy a -> TypeRep
typeRep (forall {k} (t :: k). Proxy t
Proxy :: Proxy a))
, Name
Maybe a
defaultValue :: Maybe a
name :: Name
$sel:defaultValue:Var :: Maybe a
$sel:name:Var :: Name
..
}
forall a. FromJSON a => Name -> Either Name a
decodeYaml
decodeYaml :: Yaml.FromJSON a => String -> Either String a
decodeYaml :: forall a. FromJSON a => Name -> Either Name a
decodeYaml = forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first ParseException -> Name
Yaml.prettyPrintParseException forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. FromJSON a => ByteString -> Either ParseException a
Yaml.decodeEither' forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
encodeUtf8 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. IsString a => Name -> a
fromString
parse :: (Show a) => Var a -> (String -> Either String a) -> Scan a
parse :: forall a. Show a => Var a -> (Name -> Either Name a) -> Scan a
parse Var{Name
Maybe a
Maybe Name
metavar :: Maybe Name
defaultValue :: Maybe a
name :: Name
$sel:metavar:Var :: forall a. Var a -> Maybe Name
$sel:defaultValue:Var :: forall a. Var a -> Maybe a
$sel:name:Var :: forall a. Var a -> Name
..} Name -> Either Name a
f = forall a b. ScanF a -> Scan (a -> b) -> Scan b
Scan ScanF
{ Name
name :: Name
name :: Name
name
, parser :: Maybe Name -> Either Error (Name, a)
parser = \case
Maybe Name
Nothing -> case Maybe a
defaultValue of
Maybe a
Nothing -> forall a b. a -> Either a b
Left (Name -> Error
Missing Name
name)
Just a
d -> forall a b. b -> Either a b
Right (forall a. Show a => a -> Name
show a
d forall a. Semigroup a => a -> a -> a
<> Name
" (default)", a
d)
Just Name
x -> forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap (Name -> Name -> Name -> Error
ParseError Name
name Name
x) forall a. Show a => a -> (Name, a)
withShow forall a b. (a -> b) -> a -> b
$ Name -> Either Name a
f Name
x
, Maybe Name
metavar :: Maybe Name
metavar :: Maybe Name
metavar
}
(forall a. a -> Scan a
Pure forall a. a -> a
id)
secret :: Scan a -> Scan a
secret :: forall a. Scan a -> Scan a
secret (Pure a
a) = forall a. a -> Scan a
Pure a
a
secret (Scan ScanF a
v Scan (a -> a)
k) = forall a b. ScanF a -> Scan (a -> b) -> Scan b
Scan (ScanF a
v { parser :: Maybe Name -> Either Error (Name, a)
parser = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first (forall a b. a -> b -> a
const Name
"<REDACTED>")) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. ScanF a -> Maybe Name -> Either Error (Name, a)
parser ScanF a
v }) (forall a. Scan a -> Scan a
secret Scan (a -> a)
k)
secret (Group Name
name Scan a
s) = forall a. Name -> Scan a -> Scan a
Group Name
name forall a b. (a -> b) -> a -> b
$ forall a. Scan a -> Scan a
secret Scan a
s
group :: String -> Scan a -> Scan a
group :: forall a. Name -> Scan a -> Scan a
group = forall a. Name -> Scan a -> Scan a
Group
withShow :: Show a => a -> (String, a)
withShow :: forall a. Show a => a -> (Name, a)
withShow a
x = (forall a. Show a => a -> Name
show a
x, a
x)
type EnvMap = Map.Map String String
type GroupStack = [String]
renderError :: Error -> String
renderError :: Error -> Name
renderError (Missing Name
name) = [Name] -> Name
unwords [Name
"Missing environment variable", Name
name]
renderError (ParseError Name
name Name
value Name
reason) = [Name] -> Name
unwords [Name
"Failed to parse", Name
name forall a. Semigroup a => a -> a -> a
<> Name
"=" forall a. Semigroup a => a -> a -> a
<> Name
value forall a. Semigroup a => a -> a -> a
<> Name
":", Name
reason]
renderError (CustomError Name
reason) = Name
reason
data Settings = Settings
{ Settings -> [Name] -> Name -> Name -> IO ()
parseLogger :: GroupStack -> Name -> String -> IO ()
, Settings -> [Name] -> Error -> IO ()
errorLogger :: GroupStack -> Error -> IO ()
, Settings -> Name -> Maybe (IO ())
unusedLogger :: Name -> Maybe (IO ())
, Settings -> Bool
pedantic :: Bool
, Settings -> Maybe Name
helpFlag :: Maybe Name
}
header :: GroupStack -> String -> String
[] Name
level = Name
"[EVP " forall a. Semigroup a => a -> a -> a
<> Name
level forall a. Semigroup a => a -> a -> a
<> Name
"] "
header [Name]
xs Name
level = forall a. Monoid a => [a] -> a
mconcat [Name
"[EVP ", Name
level, forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (Name
"/"<>) forall a b. (a -> b) -> a -> b
$ forall a. [a] -> [a]
reverse [Name]
xs, Name
"] "]
instance Default Settings where
def :: Settings
def = Settings
{ $sel:parseLogger:Settings :: [Name] -> Name -> Name -> IO ()
parseLogger = \[Name]
stack Name
name Name
value -> do
Bool
isTerminal <- Handle -> IO Bool
hIsTerminalDevice Handle
stdout
Handle -> Name -> IO ()
hPutStrLn (if Bool
isTerminal then Handle
stdout else Handle
stderr)
forall a b. (a -> b) -> a -> b
$ [Name] -> ShowS
header [Name]
stack Name
"Info" forall a. Semigroup a => a -> a -> a
<> Name
name forall a. Semigroup a => a -> a -> a
<> Name
": " forall a. Semigroup a => a -> a -> a
<> Name
value
, $sel:errorLogger:Settings :: [Name] -> Error -> IO ()
errorLogger = \[Name]
stack Error
e -> Handle -> Name -> IO ()
hPutStrLn Handle
stderr forall a b. (a -> b) -> a -> b
$ forall a. [a] -> [[a]] -> [a]
intercalate Name
"\n" forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map ([Name] -> ShowS
header [Name]
stack Name
"Error" <>) forall a b. (a -> b) -> a -> b
$ Name -> [Name]
lines forall a b. (a -> b) -> a -> b
$ Error -> Name
renderError Error
e
, $sel:unusedLogger:Settings :: Name -> Maybe (IO ())
unusedLogger = forall a. Monoid a => a
mempty
, $sel:pedantic:Settings :: Bool
pedantic = Bool
False
, $sel:helpFlag:Settings :: Maybe Name
helpFlag = forall a. a -> Maybe a
Just Name
"EVP_HELP"
}
assumePrefix :: String -> Name -> Maybe (IO ())
assumePrefix :: Name -> Name -> Maybe (IO ())
assumePrefix Name
prefix Name
name
| forall a. Eq a => [a] -> [a] -> Bool
isPrefixOf Name
prefix Name
name = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Handle -> Name -> IO ()
hPutStrLn Handle
stderr forall a b. (a -> b) -> a -> b
$ [Name] -> Name
unwords [Name
"[EVP Warn]", Name
name, Name
"is set but not used"]
| Bool
otherwise = forall a. Maybe a
Nothing
obsolete :: [Name] -> Name -> Maybe (IO ())
obsolete :: [Name] -> Name -> Maybe (IO ())
obsolete [Name]
nameSet Name
name
| forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
elem Name
name [Name]
nameSet = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Handle -> Name -> IO ()
hPutStrLn Handle
stderr forall a b. (a -> b) -> a -> b
$ [Name] -> Name
unwords [Name
"[EVP Warn]", Name
name, Name
"is obsolete"]
| Bool
otherwise = forall a. Maybe a
Nothing
enumerate :: Scan a -> [Name]
enumerate :: forall a. Scan a -> [Name]
enumerate Scan a
m = forall a. Set a -> [a]
Set.toList forall a b. (a -> b) -> a -> b
$ forall a. Set Name -> Scan a -> Set Name
go forall a. Set a
Set.empty Scan a
m where
go :: Set.Set Name -> Scan a -> Set.Set Name
go :: forall a. Set Name -> Scan a -> Set Name
go !Set Name
s (Pure a
_) = Set Name
s
go !Set Name
s (Scan ScanF a
k Scan (a -> a)
cont) = forall a. Set Name -> Scan a -> Set Name
go (forall a. Ord a => a -> Set a -> Set a
Set.insert (forall a. ScanF a -> Name
name ScanF a
k) Set Name
s) Scan (a -> a)
cont
go !Set Name
s (Group Name
_ Scan a
cont) = forall a. Set Name -> Scan a -> Set Name
go Set Name
s Scan a
cont
scan :: Scan a -> IO a
scan :: forall a. Scan a -> IO a
scan = forall a. Settings -> Scan a -> IO a
scanWith forall a. Default a => a
def
scanWith :: Settings -> Scan a -> IO a
scanWith :: forall a. Settings -> Scan a -> IO a
scanWith Settings{Bool
Maybe Name
Name -> Maybe (IO ())
[Name] -> Name -> Name -> IO ()
[Name] -> Error -> IO ()
helpFlag :: Maybe Name
pedantic :: Bool
unusedLogger :: Name -> Maybe (IO ())
errorLogger :: [Name] -> Error -> IO ()
parseLogger :: [Name] -> Name -> Name -> IO ()
$sel:helpFlag:Settings :: Settings -> Maybe Name
$sel:pedantic:Settings :: Settings -> Bool
$sel:unusedLogger:Settings :: Settings -> Name -> Maybe (IO ())
$sel:errorLogger:Settings :: Settings -> [Name] -> Error -> IO ()
$sel:parseLogger:Settings :: Settings -> [Name] -> Name -> Name -> IO ()
..} Scan a
action = do
Map Name Name
envs0 <- forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO [(Name, Name)]
getEnvironment
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe Name
helpFlag forall a b. (a -> b) -> a -> b
$ \Name
flag -> do
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Name
flag forall k a. Ord k => k -> Map k a -> Bool
`Map.member` Map Name Name
envs0) forall a b. (a -> b) -> a -> b
$ do
Name -> IO ()
putStrLn forall a b. (a -> b) -> a -> b
$ forall a. Scan a -> Name
help Scan a
action
forall a. IO a
exitSuccess
(Map Name Name
remainder, [([Name], Error)]
errors, Maybe a
result) <- forall a.
Map Name Name
-> Map Name Name
-> [Name]
-> Scan a
-> IO (Map Name Name, [([Name], Error)], Maybe a)
go Map Name Name
envs0 Map Name Name
envs0 [] Scan a
action
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry [Name] -> Error -> IO ()
errorLogger) [([Name], Error)]
errors
case forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Name -> Maybe (IO ())
unusedLogger forall a b. (a -> b) -> a -> b
$ forall k a. Map k a -> [k]
Map.keys Map Name Name
remainder of
Maybe (IO ())
Nothing -> forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
Just IO ()
m -> do
IO ()
m
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
pedantic forall a. IO a
exitFailure
case Maybe a
result of
Maybe a
Nothing -> forall a. IO a
exitFailure
Just a
a -> forall (f :: * -> *) a. Applicative f => a -> f a
pure a
a
where
go :: EnvMap -> EnvMap -> GroupStack -> Scan a -> IO (EnvMap, [(GroupStack, Error)], Maybe a)
go :: forall a.
Map Name Name
-> Map Name Name
-> [Name]
-> Scan a
-> IO (Map Name Name, [([Name], Error)], Maybe a)
go Map Name Name
_ Map Name Name
envs [Name]
_ (Pure a
a) = forall (f :: * -> *) a. Applicative f => a -> f a
pure (Map Name Name
envs, [], forall a. a -> Maybe a
Just a
a)
go Map Name Name
allEnvs Map Name Name
envs [Name]
groupStack (Group Name
name Scan a
inner) = do
let stack :: [Name]
stack = Name
name forall a. a -> [a] -> [a]
: [Name]
groupStack
forall a.
Map Name Name
-> Map Name Name
-> [Name]
-> Scan a
-> IO (Map Name Name, [([Name], Error)], Maybe a)
go Map Name Name
allEnvs Map Name Name
envs [Name]
stack Scan a
inner
go Map Name Name
allEnvs Map Name Name
envs [Name]
groupStack (Scan ScanF{Name
Maybe Name
Maybe Name -> Either Error (Name, a)
metavar :: Maybe Name
parser :: Maybe Name -> Either Error (Name, a)
name :: Name
metavar :: forall a. ScanF a -> Maybe Name
parser :: forall a. ScanF a -> Maybe Name -> Either Error (Name, a)
name :: forall a. ScanF a -> Name
..} Scan (a -> a)
cont) = case Maybe Name -> Either Error (Name, a)
parser (forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Name
name Map Name Name
allEnvs) of
Left Error
e -> do
(Map Name Name
remainder, [([Name], Error)]
errors, Maybe (a -> a)
_) <- forall a.
Map Name Name
-> Map Name Name
-> [Name]
-> Scan a
-> IO (Map Name Name, [([Name], Error)], Maybe a)
go Map Name Name
allEnvs (forall k a. Ord k => k -> Map k a -> Map k a
Map.delete Name
name Map Name Name
envs) [Name]
groupStack Scan (a -> a)
cont
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Map Name Name
remainder, ([Name]
groupStack, Error
e) forall a. a -> [a] -> [a]
: [([Name], Error)]
errors, forall a. Maybe a
Nothing)
Right (Name
display, a
v) -> do
[Name] -> Name -> Name -> IO ()
parseLogger [Name]
groupStack Name
name Name
display
(Map Name Name
remainder, [([Name], Error)]
errors, Maybe (a -> a)
func) <- forall a.
Map Name Name
-> Map Name Name
-> [Name]
-> Scan a
-> IO (Map Name Name, [([Name], Error)], Maybe a)
go Map Name Name
allEnvs (forall k a. Ord k => k -> Map k a -> Map k a
Map.delete Name
name Map Name Name
envs) [Name]
groupStack Scan (a -> a)
cont
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Map Name Name
remainder, [([Name], Error)]
errors, (forall a b. (a -> b) -> a -> b
$ a
v) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe (a -> a)
func)
modifyError :: (Error -> Error) -> Scan a -> Scan a
modifyError :: forall a. (Error -> Error) -> Scan a -> Scan a
modifyError Error -> Error
func = forall a. Scan a -> Scan a
go where
go :: Scan a -> Scan a
go :: forall a. Scan a -> Scan a
go (Pure a
a) = forall a. a -> Scan a
Pure a
a
go (Scan ScanF a
v Scan (a -> a)
k) = forall a b. ScanF a -> Scan (a -> b) -> Scan b
Scan (forall {a}. ScanF a -> ScanF a
apply ScanF a
v) (forall a. Scan a -> Scan a
go Scan (a -> a)
k)
go (Group Name
name Scan a
k) = forall a. Name -> Scan a -> Scan a
Group Name
name (forall a. Scan a -> Scan a
go Scan a
k)
apply :: ScanF a -> ScanF a
apply ScanF{Name
Maybe Name
Maybe Name -> Either Error (Name, a)
metavar :: Maybe Name
parser :: Maybe Name -> Either Error (Name, a)
name :: Name
metavar :: forall a. ScanF a -> Maybe Name
parser :: forall a. ScanF a -> Maybe Name -> Either Error (Name, a)
name :: forall a. ScanF a -> Name
..} = ScanF
{ Name
name :: Name
name :: Name
name
, parser :: Maybe Name -> Either Error (Name, a)
parser = forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first Error -> Error
func forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe Name -> Either Error (Name, a)
parser
, Maybe Name
metavar :: Maybe Name
metavar :: Maybe Name
metavar
}
help :: Scan a -> String
help :: forall a. Scan a -> Name
help = [Name] -> Name
unlines forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Int -> Scan a -> [Name]
go Int
1 where
go :: Int -> Scan a -> [String]
go :: forall a. Int -> Scan a -> [Name]
go Int
_ (Pure a
_) = []
go Int
depth (Scan ScanF a
v Scan (a -> a)
k) = forall a. ScanF a -> Name
format ScanF a
v forall a. a -> [a] -> [a]
: forall a. Int -> Scan a -> [Name]
go Int
depth Scan (a -> a)
k
go Int
depth (Group Name
name Scan a
k) = (forall a. Int -> a -> [a]
replicate Int
depth Char
'#' forall a. Semigroup a => a -> a -> a
<> Name
" " forall a. Semigroup a => a -> a -> a
<> Name
name) forall a. a -> [a] -> [a]
: forall a. Int -> Scan a -> [Name]
go (Int
depth forall a. Num a => a -> a -> a
+ Int
1) Scan a
k
format :: ScanF a -> Name
format ScanF{Name
Maybe Name
Maybe Name -> Either Error (Name, a)
metavar :: Maybe Name
parser :: Maybe Name -> Either Error (Name, a)
name :: Name
metavar :: forall a. ScanF a -> Maybe Name
parser :: forall a. ScanF a -> Maybe Name -> Either Error (Name, a)
name :: forall a. ScanF a -> Name
..} = Name
name forall a. Semigroup a => a -> a -> a
<> Name
"=" forall a. Semigroup a => a -> a -> a
<> forall b a. b -> (a -> b) -> Maybe a -> b
maybe Name
"" forall a. a -> a
id Maybe Name
metavar