# Parse command line arguments

I have been trying to parse command line arguments. There are a couple of types of options.

1. Mandatory
2. Optional
3. Alternative


There are built-in/3rd party libraries for this purpose in many other languages.

I haven't found any built-in functions for this purpose in Wolfram Lang. Is there any good way to do it in Wolfram Lang?

Update 2017-05-27

There is a example of parsing command line arguments in Haskell.

Example

universalbuild (-p|--project name.xcodeproj) (-s|--scheme schemename) (-c|--configuration configurationname)

projectOption = strOption (long "project" <> short 'p' <> metavar "name.xcodeproj" <> help "Build the project name.xcodeproj." )
schemeOption = strOption (long "scheme" <> short 's' <> metavar "schemename"  <> help "Build the scheme specified by schemename." )
configuraitonOption = strOption (long "configuration" <> short 'c' <> metavar "configurationname" <> help "Use the build configuration specified by configurationname when building each target.")

options :: Parser UBOptions
options = UBOptions <$> projectOption <*> schemeOption <*> configuraitonOption  I think the implementation in Haskell is concise and expressive. I don't expect it can be done like this in Mathematica, at least I think it illustrates how DSL can simplify tasks. • It is not clear what are you asking: parsing arguments given to wolframscript, or parsing of a particular DSL in WL. – Anton Antonov May 27 '17 at 16:16 • @AntonAntonov parsing arguments given to wolframscript. I didn't realise that arguments are DSL. I think they are DSL indeed. – UnchartedWorks May 27 '17 at 20:10 • I would like to mention that my answer fits your Haskell implementation -- the parsers are generated from EBNF for convenience. You can see this answer that uses both direct implementation with functional parsers and parsers generation from EBNF for Clojure expressions. – Anton Antonov May 27 '17 at 21:26 • @AntonAntonov Thanks, I will try to understand how it works. :) – UnchartedWorks May 27 '17 at 21:39 • I updated my answer with implementation corresponding to the Haskell code you posted. I hope that helps. – Anton Antonov May 27 '17 at 22:07 ## 2 Answers ## The DSL perspective As it is discussed in the comments, the question can be seen as parsing of a particular DSL in WL. ## Direct implementation This notebook screenshot image shows a direct implementation corresponding to the Haskell example in the question with the package "FunctionalParsers.m": Details on how to use the package "FunctionalParsers.m" can be found here: "Functional parsers for an integration requests language grammar.pdf". Some notes on the operators used: • Shortcut operators: • "⊕" for ParseAlternativeComposition, • "⊗" for ParseSequentialComposition, • "⊙" for ParseApply. • ParseOption is for optional parsing. • I put function wrappers around the parsed results with ParseApply. Here is the code: pOptionValue = ParsePredicate[ StringMatchQ[#, Except[{"-", "(", ")", "[", "]", WhitespaceCharacter}] ..] &]; pProgramName = Program\[CircleDot]pOptionValue; pProjectOption = Project\[CircleDot]((ParseSymbol["-p"]\[CirclePlus]ParseSymbol[ "--project"])\[CircleTimes]pOptionValue); pSchemeOption = Scheme\[CircleDot]((ParseSymbol["-s"]\[CirclePlus]ParseSymbol[ "--scheme"])\[CircleTimes]pOptionValue); pConfigurationOption = Configuration\[CircleDot]((ParseSymbol[ "-c"]\[CirclePlus]ParseSymbol[ "--configuration"])\[CircleTimes]pOptionValue); pHelp = Help\[CircleDot](ParseSymbol["-h"]\[CirclePlus]ParseSymbol[ "--help"]); pOptions = ParseMany[ pProjectOption\[CirclePlus]pSchemeOption\[CirclePlus]\ pConfigurationOption\[CirclePlus]pHelp]; pCommand = ParseShortest[ Flatten\[CircleDot](pProgramName\[CircleTimes]ParseOption[pOptions])];  ## Answer using parser generation from EBNF I am posting this part of the answer since the following command line DSL was easy to program with "FunctionalParsers.m" (it took me 15-20 minutes) using EBNF specification and parsers generation. First we program the command line DSL in Extended Backus-Naur Form (EBNF): Import["https://raw.githubusercontent.com/antononcube/MathematicaForPrediction/master/FunctionalParsers.m"] ebnfCommandLine = " <command-line> = <program> , [ <arg-list> ] ; <program> = '_WordString' <@ CLProgram ; <arg-list> = { <arg> } <@ CLArgumentList ; <arg> = <timeout-spec> | <source-spec> | <help> | <option-name> , <option-value> <@ CLArgument ; <option-name> = '_String' <@ CLOptionName ; <option-value> = '_String' <@ CLOptionValue ; <help> = '--help' | '-h' <@ CLHelp ; <timeout-spec> = ( '--timeout' | '-t' ) &> '_?NumberQ' <@ CLTimeoutSpec ; <source-spec> = ( '--source' | '-src' ) &> '_String' <@ CLSourceSpec ; ";  Note that in the EBNF string above I have used function wrappers for the parsing rules. Some of them can be skipped (e.g. CLArgumentList). The following generates the parsers from the EBNF string: GenerateParsersFromEBNF[ToTokens[ebnfCommandLine]]; LeafCount[res] (* 258 *)  Here we overwrite the parser for <option-name> in order to make it more specific. (Hard to do in the EBNF string.) pOPTIONNAME = ParseApply[CLOptionName, ParsePredicate[ StringMatchQ[#, ("-" | "--") ~~ (WordCharacter ..)] &]];  Here is a table of example command parsings: commands = {"example", "example --help", "example1 --timeout 123", "example2 -t 34 -src ./MyFile.php", "exampleUknownOption --timeout 34 --source ./MyFile.php -out ./MyFile.PHP", "exampleFail1 --timeout 34 --source ./MyFile.php -;out ./MyFile.PHP", "exampleFail2 5 6 out xxx", "exampleMisSpell --timeout 34 --sourse ./MyFile.php" }; ParsingTestTable[ParseShortest[pCOMMANDLINE], commands, "Layout" -> "Vertical"]  For more details on programming DSLs see the blog post: "Creating and programming domain specific languages". Command line arguments are stored in $CommandLine. Mine looks like this:

$CommandLine (* {"/Applications/Mathematica 11.app/Contents/MacOS/WolframKernel", "-wstp", "-mathlink", "-linkprotocol", "SharedMemory", "-linkconnect", "-linkname", "cddhm_shm"} *)  You can parse these relatively easily with the usual functions such as MemberQ, Position, Replace, etc. For example, Replace[$CommandLine, {___, "-linkname", linkname_, ___} :> linkname]
(* "cddhm_shm" *)


Several of the standard arguments, such as -noinit or -nopaclet are in fact handled in Wolfram Language code. You can find references to these if you browse the \$InstallationDirectory.

Many tools these days use - for single letter flags and -- for multi-letter ones. I do not think it is a good idea to use this convention with Mathematica because its multi-letter built-in options all use a single -. It would not be possible to distinguish them from single-letter flags.