Ry-
Ry-

Reputation: 224904

A reliable pattern for command-line arguments

I see so many programs take command-line arguments with flags, for example gcc hello.c -o hello. Of course, I can implement that in my application:

Dim args() As String = Environment.GetCommandLineArgs()
Dim oi As Integer = Array.IndexOf("-o", args)
If oi > -1 AndAlso oi < args.Length Then
    CompileTo(args(oi + 1)) 'Or whatever
Else
    CompileTo("out.exe") 'Or whatever
End If

But it's ugly and annoying to use, prone to errors, and inefficient. What's the better way that I keep overlooking?

Upvotes: 1

Views: 367

Answers (3)

Horst Walter
Horst Walter

Reputation: 14081

May you check out Best way to parse command line arguments in C#? , there are some interesting answers about a similar topic (C#, but this should not matter). It also shows links to "ready-to-use" libs you might want to use.

Upvotes: 3

Martin
Martin

Reputation: 1448

Create a form with a - textbox named OptString and text: -in "c:\my docs\my files" +n -sort:a -xyz - textbox named wop (short for Wrong Options) - button named ParseBt - RichTextBox named rtb (short for RichTextBox)

add this code and run it:

Public Class Form1
Dim ListOfPossibleOptions As New Collection  

Dim RejectedOptions As String   

Private Sub ParseBt_Click(sender As System.Object, e As System.EventArgs) Handles ParseBt.Click
    ListOfPossibleOptions.Clear()
    ListOfPossibleOptions.Add(New OneOption("Input", " "c, True))
    ListOfPossibleOptions.Add(New OneOption("Sort", ":"c))
    ListOfPossibleOptions.Add(New OneOption("New"))

    ParseOptions(ListOfPossibleOptions, RejectedOptions)

    Dim s As String = ""
    For Each CurrOption As OneOption In ListOfPossibleOptions
        s &= CurrOption.OptionText & ": "
        If CurrOption.Present Then
            s &= "Present option=" & CurrOption.OptionChar
            If CurrOption.ValueReq Then
                s &= " value=" & CurrOption.TextValue
            End If
        Else
            s &= "not present"
        End If
        s &= vbCrLf
    Next
    rtb.Text = s
End Sub
Sub ParseOptions(ListOfPossibleOptions As Collection, RejectedOptions As String)
    Dim Fnd As Boolean
    Dim OptionString As String = OptString.Text.Trim.ToUpper & " "
    Dim OptionFnd As OneOption
    RejectedOptions = ""
    While OptionString.Length() > 0
        Fnd = False
        Do While True
            For Each CurrOption As OneOption In ListOfPossibleOptions
                Dim ot As String = CurrOption.OptionText.ToUpper
                For l As Integer = 1 To CurrOption.OptionText.Length
                    If l < OptionString.Length Then
                        Debug.WriteLine("|" & ot.Substring(0, l) & "|" & OptionString.Substring(1, l) & "|")
                        If ot.Substring(0, l) = OptionString.Substring(1, l) Then
                            If OptionString.Substring(1 + l, 1) = CurrOption.Separator Then
                                Fnd = True
                                OptionFnd = CurrOption
                                OptionFnd.Present = True
                                OptionFnd.OptionChar = OptionString(0)
                                OptionString = OptionString.Substring(l + 2)
                                Exit Do ' found
                            End If
                        Else
                            Exit For ' next possible option
                        End If
                    End If
                Next
            Next
            Exit Do ' not found
        Loop
        If Not Fnd Then
            Dim i As Integer = OptionString.IndexOf(" ")
            RejectedOptions &= OptionString.Substring(0, i) & " "
            OptionString = OptionString.Substring(i).TrimStart
        Else
            If OptionFnd.ValueReq Then
                If OptionFnd.Quoted Then
                    If OptionString(0) = """" Then
                        OptionString = OptionString.Substring(1)
                        Dim i As Integer = OptionString.IndexOf("""")
                        If i > -1 Then
                            OptionFnd.TextValue = OptionString.Substring(0, i)
                            OptionString = OptionString.Substring(i + 1).TrimStart
                        Else ' closing quote missing
                            i = OptionString.IndexOf(" ")
                            OptionFnd.TextValue = """" & OptionString.Substring(0, i)
                            OptionString = OptionString.Substring(i).TrimStart
                        End If
                    Else ' not quoted
                        Dim i As Integer = OptionString.IndexOf(" ")
                        OptionFnd.TextValue = OptionString.Substring(0, i)
                        OptionString = OptionString.Substring(i).TrimStart
                    End If
                Else ' never quoted
                    Dim i As Integer = OptionString.IndexOf(" ")
                    OptionFnd.TextValue = OptionString.Substring(0, i)
                    OptionString = OptionString.Substring(i).TrimStart
                End If
            End If
        End If
    End While
    wop.Text = RejectedOptions
End Sub
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
End Sub
End Class
Public Class OneOption
'input
Friend OptionText As String ' required
Friend Separator As Char ' if specified, CurrOption value follows the option, like : in -SORT:A
Friend Quoted As Boolean ' value may be "q u o t e d"   
'work
Friend ValueReq As Boolean ' is value required (as seperator was given in NEW)?
'output 
Friend Present As Boolean ' option present
Friend OptionChar As Char ' options was preceeded by + - / whatever
Friend TextValue As String ' the value following the option
Sub New(pOptionText As String) ' option without a value, a switch
    OptionText = pOptionText
    reset()
End Sub
Sub New(pOptionText As String, pSeparator As Char) ' option with a value, the separator between option and value has to be specified
    OptionText = pOptionText
    reset()
    Separator = pSeparator
    ValueReq = True
    Quoted = False
End Sub
Sub New(pOptionText As String, pSeparator As Char, pQuoted As Boolean) ' option with a possibly "quoted value", the separator between option and value has to be specified
    OptionText = pOptionText
    reset()
    Separator = pSeparator
    ValueReq = True
    Quoted = pQuoted
End Sub
Sub reset()
    Separator = " "c
    Quoted = False
    Present = False
    ValueReq = False
End Sub
End Class

Upvotes: -1

fvu
fvu

Reputation: 32953

In many (most?) Linux programs these options are handled by getopt. It's a pretty versatile system, so it might be a good point to start and get some inspiration.

Upvotes: 1

Related Questions