2013-06-30 6 views
7

Ich bin auf der Suche nach einer Bibliothek, die eine Monade verwendet, um über die Aufregung der Kommandozeilenargumente zu analysieren, die Analyse und Hilfe zu generieren. Ich habe folgendes ziemlich offensichtlich Nutzungsmuster im Sinn:Befehlszeilenargumente lesen Monad-Bibliothek

main = do 
    portOrSocket <- Args.run $ do 
    mbSocket <- Args.read $ Args.Arg "s" "socket" "Description" 
    mbPort <- Args.read $ Args.Arg "p" "port" "Description" 
    case mbSocket of 
     Just socket -> return $ Right socket 
     Nothing -> case mbPort of 
     Just port -> return $ Left port 
     Nothing -> return $ Left defaultPort 
    ... 

Der obige Code hat alle erforderlichen Informationen, um Parsing, Validierung und Nutzung Generation zu verarbeiten und IMO ist ziemlich einfach zu verstehen. Leider habe ich nach dem Durchschauen von Paketen wie cmdargs, cmdlib, parseargs und ReadArgs nichts gefunden. Aber bevor ich in die Implementierung gehe, möchte ich sicherstellen, dass ich nichts verpasst habe. Gibt es also eine Bibliothek, die einen ähnlichen Ansatz für das Problem ausnutzt?

+8

Haben Sie versucht, 'optparse-applicative'? –

+4

+1 für 'optarse-applicative'. Es ist großartig. – jtobin

+1

Es scheint fast unmöglich zu sein, automatische Hilfemeldungen zu erzeugen, wenn Parameter von Werten anderer Parameter abhängen. Dies ist wahrscheinlich der Grund, warum _optsparse-applicative_ Applicative verwendet. –

Antwort

8

Sie können optparse-applicative verwenden. Die häufigste sieht Verwendung Muster wie folgt aus (ich bin nur durch Kopieren und Einfügen aus einem kleinen Dienstprogramm, das ich verwenden):

options :: Parser (String, String) 
options = (,) 
    <$> (strOption $ mconcat [ 
     short 'n', 
     long "node", 
     metavar "NODE", 
     value "127.0.0.1", 
     showDefaultWith id, 
     completer (bashCompleter "hostname"), 
     help "AMQP node to connect to" ]) 
    <*> (strOption $ mconcat [ 
     short 'q', 
     long "queue", 
     metavar "QUEUE", 
     value "1.0.0", 
     showDefaultWith id, 
     help "Queue to initialize" ]) 

main = do 
    (hostName, queue) <- 
     execParser $ info (helper <*> options) $ mconcat [ 
      fullDesc, 
      header "The Suns setup utility", 
      progDesc "Sets up an AMQP node", 
      footer "Report bugs to [email protected]" ] 
    ... 

Als ich das kompilierte Programm mit -h laufen, erhalte ich:

$ suns-admin -h 
The Suns setup utility 

Usage: suns-admin [-n|--node NODE] [-q|--queue QUEUE] 
    Sets up an AMQP node 

Available options: 
    -h,--help    Show this help text 
    -n,--node NODE   AMQP node to connect to (default: 127.0.0.1) 
    -q,--queue QUEUE   Queue to initialize (default: 1.0.0) 

Report bugs to [email protected] 

Das gibt Ihnen eine Vorstellung von einigen netten Optionen, mit denen Sie spielen können, und der netten Ausgabe, die das Programm erzeugt.

2

Wenn jemand bei der Lösung des Problems in der Frage vorgelegt interessiert optparse-applicative verwenden, hier ist, wie ich erreicht, dass:

import Options.Applicative 

getOptions :: Int -> IO (Either Int String) 
getOptions defaultPort = 
    execParser $ 
    info (helper <*> parser defaultPort) $ 
    fullDesc <> 
    progDesc "Run a content-db server on a socket or a port" <> 
    header "Run a content-db server" 

parser :: Int -> Parser (Either Int String) 
parser defaultPort = 
    portOrSocket <$> 
    (optional . strOption) 
     (short 's' <> 
     long "socket" <> 
     help "Socket") 
    <*> 
    option 
     (short 'p' <> 
     long "port" <> 
     help "Port" <> 
     value defaultPort) 
    where 
    portOrSocket (Just socket) _ = Right socket 
    portOrSocket _ port = Left port 

main = do 
    getOptions 43400 >>= \o -> case o of 
    Left port -> print port 
    Right socket -> print socket