2016-06-30 2 views
1

J'ai le code suivant;Haskell - génère un message d'erreur d'argument manquant à partir du type de données

module Billing.Options 
    (
     GlobalOpts(..) 
    , globalOptsParser 
    , parseDb 
    , parseSql 
) where 

import Options.Applicative 
import Options.Applicative.Simple 
import Options.Applicative.Types 
import System.FilePath.Posix 
import Text.Regex.PCRE 

-- ------------------------------------------------------------ 

data GlobalOpts = GlobalOpts 
    { 
    optDb   :: String, 
    optSql   :: String 
    } deriving Show 

-- ------------------------------------------------------------ 

globalOptsParser :: Parser GlobalOpts 
globalOptsParser = GlobalOpts 
    <$> option (parseDb =<< readerAsk) 
    ( long "db" 
    <> short 'd' 
    <> metavar "<DB name>" 
    <> help "dmt | report" 
    ) 
    <*> option parseSql 
    ( long "sql" 
    <> metavar "<SQL SELECT statement>" 
    <> help "sql select statement to use in order to generate JSON config file" 
    ) 
-- ------------------------------------------------------------ 

matches :: String -> String -> Bool 
matches = (=~) 

-- ------------------------------------------------------------ 

parseDb :: String -> ReadM String 
parseDb val = do 
    if not (elem val ["dmt", "report"]) 
     then readerError $ "Unknown DB, '" ++ val ++ "'" 
     else return val 

-- ------------------------------------------------------------ 

parseSql :: ReadM String 
parseSql = do 
    val <- readerAsk 
    if not (val `matches` "(?i)select .+ from .+") 
     then readerError $ "Please provide a valid SQL SELECT statement" 
     else return val 

-- [EOF] 

Je suis en train de tester mon analyseur d'arguments avec le code suivant;

error' = let mp = runParser AllowOpts globalOptsParser ["-d", "billing"] 
      opts = ParserPrefs "suffix" False False False 80 
     in fst $ runP mp opts 

Les arguments sont nécessaires,

-d <DB name> 
    --sql <SQL SELECT statement> 

Je veux vérifier que je reçois le message d'erreur,

Missing: --sql <SQL SELECT statement> 

quand je ne précise "facturation -d".

Le code de test ci-dessus donne la sortie suivante si j'imprimer le résultat,

Left (MissingError (MultNode [MultNode [MultNode [AltNode [Leaf (Chunk {unChunk = Just --sql <SQL SELECT statement>})]]]])) 

est-il un moyen de générer le message d'erreur attendu (String) du résultat ci-dessus (soit le type de données)? Est-ce que Haskell fournit une fonction évidente à utiliser à cette fin car je ne trouve rien dans la documentation et googler pour des exemples n'a pas non plus produit de réponses.

+3

Il existe des bibliothèques d'options de ligne de commande gazillion pour Haskell, vous devez donc nous indiquer quelle bibliothèque vous utilisez et inclure vos importations. – ErikR

+0

Excuses, j'ai mis à jour ma question. –

+0

@TresiaBurger Alors .... utilisez-vous 'http: // hackage.haskell.org/paquet/optparse-applicative' alors? –

Répondre

2

Si vous regardez le référentiel de code source pour optparse-applicative(link), vous verrez qu'il a lui-même une suite de tests dans le sous-répertoire tests.

Une routine qui ressemble comme il le fait un peu comme ce que vous voulez est checkHelpTextWith dans le fichier tests/Test.hs:

checkHelpTextWith :: Show a => ExitCode -> ParserPrefs -> String 
        -> ParserInfo a -> [String] -> Assertion 
checkHelpTextWith ecode pprefs name p args = do 
    let result = execParserPure pprefs p args 
    assertError result $ \failure -> do 
    expected <- readFile $ name ++ ".err.txt" 
    let (msg, code) = renderFailure failure name 
    expected @=? msg ++ "\n" 
    ecode @=? code 

Cette fonction prend un analyseur d'option à l'échec et compare le message d'erreur avec le contenu d'un fichier .

Les principales fonctions d'intérêt sont les suivants:

execParserPure :: ParserPrefs -> ParserInfo a -> [String] -> ParserResult a 

renderFailure :: ParserFailure ParserHelp -> String -> (String, ExitCode) 

La chaîne retournée par renderFailure est le message d'erreur.