помощь подкоманды с помощью приложения optparse

У меня есть две проблемы с optparse-applicative: (я объединил проблемы, поскольку, вероятно, существует одно основное неправильное представление).

  1. #P2# <блочная цитата> #P3# #P4#

Я бы хотел, чтобы на самом деле отображалось имя программы (не интерактивное), а также список КОМАНД, но я не понимаю, как добавить метаданные для конкретной подкоманды.

  1. Когда я пытаюсь получить справку по определенной подкоманде, я получаю сообщение об отсутствии обязательных аргументов. (

stack exec commandline-exe -- DeployStack --help

> Invalid option `--help'
> 
> Usage: <interactive> DeployStack (-d|--deployment DEPLOYMENT)
>                                  (-t|--template TEMPLATE) 
>                                  [-p|--provider PROVIDER]   Deploy a Stack

Вот как я строю помощь:

-- For information about how this was done see: https://stackoverflow.com/questions/36339103/using-optparse-applicative-with-multiple-subcommands-and-global-options
-- and https://hackage.haskell.org/package/optparse-applicative
module CLIParser
  ( Actions(..)
  , actions
  ) where

import           Data.Semigroup      ((<>))
import           Options.Applicative
import           Text.Show.Functions

data Actions
  = CreateTemplate
      { name :: String
      , path :: String
      }
  | DeployStack
      { deployment :: String
      , template   :: String
      , provider   :: String
      }
  deriving (Show)

actions :: Parser Actions
actions =
  subparser
    (command
       "CreateTemplate"
       (info templateCreator (progDesc "Create Template")) <>
     commandGroup "Template commands:") <|>
  subparser
    (command "DeployStack" (info deployStack (progDesc "Deploy a Stack")) <>
     commandGroup "Deploy commands:")

templateCreator :: Parser Actions
templateCreator = CreateTemplate <$> nameArg <*> pathArg

deployStack :: Parser Actions
deployStack = DeployStack <$> deployArg <*> templateArg <*> providerArg

nameArg :: Parser String
nameArg =
  strOption
    (long "name" <> metavar "NAME" <> short 'n' <> help "Name to give template")

pathArg :: Parser String
pathArg =
  strOption
    (long "path" <> metavar "PATH" <> short 'p' <> help "Path to template file")

deployArg :: Parser String
deployArg =
  strOption
    (long "deployment" <>
     metavar "DEPLOYMENT" <> short 'd' <> help "Name of deployment")

templateArg :: Parser String
templateArg =
  strOption
    (long "template" <>
     metavar "TEMPLATE" <> short 't' <> help "Template for deployement")

providerArg :: Parser String
providerArg =
  strOption
    (long "provider" <>
     metavar "PROVIDER" <>
     short 'p' <> showDefault <> value "AWS" <> help "Cloud Provider (e.g. AWS)")

** Main.hs **

module Main where

import CLIParser
import Options.Applicative
import System.IO

options :: ParserInfo Actions
options = info (actions <**> helper)
  ( fullDesc
    <> progDesc "The CLI for CRIME"
    <> header "crime cli - process CRIME template and deploy commands" )

main :: IO ()
main = execParser options >>= display


display :: Show a => a -> IO ()
display x = print x

person Dr.YSG    schedule 13.01.2020    source источник


Ответы (1)


Решение для получения USAGE (COMMAND | COMMAND) заключается в использовании метаваров в подгруппе команд.

Чтобы получить справку по каждой команде, используйте hsubcommand, а не команду.

Решения, показанные ниже:

D:\CRIME\commandLine>stack exec crimeCLI -- --help
crime cli - process CRIME template and deploy commands

Usage: crimeCLI.EXE (Template COMMAND | Deployment COMMAND)
  (e.g. stack exec crimeCLI -- TemplateCreate -name NAME -path PATHS)

Available options:
  -h,--help                Show this help text

Template commands:
  TemplateCreate           Create Template
  TemplateDetails          Show Details about a Template
  TemplateList             List all Templates for this user

Deploy commands:
  DeployStack              Deploy a Stack to a Provider
  DeployRemove             Remove a deployed stack from a Provider

и вот код:

-- For information about how this was done see: https://stackoverflow.com/questions/36339103/using-optparse-applicative-with-multiple-subcommands-and-global-options
-- and https://hackage.haskell.org/package/optparse-applicative
module CLIParser
  ( Actions(..)
  , actions
  ) where

import           Data.Semigroup      ((<>))
import           Options.Applicative
import           Text.Show.Functions

data Actions
  = TemplateCreate
      { name :: String
      , path :: String
      }
  | TemplateDelete
      { name :: String
      , path :: String
      }
  | TemplateDetails
      { name :: String
      }
  | TemplateList
  | DeployStack
      { deployment :: String
      , template   :: String
      , provider   :: String
      }
  | DeployRemove
      { deployment :: String
      , template   :: String
      , provider   :: String
      }
  deriving (Show)

actions :: Parser Actions
actions =
  hsubparser
    (command
       "TemplateCreate"
       (info templateCreator (progDesc "Create Template")) <>
     command
       "TemplateDetails"
       (info templateDetails (progDesc "Show Details about a Template")) <>
     command
       "TemplateList"
       (info templateList (progDesc "List all Templates for this user")) <>
     commandGroup "Template commands:" <> (metavar "Template COMMAND")) <|>
  hsubparser
    (command
       "DeployStack"
       (info deployStack (progDesc "Deploy a Stack to a Provider")) <>
     command
       "DeployRemove"
       (info deployRemove (progDesc "Remove a deployed stack from a Provider")) <>
     commandGroup "Deploy commands:"  <> (metavar "Deployment COMMAND"))

templateCreator :: Parser Actions
templateCreator = TemplateCreate <$> nameArg <*> pathArg

templateDetails :: Parser Actions
templateDetails = TemplateDetails <$> nameArg

templateList :: Parser Actions
templateList = pure TemplateList

deployStack :: Parser Actions
deployStack = DeployStack <$> deployArg <*> templateArg <*> providerArg

deployRemove :: Parser Actions
deployRemove = DeployRemove <$> deployArg <*> templateArg <*> providerArg

nameArg :: Parser String
nameArg =
  strOption
    (long "name" <> metavar "NAME" <> short 'n' <> help "Name to give template")

pathArg :: Parser String
pathArg =
  strOption
    (long "path" <> metavar "PATH" <> short 'p' <> help "Path to template file")

deployArg :: Parser String
deployArg =
  strOption
    (long "deployment" <>
     metavar "DEPLOYMENT" <> short 'd' <> help "Name of deployment")

templateArg :: Parser String
templateArg =
  strOption
    (long "template" <>
     metavar "TEMPLATE" <> short 't' <> help "Template for deployement")

providerArg :: Parser String
providerArg =
  strOption
    (long "provider" <>
     metavar "PROVIDER" <>
     short 'p' <> showDefault <> value "AWS" <> help "Cloud Provider (e.g. AWS)")


person Dr.YSG    schedule 16.01.2020