VB2008でコマンドライン スイッチの判定を実装してみた

http://devadjust.exblog.jp/20069155/
この記事を見て、久々に何か書いてみたいな!と思ったので、書いてみます。

まず、コマンドライン引数のパーサを書くんだけど、パースした結果をどう扱えるか? どれだけ扱いやすいか? という事から考えてみた。私なら、こう書きたい。

        Dim opts = (New OptionParser).Parse(args)   'この辺はきっとごにょごにょする

        Dim hogeParam1 As String = "hogedefault1"   'set default
        Dim hogeParam2 As String = "hogedefault2"   'set default
        If opts.ContainsKey("hoge") Then            'こんな感じで「このパラメータあれば」って書けるとうれしい
            With opts("hoge")                       'VB風味を加える
                If .Count >= 1 Then                 '個別の引数はこんな感じで
                    hogeParam1 = .Item(0)
                End If
                If .Count >= 2 Then
                    hogeParam2 = .Item(1)
                End If
            End With
        End If

こんな感じでスイッチの部分はディクショナリのキーになってて、そのスイッチの引数はディクショナリの値(コレクション)に要素として入ってる。きっと書くときこうなってると嬉しい感じがする。で、これをやってくれるOptionParserを書いた。

Public Class OptionParser
    Private listOfOptionName As New List(Of String)
    Private swChar As Char
    Public Sub New(ByVal args() As String, ByVal swc As Char)
        swChar = swc
        listOfOptionName = args.Distinct().ToList()
    End Sub
    Public Function Parse(ByVal args() As String) As Dictionary(Of String, List(Of String))
        Parse = New Dictionary(Of String, List(Of String))
        For i = 0 To args.Length - 1
            Dim targetArg = args(i)
            If listOfOptionName.Exists(Function(n) String.Format("{0}{1}", swChar, n) = targetArg) Then
                Parse.Add(targetArg.Substring(1, targetArg.Length - 1), New List(Of String))
            Else
                If Parse.Count > 0 AndAlso targetArg(0) <> swChar Then
                    Parse.Last.Value.Add(targetArg)
                Else
                    Debug.Print("{0} droped.index={1}", targetArg, i)
                End If
            End If
        Next
    End Function
End Class

呼ぶときはこんな感じに。

    Sub Main(ByVal args() As String)
        Dim myOptions() As String = {"hoge", "fuga", "piyo"}
        Dim opts = (New OptionParser(myOptions, "-"c)).Parse(args)

コンストラクタの第二引数に"-"cとか書いてあるのは、ほら、あれですよ、スイッチって"/"のコマンドとかもあるじゃないですか。そこらへんのフィーリングに引数ひとつで対応する為。考えすぎかもしれないけど。

呼び出し部分全体を、もっかい貼り付けてみよう。

Module OptionParseSample
    Sub Main(ByVal args() As String)
        Dim myOptions() As String = {"hoge", "hoge", "fuga", "piyo"}
        Dim opts = (New OptionParser(myOptions, "-"c)).Parse(args)

        'パースした結果を出力
        For Each item In opts
            Console.WriteLine(item.Key)
            For Each p In item.Value
                Console.WriteLine("  {0}", p)
            Next
        Next

        'こんな風に書けるよ!
        Dim hogeParam1 As String = "hogedefault1"   'set default
        Dim hogeParam2 As String = "hogedefault2"   'set default
        If opts.ContainsKey("hoge") Then
            With opts("hoge")
                If .Count >= 1 Then
                    hogeParam1 = .Item(0)
                End If
                If .Count >= 2 Then
                    hogeParam2 = .Item(1)
                End If
            End With
        End If
    End Sub
End Module

お楽しみでほいほいーっと書いたので、テキトーにバグってるかもしんない(予防線)。でもまあ、OKだ。初めてGitHubリポジトリも作ってアップしちゃったー! きゃー!w

でも、このリポジトリへのリンクとかどうやって貼るんだろ? ま、それはあとで勉強しよう。ひとまず送信!

ベランダ日記

ちょーひさびさのベランダ日記。まずはセントポーリア。

いい感じにつぼみがついてきました。日差しが午前中だけ入るベランダに置いておいたらいい感じになってきた。やっぱ日光大事。

次はトマト。
お義母さんがベランダに置いて行ってくれたプランターと苗がここまでになった。

トマトすげー楽だ!

あ…ありのまま 今 起こった事を話すぜ!

         ,. -‐'''''""¨¨¨ヽ
         (.___,,,... -ァァフ|          あ…ありのまま 今 起こった事を話すぜ!
          |i i|    }! }} //|
         |l、{   j} /,,ィ//|       『Short型のSelect文のCaseに
        i|:!ヾ、_ノ/ u {:}//ヘ        文字列をCIntした値が使われていた』
        |リ u' }  ,ノ _,!V,ハ |
       /´fト、_{ル{,ィ'eラ , タ人        な… 何を言ってるのか わからねーと思うが
     /'   ヾ|宀| {´,)⌒`/ |<ヽトiゝ        おれも何をされたのかわからなかった…
    ,゙  / )ヽ iLレ  u' | | ヾlトハ〉
     |/_/  ハ !ニ⊇ '/:}  V:::::ヽ        頭がどうにかなりそうだった…
    // 二二二7'T'' /u' __ /:::::::/`ヽ
   /'´r -―一ァ‐゙T´ '"´ /::::/-‐  \    暗黙の型変換だとかマジックナンバーだとか
   / //   广¨´  /'   /:::::/´ ̄`ヽ ⌒ヽ    そんなチャチなもんじゃあ 断じてねえ
  ノ ' /  ノ:::::`ー-、___/::::://       ヽ  }
_/`丶 /:::::::::::::::::::::::::: ̄`ー-{:::...       イ  もっと恐ろしいものの片鱗を味わったぜ…

こんな。

Module Arinomama

    Sub Main(args() As String)
        Dim hoge As Short = Short.Parse(args(0))
        Select Case hoge
            Case CInt("0")
                Console.WriteLine("zero!")
            Case CInt("1")
                Console.WriteLine("one!")
        End Select
    End Sub

End Module

まじで。
助けてドラえもん!!!

つーか、現場にはこんなコードがあふれかえってるんだよ! もうなんか、悲しい! このやりきれなさを俺は一体どうしたらいいのか!

うーん、サンプルコードがShortじゃなくてSingleになってたのを修正。やっぱり、頭がどうかしてしまったようだ。

70-515合格!

*     +     巛 ヽ
            〒 !   +    。     +    。     *     。
      +    。  |  |
   *     +   / /   イヤッッホォォォオオォオウ!
       ∧_∧ / /
      (´∀` / / +    。     +    。   *     。
      ,-     f
      / ュヘ    | *     +    。     +   。 +
     〈_} )   |
        /    ! +    。     +    +     *
       ./  ,ヘ  |
 ガタン ||| j  / |  | |||
――――――――――――

対策本の無い試験は難しいね。でも大分勉強して知識は多少なりとも増えたと思う。よかった。