content: {-# LANGUAGE NamedFieldPuns #-}
  
  module Examples.ParserGroup.AllGrouped (opts, main) where
  
  import Data.Semigroup ((<>))
  import Options.Applicative
  
  -- Tests the help page when every option belongs to some group i.e. there are
  -- no top-level options. Notice we put the helper (<**> helper) __inside__
  -- one of the groups, so that it is not a top-level option.
  --
  -- Also notice that although we add cmdParser to the same group, it is __not__
  -- rendered as part of this group. This is what we want, as it is an Argument
  -- and should not be rendered with the Options.
  
  data LogGroup = LogGroup
    { logPath :: Maybe String,
      logVerbosity :: Maybe Int
    }
    deriving (Show)
  
  data SystemGroup = SystemGroup
    { poll :: Bool,
      timeout :: Int
    }
    deriving (Show)
  
  data Sample = Sample
    { logGroup :: LogGroup,
      systemGroup :: SystemGroup,
      cmd :: String
    }
    deriving (Show)
  
  sample :: Parser Sample
  sample =
    Sample
      <$> parseLogGroup
      <*> parseSystemGroup
      <*> parseCmd
  
    where
      parseLogGroup =
        parserOptionGroup "Logging" $
          LogGroup
            <$> optional
              ( strOption
                  ( long "file-log-path"
                      <> metavar "PATH"
                      <> help "Log file path"
                  )
              )
            <*> optional
              ( option
                  auto
                  ( long "file-log-verbosity"
                      <> metavar "INT"
                      <> help "File log verbosity"
                  )
              )
              <**> helper
  
      parseSystemGroup =
        parserOptionGroup "System Options" $
          SystemGroup
            <$> switch
              ( long "poll"
                  <> help "Whether to poll"
              )
            <*> option
                  auto
                  ( long "timeout"
                      <> metavar "INT"
                      <> help "Whether to time out"
                  )
  
      parseCmd = argument str (metavar "Command")
  
  opts :: ParserInfo Sample
  opts =
    info
      sample
      (  progDesc "Every option is grouped"
          <> header "parser_group.all_grouped - a test for optparse-applicative"
      )
  
  main :: IO ()
  main = do
    r <- customExecParser (prefs helpShowGlobals) opts
    print r
  