I've parsed the command line on a console app a couple of different ways but I'm curious if there is a pattern or "best" way to do it. Physically parsing is easy. I've got a C# implementation of the GetOpt library. It's applying the arguments to the business logic -- setting up the application to run. That is the part I wonder about.
Here is what I generally do:
Here's an example in code to perhaps make things a little more clear. You can ignore this if you want, I'm just including it as an example to supplement some of my statements above.
What do you do? Is there a good pattern to use or any general concepts that work particularly well? As I've said, what I do works, it just feels kind of clunky. I'm just curious what other developers are doing with regards to command line interfaces.
Here is what I generally do:
Code:
Public Class CommandLineApp
//define these up top so it's easier to change them later
Private Class DefinedParameters
Public Const firstArgLong As String = "arg1"
//...
End Class
Public Sub New()
End Sub
Public CommandLinePattern()
//1. Get the command line parameters -- either passed in or Environment.GetCommandLineArgs()
//2. Check initial error Conditions for early trouble
//3. Set up GetOpt
Try
//4. Parse command line using GetOpt
//5. Check for early termination scenarios -- user asks for help or version number, improper use of arguments, etc.
//6. Set up boolean flags or variables for all the parameters that are left that could be good (such as hide banner or output file or configuration type)
//7. Run the business/meaty part of the app with the flags/variables
Catch e As ArgumentException
Console.WriteLine(e.Message)
ShowHelp()
End Try
End Function
Here's an example in code to perhaps make things a little more clear. You can ignore this if you want, I'm just including it as an example to supplement some of my statements above.
Visual Basic:
Public Class CommandLineApp
''define these up top so it's easier to change them later
Private Class DefinedParameters
Public Const loud As String = "loud"
Public Const loud2 As String = "l"
Public Const hidebanner As String = "hidebanner"
Public Const hidebanner2 As String = "b"
Public Const version As String = "version"
Public Const version2 As String = "v"
Public Const help As String = "help"
Public Const help2 As String = "h"
Public Const help3 As String = "?"
End Class
'
Public Sub New()
'
End Sub
'
'Usage: Appy filename [-l|--loud] [-b|--hidebanner] | [-v|--version] | [--help|-h|-?]
''This is called from the static Main() function but could easily BE the Main()
Public Function Run(ByVal commandLineArgs As String()) As Boolean
If commandLineArgs.Length = 1 Then ''you have to either a filename, -v, or -h or the user needs more help
ShowHelp()
Return True
End If
''Setting up GetOpt
Dim commandLineParser As New Heyes.GetOpt(commandLineArgs)
Dim expectedArgs() As String = {DefinedParameters.loud, DefinedParameters.loud2, _
DefinedParameters.hidebanner, DefinedParameters.hidebanner2, _
DefinedParameters.version, DefinedParameters.version2, _
DefinedParameters.help, DefinedParameters.help2, DefinedParameters.help3}
Try
commandLineParser.SetOpts(expectedArgs)
commandLineParser.Parse()
''If there is a request for the version, always honor it
If commandLineParser.IsDefined(DefinedParameters.version) OrElse commandLineParser.IsDefined(DefinedParameters.version2) Then
ShowBanner()
Return True
End If
''if more than one file is attempted, send the user some help
If commandLineParser.Args.Count > 2 Then ''1 or 0 files is alright. Remember, the exe is the first arg
Console.WriteLine("Only one file may be specified at a time.")
ShowHelp()
Return True 'ditch out, becuase you failed
End If
''no matter what, if the user wants help, give it to them, unless they want the version which I took care of above and ditched out
If commandLineParser.IsDefined(DefinedParameters.help) OrElse _
commandLineParser.IsDefined(DefinedParameters.help2) OrElse _
commandLineParser.IsDefined(DefinedParameters.help3) Then
ShowHelp()
Return True ''ditch out, we gave them their help.
End If
If commandLineParser.IsDefined(DefinedParameters.loud) AndAlso commandLineParser.IsDefined(DefinedParameters.loud2) Then
Console.WriteLine("Options cannot be specified more than once")
Console.WriteLine("Paramater name: " + DefinedParameters.loud + ", " + DefinedParameters.loud2)
ShowHelp()
Return True
End If
If commandLineParser.IsDefined(DefinedParameters.hidebanner) AndAlso commandLineParser.IsDefined(DefinedParameters.hidebanner2) Then
Console.WriteLine("Options cannot be specified more than once")
Console.WriteLine("Paramater name: " + DefinedParameters.hidebanner + ", " + DefinedParameters.hidebanner2)
ShowHelp()
Return True
End If
''define the arguments we have that aren't a help or version
Dim hideBanner As Boolean = False
If commandLineParser.IsDefined(DefinedParameters.loud) OrElse commandLineParser.IsDefined(DefinedParameters.loud2) Then
Me._loud = True
End If
If commandLineParser.IsDefined(DefinedParameters.hidebanner) OrElse commandLineParser.IsDefined(DefinedParameters.hidebanner2) Then
hideBanner = True
End If
''Now down to business
Execute(commandLineParser.Args(1), hideBanner)
Return True
Catch e As ArgumentException
Console.WriteLine(e.Message)
ShowHelp()
Return True
End Try
End Function
What do you do? Is there a good pattern to use or any general concepts that work particularly well? As I've said, what I do works, it just feels kind of clunky. I'm just curious what other developers are doing with regards to command line interfaces.