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になってたのを修正。やっぱり、頭がどうかしてしまったようだ。