1 #Region "Microsoft.VisualBasic::8131ed9a4734ae73329de534db8a7e7f, Microsoft.VisualBasic.Core\CommandLine\CommandLine.vb"
2
3     ' Author:
4     
5     '       asuka (amethyst.asuka@gcmodeller.org)
6     '       xie (genetics@smrucc.org)
7     '       xieguigang (xie.guigang@live.com)
8     
9     ' Copyright (c) 2018 GPL3 Licensed
10     
11     
12     ' GNU GENERAL PUBLIC LICENSE (GPL3)
13     
14     
15     ' This program is free software: you can redistribute it and/or modify
16     ' it under the terms of the GNU General Public License as published by
17     ' the Free Software Foundation, either version 3 of the License, or
18     ' (at your option) any later version.
19     
20     ' This program is distributed in the hope that it will be useful,
21     ' but WITHOUT ANY WARRANTY; without even the implied warranty of
22     ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23     ' GNU General Public License for more details.
24     
25     ' You should have received a copy of the GNU General Public License
26     ' along with this program. If not, see <http://www.gnu.org/licenses/>.
27
28
29
30     ' /********************************************************************************/
31
32     ' Summaries:
33
34     '     Class CommandLine
35     
36     '         Properties: BoolFlags, CLICommandArgvs, Count, EnvironmentVariables, IsNothing
37     '                     IsNullOrEmpty, IsReadOnly, Keys, Name, ParameterList
38     '                     Parameters, SingleValue, Tokens
39     
40     '         FunctionAssert, CheckMissingRequiredArguments, CheckMissingRequiredParameters, Contains, ContainsParameter
41     '                   GetBoolean, GetByte, GetBytes, GetChar, GetChars
42     '                   GetCommandsOverview, GetDateTime, GetDecimal, GetDictionary, GetDouble
43     '                   GetEnumerator, GetEnumerator1, GetFloat, GetFullDIRPath, GetFullFilePath
44     '                   GetGuid, GetInt16, GetInt32, GetInt64, GetObject
45     '                   GetOrdinal, GetString, GetValue, HavebFlag, IsNull
46     '                   IsTrue, OpenHandle, OpenStreamInput, OpenStreamOutput, ReadInput
47     '                   (+2 Overloads) Remove, ToArgumentVector, ToString
48     
49     '         Sub: (+2 Overloads) Add, Clear, CopyTo
50     
51     '         Operators: (+4 Overloads) -, ^, +, <, (+2 Overloads) <=
52     '                    >, (+2 Overloads) >=
53     
54     
55     ' /********************************************************************************/
56
57 #End Region
58
59 Imports System.IO
60 Imports System.Runtime.CompilerServices
61 Imports System.Text
62 Imports Microsoft.VisualBasic.CommandLine.Parsers
63 Imports Microsoft.VisualBasic.ComponentModel.Collection.Generic
64 Imports Microsoft.VisualBasic.ComponentModel.DataSourceModel
65 Imports Microsoft.VisualBasic.Language
66 Imports Microsoft.VisualBasic.Language.Default
67 Imports Microsoft.VisualBasic.Language.UnixBash.FileSystem
68 Imports Microsoft.VisualBasic.Linq
69 Imports Microsoft.VisualBasic.Scripting
70 Imports Microsoft.VisualBasic.Scripting.Expressions
71 Imports Microsoft.VisualBasic.Serialization
72 Imports Microsoft.VisualBasic.Text
73
74 Namespace CommandLine
75
76     ''' <summary>
77     ''' A command line object that parse from the user input commandline string.
78     ''' (从用户所输入的命令行字符串之中解析出来的命令行对象,标准的命令行格式为:
79     ''' <example>&lt;EXE> &lt;CLI_Name> ["Parameter" "Value"]</example>)
80     ''' </summary>
81     ''' <remarks></remarks>
82     '''
83     Public Class CommandLine : Inherits BaseClass
84         Implements ICollection(Of NamedValue(Of String))
85         Implements INamedValue
86
87         Friend __arguments As New List(Of NamedValue(Of String))
88         ''' <summary>
89         ''' 原始的命令行字符串
90         ''' </summary>
91         Friend _CLICommandArgvs As String
92
93         Dim _name As String
94
95         ''' <summary>
96         ''' The command name that parse from the input command line.
97         ''' (从输入的命令行中所解析出来的命令的名称)
98         ''' </summary>
99         ''' <value></value>
100         ''' <returns></returns>
101         ''' <remarks></remarks>
102         Public Property Name As String Implements INamedValue.Key
103             <MethodImpl(MethodImplOptions.AggressiveInlining)>
104             Get
105                 Return _name
106             End Get
107             Protected Friend Set(value As String)
108                 _name = value
109             End Set
110         End Property
111
112         ''' <summary>
113         ''' The command tokens that were parsed from the input commandline.
114         ''' (从所输入的命令行之中所解析出来的命令参数单元)
115         ''' </summary>
116         ''' <value></value>
117         ''' <returns></returns>
118         ''' <remarks></remarks>
119         Public Property Tokens As String()
120
121         ''' <summary>
122         ''' Listing all of the parameter value collection that parsed from the commandline string.
123         ''' </summary>
124         ''' <returns></returns>
125         Public ReadOnly Property ParameterList As NamedValue(Of String)()
126             <MethodImpl(MethodImplOptions.AggressiveInlining)>
127             Get
128                 Return __arguments.ToArray
129             End Get
130         End Property
131
132         ''' <summary>
133         ''' 得到当前的命令行对象之中的所有的参数的名称的列表
134         ''' </summary>
135         ''' <returns></returns>
136         Public ReadOnly Property Keys As String()
137             <MethodImpl(MethodImplOptions.AggressiveInlining)>
138             Get
139                 Return __arguments.Select(Function(v) v.Name).ToArray
140             End Get
141         End Property
142
143         ''' <summary>
144         ''' The parameters in the commandline without the first token of the command name.
145         ''' (将命令行解析为词元之后去掉命令的名称之后所剩下的所有的字符串列表)
146         ''' </summary>
147         ''' <value></value>
148         ''' <returns></returns>
149         ''' <remarks></remarks>
150         <DumpNode> Public ReadOnly Property Parameters As String()
151             <MethodImpl(MethodImplOptions.AggressiveInlining)>
152             Get
153                 Return Tokens.Skip(1).ToArray
154             End Get
155         End Property
156
157         ''' <summary>
158         ''' 对于参数而言,都是--或者-或者/或者\开头的,下一个单词为单引号或者非上面的字符开头的,例如/o &lt;path>
159         ''' 对于开关而言,与参数相同的其实符号,但是后面不跟参数而是其他的开关,通常开关用来进行简要表述一个逻辑值
160         ''' </summary>
161         ''' <returns></returns>
162         Public Property BoolFlags As String()
163
164         ''' <summary>
165         ''' 获取得到通过``/@set``参数所传入的环境变量
166         ''' </summary>
167         ''' <returns></returns>
168         Public ReadOnly Property EnvironmentVariables As Dictionary(Of StringString)
169             <MethodImpl(MethodImplOptions.AggressiveInlining)>
170             Get
171                 ' 在命令行之中没有任何其他的参数,但是存在一个/@set的话,这个标记会被当作为命令名称
172                 ' 则在读取环境变量的时候就会失败
173                 If Name.TextEquals("/@set"Then
174                     Return DictionaryParser.TryParse(Parameters(Scan0))
175                 Else
176                     Return GetDictionary("/@set")
177                 End If
178             End Get
179         End Property
180
181         ''' <summary>
182         ''' Get the original command line string.(获取所输入的命令行对象的原始的字符串)
183         ''' </summary>
184         ''' <value></value>
185         ''' <returns></returns>
186         ''' <remarks></remarks>
187         Public ReadOnly Property CLICommandArgvs As String
188             <MethodImpl(MethodImplOptions.AggressiveInlining)>
189             Get
190                 Return _CLICommandArgvs
191             End Get
192         End Property
193
194         ''' <summary>
195         ''' The parameter name is not case sensitive.
196         ''' (开关的名称是不区分大小写的,进行字符串插值脚本化处理的时候,是使用的<see cref="App.GetVariable"/>函数来获取环境变量值)
197         ''' </summary>
198         ''' <param name="paramName">The argument name in the commandline.</param>
199         ''' <value></value>
200         ''' <returns></returns>
201         ''' <remarks></remarks>
202         Default Public ReadOnly Property Item(paramName As StringAs DefaultString
203             Get
204                 Dim LQuery As NamedValue(Of String) =
205                     __arguments _
206                         .Where(Function(x)
207                                    Return String.Equals(x.Name, paramName, StringComparison.OrdinalIgnoreCase)
208                                End Function) _
209                         .FirstOrDefault
210
211                 Dim value As String = LQuery.Value ' 是值类型,不会出现空引用的情况
212
213                 If value.StringEmpty Then
214                     ' 2018-1-22
215                     '
216                     ' 如果是需要获取逻辑值的话,直接查找__arguments值列表是获取不到结果的
217                     ' 在这里使用IsTrue来判断,如果开关存在则返回TRUE字符串
218                     ' 否则返回空字符串表示不存在
219
220                     If HavebFlag(paramName) Then
221                         value = "TRUE"
222                     Else
223                         value = ""
224                     End If
225                 Else
226                     ' 尝试进行字符串插值,从而实现命令行部分脚本化
227
228                     ' 2017-3-13
229                     ' 对于Windows文件路径而言, 不推荐转义
230                     ' 因为Windows的文件路径分隔符为\,很容易引起误解,例如C:\tsv会被误转义为C:<TAB>sv而导致错误
231                     ' 所以在这里关闭escape参数选项
232                     value = value.Interpolate(__envir, escape:=False)
233                 End If
234
235                 Return New DefaultString(value)
236             End Get
237         End Property
238
239         ReadOnly __envir As Func(Of StringString) = AddressOf App.GetVariable
240
241         Public Property SingleValue As String
242
243         ''' <summary>
244         ''' See if the target logical flag argument is exists in the commandline?
245         ''' (查看命令行之中是否存在某一个逻辑开关)
246         ''' </summary>
247         ''' <param name="name"></param>
248         ''' <returns></returns>
249         Public Function HavebFlag(name As StringAs Boolean
250             If Me.BoolFlags.IsNullOrEmpty Then
251                 Return False
252             Else
253                 ' boolflags 已经全部都被转换为小写形式了
254                 Return Array.IndexOf(BoolFlags, name.ToLower) > -1
255             End If
256         End Function
257
258         ''' <summary>
259         ''' Returns the original cli command line argument string.(返回所传入的命令行的原始字符串)
260         ''' </summary>
261         ''' <returns></returns>
262         ''' <remarks></remarks>
263         ''' 
264         <MethodImpl(MethodImplOptions.AggressiveInlining)>
265         Public Overrides Function ToString() As String
266             Return CLICommandArgvs
267         End Function
268
269         ''' <summary>
270         ''' Get specific argument value as full directory path.
271         ''' </summary>
272         ''' <param name="name">parameter name</param>
273         ''' <returns></returns>
274         ''' 
275         <MethodImpl(MethodImplOptions.AggressiveInlining)>
276         Public Function GetFullDIRPath(name As StringAs String
277             Return FileIO.FileSystem.GetDirectoryInfo(Me(name)).FullName
278         End Function
279
280         ''' <summary>
281         ''' Get specific argument value as full file path.(这个函数还会同时修正file://协议的头部)
282         ''' </summary>
283         ''' <param name="name">parameter name</param>
284         ''' <returns></returns>
285         Public Function GetFullFilePath(name As StringAs String
286             Dim path$ = Me(name)
287             path = FixPath(path)
288             Return FileIO.FileSystem.GetFileInfo(path).FullName
289         End Function
290
291         ''' <summary>
292         ''' Gets the brief summary information of current cli command line object.
293         ''' (获取当前的命令行对象的参数摘要信息)
294         ''' </summary>
295         ''' <returns></returns>
296         ''' <remarks></remarks>
297         Public Function GetCommandsOverview() As String
298             Dim sb As New StringBuilder(vbCrLf, 1024)
299             Call sb.AppendLine($"Commandline arguments overviews{vbCrLf}Command Name  --  ""{Me.Name}""")
300             Call sb.AppendLine()
301             Call sb.AppendLine("---------------------------------------------------------")
302             Call sb.AppendLine()
303
304             If __arguments.Count = 0 Then
305                 Call sb.AppendLine("No parameter was define in this commandline.")
306                 Return sb.ToString
307             End If
308
309             Dim MaxSwitchName As Integer = (From item As NamedValue(Of String)
310                                             In __arguments
311                                             Select Len(item.Name)).Max
312             For Each sw As NamedValue(Of StringIn __arguments
313                 Call sb.AppendLine($"  {sw.Name}  {New String(" "c, MaxSwitchName - Len(sw.Name))}= ""{sw.Value}"";")
314             Next
315
316             Return sb.ToString
317         End Function
318
319         ''' <summary>
320         ''' Checking for the missing required parameter, this function will returns the missing parameter
321         ''' in the current cli command line object using a specific parameter name list.
322         ''' (检查<paramref name="list"></paramref>之中的所有参数是否存在,函数会返回不存在的参数名)
323         ''' </summary>
324         ''' <param name="list"></param>
325         ''' <returns></returns>
326         ''' <remarks></remarks>
327         Public Function CheckMissingRequiredParameters(list As IEnumerable(Of String)) As String()
328             Dim LQuery$() = LinqAPI.Exec(Of String) _
329  _
330                 () <= From p As String
331                       In list
332                       Where String.IsNullOrEmpty(Me(p))
333                       Select p
334
335             Return LQuery
336         End Function
337
338         ''' <summary>
339         ''' Gets a list of missing required argument name.
340         ''' </summary>
341         ''' <param name="args"></param>
342         ''' <returns></returns>
343         ''' 
344         <MethodImpl(MethodImplOptions.AggressiveInlining)>
345         Public Function CheckMissingRequiredArguments(ParamArray args As String()) As String()
346             Return CheckMissingRequiredParameters(list:=args)
347         End Function
348
349         ''' <summary>
350         ''' Does this cli command line object contains any parameter argument information.
351         ''' (查看本命令行参数对象之中是否存在有参数信息)
352         ''' </summary>
353         ''' <value></value>
354         ''' <returns></returns>
355         ''' <remarks></remarks>
356         Public ReadOnly Property IsNullOrEmpty As Boolean
357             <MethodImpl(MethodImplOptions.AggressiveInlining)>
358             Get
359                 Return Tokens.IsNullOrEmpty OrElse (Tokens.Length = 1 AndAlso String.IsNullOrEmpty(Tokens.First))
360             End Get
361         End Property
362
363         ''' <summary>
364         ''' <see cref="String.IsNullOrEmpty"/> of <see cref="Name"/> AndAlso <see cref="IsNullOrEmpty"/>
365         ''' </summary>
366         ''' <returns></returns>
367         Public ReadOnly Property IsNothing As Boolean
368             <MethodImpl(MethodImplOptions.AggressiveInlining)>
369             Get
370                 Return String.IsNullOrEmpty(Me.Name) AndAlso IsNullOrEmpty
371             End Get
372         End Property
373
374         ''' <summary>
375         ''' Does the specific argument exists in this commandline? argument name is not case sensitity.
376         ''' (参数名称字符串大小写不敏感)
377         ''' </summary>
378         ''' <param name="parameterName"></param>
379         ''' <returns></returns>
380         Public Function ContainsParameter(parameterName As String, trim As BooleanAs Boolean
381             Dim namer As String = If(trim, parameterName.TrimParamPrefix, parameterName)
382             Dim LQuery = LinqAPI.DefaultFirst(Of Integer) _
383  _
384                 () <= From para As NamedValue(Of String)
385                       In Me.__arguments  '  名称都是没有处理过的
386                       Where String.Equals(namer, para.Name, StringComparison.OrdinalIgnoreCase)
387                       Select 100
388
389             Return LQuery > 50
390         End Function
391
392         ''' <summary>
393         ''' Parsing the commandline string as object model
394         ''' </summary>
395         ''' <param name="CommandLine"></param>
396         ''' <returns></returns>
397         ''' 
398         <MethodImpl(MethodImplOptions.AggressiveInlining)>
399         Public Shared Widening Operator CType(CommandLine As StringAs CommandLine
400             Return TryParse(CommandLine)
401         End Operator
402
403         <MethodImpl(MethodImplOptions.AggressiveInlining)>
404         Public Shared Widening Operator CType(CLI As Func(Of String)) As CommandLine
405             Return TryParse(CLI())
406         End Operator
407
408         ''' <summary>
409         ''' Determined that the specific Boolean flag is exists or not? 
410         ''' if not then returns <paramref name="failure"/>, if exists such flag, then returns the <paramref name="name"/>.
411         ''' </summary>
412         ''' <param name="name">Boolean flag name</param>
413         ''' <param name="failure"></param>
414         ''' <returns></returns>
415         Public Function Assert(name As StringOptional failure As String = ""As String
416             If GetBoolean(name) Then
417                 Return name
418             Else
419                 Return failure
420             End If
421         End Function
422
423         ''' <summary>
424         ''' If the target parameter is not presents in the CLI, then this function will returns nothing.
425         ''' (键值对之间使用分号分隔)
426         ''' </summary>
427         ''' <param name="name$"></param>
428         ''' <returns></returns>
429         Public Function GetDictionary(name$, Optional default$ = NothingAs Dictionary(Of StringString)
430             Dim s$ = Me(name$)
431
432             If String.IsNullOrEmpty(s$) Then
433                 If [default].StringEmpty Then
434                     Return Nothing
435                 Else
436                     Return DictionaryParser.TryParse([default])
437                 End If
438             Else
439                 Return DictionaryParser.TryParse(s$)
440             End If
441         End Function
442
443         Public Function IsTrue(parameter$) As Boolean
444             If Me.HavebFlag(parameter) Then
445                 Return True
446             End If
447             Return Me(parameter).DefaultValue.ParseBoolean
448         End Function
449
450 #Region "Pipeline"
451
452         ''' <summary>About <paramref name="s"/>:
453         ''' 
454         ''' + If the file path is not a value path, then is the value is not null, the argument value will be returned from this parameter. 
455         ''' + If the value is nothing, then this function will open the standard input as input.
456         ''' + If the file path is valid as input file, then a local file system pointer will be returned.
457         ''' 
458         ''' [管道函数] 假若参数名存在并且所指向的文件也存在,则返回本地文件的文件指针,否则返回标准输入的指针
459         ''' </summary>
460         ''' <param name="param"></param>
461         ''' <param name="s">
462         ''' + If the file path is not a value path, then is the value is not null, the argument value will be returned from this parameter. 
463         ''' + If the value is nothing, then this function will open the standard input as input.
464         ''' + If the file path is valid as input file, then a local file system pointer will be returned.
465         ''' </param>
466         ''' <returns></returns>
467         Public Function OpenStreamInput(param As StringOptional ByRef s As String = NothingAs StreamReader
468             Dim path As String = Me(param)
469
470             If path.FileExists Then
471                 Return New StreamReader(New FileStream(path, FileMode.Open, access:=FileAccess.Read))
472             ElseIf Not String.IsNullOrEmpty(path) Then
473                 s = path
474                 Return Nothing
475             Else
476                 Return New StreamReader(Console.OpenStandardInput)
477             End If
478         End Function
479
480         ''' <summary>
481         ''' If the <see cref="StreamWriter.BaseStream"/> is <see cref="FileStream"/>, then it means not a ``std_out`` pointer.
482         ''' ([管道函数] 假若参数名存在,则返回本地文件的文件指针,否则返回标准输出的指针)
483         ''' </summary>
484         ''' <param name="param"></param>
485         ''' <returns></returns>
486         Public Function OpenStreamOutput(param$, Optional encoding As Encodings = Encodings.UTF8) As StreamWriter
487             Dim path As String = Me(param)
488             Dim textEncode As Encoding = encoding.CodePage
489
490             If path.StringEmpty Then
491                 Return New StreamWriter(Console.OpenStandardOutput, textEncode)
492             Else
493                 Call path.ParentPath.MkDIR
494
495                 Dim fs As New FileStream(path, FileMode.OpenOrCreate, access:=FileAccess.ReadWrite)
496                 Return New StreamWriter(fs, textEncode)
497             End If
498         End Function
499
500         ''' <summary>
501         ''' Read all of the text input from the file or ``std_in``
502         ''' </summary>
503         ''' <param name="param"></param>
504         ''' <returns></returns>
505         Public Function ReadInput(param As StringAs String
506             Dim s As String = Nothing
507             Dim read As StreamReader = OpenStreamInput(param, s)
508             If read Is Nothing Then
509                 Return s
510             Else
511                 Return read.ReadToEnd
512             End If
513         End Function
514 #End Region
515
516 #Region "IDataRecord Methods"
517
518         ''' <summary>
519         ''' Gets the value Of the specified column As a Boolean.
520         ''' (这个函数也同时包含有开关参数的,开关参数默认为逻辑值类型,当包含有开关参数的时候,其逻辑值为True,反之函数会检查参数列表,参数不存在则为空值字符串,则也为False)
521         ''' </summary>
522         ''' <param name="parameter">可以包含有开关参数</param>
523         ''' <returns></returns>
524         ''' 
525         <MethodImpl(MethodImplOptions.AggressiveInlining)>
526         Public Function GetBoolean(parameter As StringAs Boolean
527             Return Me.IsTrue(parameter)
528         End Function
529
530         ''' <summary>
531         ''' Gets the 8-bit unsigned Integer value Of the specified column.
532         ''' </summary>
533         ''' <param name="parameter"></param>
534         ''' <returns></returns>
535         ''' 
536         <MethodImpl(MethodImplOptions.AggressiveInlining)>
537         Public Function GetByte(parameter As StringAs Byte
538             Return CByte(Val(Me(parameter)))
539         End Function
540
541         ''' <summary>
542         ''' Reads a stream Of bytes from the specified column offset into the buffer As an array, starting at the given buffer offset.
543         ''' </summary>
544         ''' <returns></returns>
545         Public Function GetBytes(parameter As StringAs Byte()
546             Dim tokens As String() = Me(parameter).DefaultValue.Split(","c)
547             Return (From s As String In tokens Select CByte(Val(s))).ToArray
548         End Function
549
550         ''' <summary>
551         ''' Gets the character value Of the specified column.
552         ''' </summary>
553         ''' <returns></returns>
554         Public Function GetChar(parameter As StringAs Char
555             Dim s As String = Me(parameter)
556
557             If String.IsNullOrEmpty(s) Then
558                 Return ASCII.NUL
559             Else
560                 Return s.First
561             End If
562         End Function
563
564         ''' <summary>
565         ''' Reads a stream Of characters from the specified column offset into the buffer As an array, starting at the given buffer offset.
566         ''' </summary>
567         ''' <returns></returns>
568         ''' 
569         <MethodImpl(MethodImplOptions.AggressiveInlining)>
570         Public Function GetChars(parameter As StringAs Char()
571             Return Me(parameter)
572         End Function
573
574         ''' <summary>
575         ''' Gets the Date And time data value Of the specified field.
576         ''' </summary>
577         ''' <returns></returns>
578         ''' 
579         <MethodImpl(MethodImplOptions.AggressiveInlining)>
580         Public Function GetDateTime(parameter As StringAs DateTime
581             Return Me(parameter).DefaultValue.ParseDateTime
582         End Function
583
584         ''' <summary>
585         ''' Gets the fixed-position numeric value Of the specified field.
586         ''' </summary>
587         ''' <returns></returns>
588         ''' 
589         <MethodImpl(MethodImplOptions.AggressiveInlining)>
590         Public Function GetDecimal(parameter As StringAs Decimal
591             Return CDec(Val(Me(parameter).DefaultValue))
592         End Function
593
594         ''' <summary>
595         ''' Gets the Double-precision floating point number Of the specified field.
596         ''' </summary>
597         ''' <returns></returns>
598         ''' 
599         <MethodImpl(MethodImplOptions.AggressiveInlining)>
600         Public Function GetDouble(parameter As StringAs Double
601             Return Val(Me(parameter).DefaultValue)
602         End Function
603
604         ''' <summary>
605         ''' Gets the Single-precision floating point number Of the specified field.
606         ''' </summary>
607         ''' <returns></returns>
608         ''' 
609         <MethodImpl(MethodImplOptions.AggressiveInlining)>
610         Public Function GetFloat(parameter As StringAs Single
611             Return CSng(Val(Me(parameter).DefaultValue))
612         End Function
613
614         ''' <summary>
615         ''' Returns the GUID value Of the specified field.
616         ''' </summary>
617         ''' <returns></returns>
618         ''' 
619         <MethodImpl(MethodImplOptions.AggressiveInlining)>
620         Public Function GetGuid(parameter As StringAs Guid
621             Return Guid.Parse(Me(parameter))
622         End Function
623
624         ''' <summary>
625         ''' Gets the 16-bit signed Integer value Of the specified field.
626         ''' </summary>
627         ''' <returns></returns>
628         ''' 
629         <MethodImpl(MethodImplOptions.AggressiveInlining)>
630         Public Function GetInt16(parameter As StringAs Int16
631             Return CType(Val(Me(parameter).DefaultValue), Int16)
632         End Function
633
634         ''' <summary>
635         ''' Gets the 32-bit signed Integer value Of the specified field.
636         ''' </summary>
637         ''' <returns></returns>
638         ''' 
639         <MethodImpl(MethodImplOptions.AggressiveInlining)>
640         Public Function GetInt32(parameter As StringAs Int32
641             Return CInt(Val(Me(parameter).DefaultValue))
642         End Function
643
644         ''' <summary>
645         ''' Gets the 64-bit signed Integer value Of the specified field.
646         ''' </summary>
647         ''' <returns></returns>
648         ''' 
649         <MethodImpl(MethodImplOptions.AggressiveInlining)>
650         Public Function GetInt64(parameter As StringAs Int64
651             Return CLng(Val(Me(parameter).DefaultValue))
652         End Function
653
654         ''' <summary>
655         ''' Return the index Of the named field. If the name is not exists in the parameter list, then a -1 value will be return.
656         ''' </summary>
657         ''' <returns></returns>
658         Public Function GetOrdinal(parameter As StringAs Integer
659             Dim i% = LinqAPI.DefaultFirst(Of Integer)(-1) _
660  _
661                 <= From entry As NamedValue(Of String)
662                    In Me.__arguments
663                    Where String.Equals(parameter, entry.Name, StringComparison.OrdinalIgnoreCase)
664                    Select __arguments.IndexOf(entry)
665
666             Return i
667         End Function
668
669         ''' <summary>
670         ''' Gets the String value Of the specified field.
671         ''' </summary>
672         ''' <returns></returns>
673         ''' 
674         <MethodImpl(MethodImplOptions.AggressiveInlining)>
675         Public Function GetString(parameter As StringAs String
676             Return Me(parameter)
677         End Function
678
679         ''' <summary>
680         ''' Return whether the specified field Is Set To null.
681         ''' </summary>
682         ''' <returns></returns>
683         ''' 
684         <MethodImpl(MethodImplOptions.AggressiveInlining)>
685         Public Function IsNull(parameter As StringAs Boolean
686             Return Not Me.ContainsParameter(parameter, False)
687         End Function
688
689         ''' <summary>
690         '''
691         ''' </summary>
692         ''' <typeparam name="T"></typeparam>
693         ''' <param name="parameter">Command parameter name in the command line inputs.</param>
694         ''' <param name="__getObject"></param>
695         ''' <returns></returns>
696         Public Function GetObject(Of T)(parameter$, Optional __getObject As Func(Of String, T) = NothingAs T
697             Dim value$ = Me(parameter)
698             Dim obj = (__getObject Or StringParser(GetType(T)))(arg:=value)
699             Dim x As T = DirectCast(obj, T)
700             Return x
701         End Function
702
703         ''' <summary>
704         ''' If the given parameter is not exists in the user input arguments, then a developer specific default value will be return.
705         ''' </summary>
706         ''' <typeparam name="T"></typeparam>
707         ''' <param name="name">The optional argument parameter name</param>
708         ''' <param name="[default]">The default value for returns when the parameter is not exists in the user input.</param>
709         ''' <param name="__ctype">The custom string parser for the CLI argument value</param>
710         ''' <returns></returns>
711         Public Function GetValue(Of T)(name$, [default] As T, Optional __ctype As Func(Of String, T) = NothingAs T
712             If Not Me.ContainsParameter(name, FalseThen
713                 If GetType(T).Equals(GetType(Boolean)) Then
714                     If HavebFlag(name) Then
715                         Return DirectCast(DirectCast(GetBoolean(name), Object), T)
716                     End If
717                 End If
718
719                 Return [default]
720             End If
721
722             Dim str As String = Me(name).DefaultValue
723
724             If __ctype Is Nothing Then
725                 Dim value As Object = InputHandler.CTypeDynamic(str, GetType(T))
726                 Return DirectCast(value, T)
727             Else
728                 Return __ctype(str)
729             End If
730         End Function
731
732         ''' <summary>
733         ''' Open a file handle by using the parameter value
734         ''' </summary>
735         ''' <param name="name">The parameter name, and its argument value should be a valid file path</param>
736         ''' <param name="[default]">Default file path if the argument value is not exists</param>
737         ''' <returns></returns>
738         Public Function OpenHandle(name$, Optional default$ = ""As int
739             Dim file As String = Me(name)
740             If String.IsNullOrEmpty(file) Then
741                 file = [default]
742             End If
743             Return New int(FileHandles.OpenHandle(file))
744         End Function
745 #End Region
746
747 #Region "Implements IReadOnlyCollection(Of KeyValuePair(Of StringString))"
748
749         ''' <summary>
750         ''' 这个枚举函数也会将开关给包含进来,与<see cref="ToArgumentVector"/>方法所不同的是,这个函数里面的逻辑值开关的名称没有被修饰剪裁
751         ''' </summary>
752         ''' <returns></returns>
753         Public Iterator Function GetEnumerator() As IEnumerator(Of NamedValue(Of String)) Implements IEnumerable(Of NamedValue(Of String)).GetEnumerator
754             Dim source As New List(Of NamedValue(Of String))(Me.__arguments)
755
756             If Not Me.BoolFlags.IsNullOrEmpty Then
757                 source += From name As String
758                           In BoolFlags
759                           Select New NamedValue(Of String)(name, "true")
760             End If
761
762             For Each x As NamedValue(Of StringIn source
763                 Yield x
764             Next
765         End Function
766
767         Public Iterator Function GetEnumerator1() As IEnumerator Implements IEnumerable.GetEnumerator
768             Yield GetEnumerator()
769         End Function
770
771         ''' <summary>
772         ''' Adds an item to the System.Collections.Generic.ICollection`1.
773         ''' </summary>
774         ''' <param name="item"></param>
775         ''' 
776         <MethodImpl(MethodImplOptions.AggressiveInlining)>
777         Public Sub Add(item As NamedValue(Of String)) Implements ICollection(Of NamedValue(Of String)).Add
778             Call __arguments.Add(item)
779         End Sub
780
781         ''' <summary>
782         ''' Add a parameter with name and its value.
783         ''' </summary>
784         ''' <param name="key"></param>
785         ''' <param name="value"></param>
786         Public Sub Add(key$, value$,
787                        Optional allowDuplicated As Boolean = False,
788                        <CallerMemberName> Optional stack$ = Nothing)
789
790             Dim item As New NamedValue(Of StringWith {
791                 .Name = key.ToLower,
792                 .Value = value,
793                 .Description = stack & "->" & NameOf(Add)
794             }
795
796             If Not allowDuplicated Then
797                 For i As Integer = 0 To __arguments.Count - 1
798                     With __arguments(i)
799                         If .Name.TextEquals(key) Then
800                             __arguments(i) = item
801                             Return
802                         End If
803                     End With
804                 Next
805
806                 ' 没有查找到需要被替换掉的下标,则直接在下面的代码之中进行添加
807             End If
808
809             __arguments += item
810         End Sub
811
812         ''' <summary>
813         ''' Clear the inner list buffer
814         ''' </summary>
815         ''' 
816         <MethodImpl(MethodImplOptions.AggressiveInlining)>
817         Public Sub Clear() Implements ICollection(Of NamedValue(Of String)).Clear
818             Call __arguments.Clear()
819         End Sub
820
821         ''' <summary>
822         ''' 只是通过比较名称来判断是否存在,值没有进行比较
823         ''' </summary>
824         ''' <param name="item"></param>
825         ''' <returns></returns>
826         Public Function Contains(item As NamedValue(Of String)) As Boolean Implements ICollection(Of NamedValue(Of String)).Contains
827             Dim LQuery% = LinqAPI.DefaultFirst(-1) _
828  _
829                 <= From obj As NamedValue(Of String)
830                    In Me.__arguments
831                    Where String.Equals(obj.Name, item.Name, StringComparison.OrdinalIgnoreCase)
832                    Select 100
833
834             Return LQuery > 50
835         End Function
836
837         <MethodImpl(MethodImplOptions.AggressiveInlining)>
838         Public Sub CopyTo(array() As NamedValue(Of String), arrayIndex As IntegerImplements ICollection(Of NamedValue(Of String)).CopyTo
839             Call __arguments.ToArray.CopyTo(array, arrayIndex)
840         End Sub
841
842         ''' <summary>
843         ''' Get the switch counts in this commandline object.(获取本命令行对象中的所定义的开关的数目)
844         ''' </summary>
845         ''' <value></value>
846         ''' <returns></returns>
847         ''' <remarks></remarks>
848         Public ReadOnly Property Count As Integer Implements ICollection(Of NamedValue(Of String)).Count
849             <MethodImpl(MethodImplOptions.AggressiveInlining)>
850             Get
851                 Return Me.__arguments.Count
852             End Get
853         End Property
854
855         Private ReadOnly Property IsReadOnly As Boolean Implements ICollection(Of NamedValue(Of String)).IsReadOnly
856             <MethodImpl(MethodImplOptions.AggressiveInlining)>
857             Get
858                 Return True
859             End Get
860         End Property
861
862         ''' <summary>
863         ''' Removes a parameter by name
864         ''' </summary>
865         ''' <param name="paramName"></param>
866         ''' <returns></returns>
867         Public Function Remove(paramName As StringAs Boolean
868             Dim LQuery = LinqAPI.DefaultFirst(Of NamedValue(Of String)) _
869  _
870                 () <= From obj As NamedValue(Of String)
871                       In Me.__arguments
872                       Where String.Equals(obj.Name, paramName, StringComparison.OrdinalIgnoreCase)
873                       Select obj
874
875             If LQuery.IsEmpty Then
876                 Return False
877             Else
878                 Call __arguments.Remove(LQuery)
879                 Return True
880             End If
881         End Function
882
883         ''' <summary>
884         ''' Removes a parameter by <see cref="NamedValue(Of String).Name"/>
885         ''' </summary>
886         ''' <param name="item"></param>
887         ''' <returns></returns>
888         ''' 
889         <MethodImpl(MethodImplOptions.AggressiveInlining)>
890         Public Function Remove(item As NamedValue(Of String)) As Boolean Implements ICollection(Of NamedValue(Of String)).Remove
891             Return Remove(item.Name)
892         End Function
893 #End Region
894
895         ''' <summary>
896         ''' 将当前的这个命令行对象之中的所有的参数值都合并到一个向量之中返回.
897         ''' (``ToArray``拓展好像是有BUG的,所以请使用这个函数来获取所有的参数信息。
898         ''' 请注意,逻辑值开关的名称会被去掉前缀)
899         ''' </summary>
900         ''' <returns></returns>
901         Public Function ToArgumentVector() As NamedValue(Of String)()
902             Dim list As New List(Of NamedValue(Of String))
903
904             list += From arg As NamedValue(Of String)
905                     In __arguments.SafeQuery
906                     Select New NamedValue(Of StringWith {
907                         .Name = arg.Name,
908                         .Value = arg.Value
909                     }
910             list += From bs As String
911                     In BoolFlags.SafeQuery
912                     Select New NamedValue(Of StringWith {
913                         .Name = bs,
914                         .Value = "True"
915                     }
916
917             Return list
918         End Function
919
920         ''' <summary>
921         ''' Open a handle for a file system object.
922         ''' </summary>
923         ''' <param name="args"></param>
924         ''' <param name="fs"></param>
925         ''' <returns></returns>
926         Public Overloads Shared Operator +(args As CommandLine, fs$) As Integer
927             Dim path As String = args(fs)
928             Return FileHandles.OpenHandle(path)
929         End Operator
930
931         ''' <summary>
932         ''' Gets the CLI parameter value.
933         ''' </summary>
934         ''' <param name="args"></param>
935         ''' <param name="name"></param>
936         ''' <returns></returns>
937         Public Overloads Shared Operator <=(args As CommandLine, name$) As String
938             If args Is Nothing Then
939                 Return Nothing
940             Else
941                 Return args(name)
942             End If
943         End Operator
944
945         <MethodImpl(MethodImplOptions.AggressiveInlining)>
946         Public Shared Operator <=(opt As String, args As CommandLine) As CommandLine
947             Return TryParse(args(opt))
948         End Operator
949
950         Public Shared Operator ^(args As CommandLine, [default] As StringAs String
951             If args Is Nothing OrElse String.IsNullOrEmpty(args.CLICommandArgvs) Then
952                 Return [default]
953             Else
954                 Return args.CLICommandArgvs
955             End If
956         End Operator
957
958         Public Shared Operator >=(opt As String, args As CommandLine) As CommandLine
959             Throw New NotSupportedException
960         End Operator
961
962         ''' <summary>
963         ''' Try get parameter value.
964         ''' </summary>
965         ''' <param name="args"></param>
966         ''' <param name="name"></param>
967         ''' <returns></returns>
968         <MethodImpl(MethodImplOptions.AggressiveInlining)>
969         Public Overloads Shared Operator -(args As CommandLine, name As StringAs String
970             Return args(name)
971         End Operator
972
973         ''' <summary>
974         ''' Try get parameter value.
975         ''' </summary>
976         ''' <param name="args"></param>
977         ''' <returns></returns>
978         <MethodImpl(MethodImplOptions.AggressiveInlining)>
979         Public Overloads Shared Operator -(args As CommandLine, null As CommandLine) As CommandLine
980             Return args
981         End Operator
982
983         <MethodImpl(MethodImplOptions.AggressiveInlining)>
984         Public Overloads Shared Operator -(args As CommandLine, name As IEnumerable(Of String)) As String
985             Return args.GetValue(name.First, name.Last)
986         End Operator
987
988         <MethodImpl(MethodImplOptions.AggressiveInlining)>
989         Public Shared Operator -(args As CommandLine) As CommandLine
990             Return args
991         End Operator
992
993         <MethodImpl(MethodImplOptions.AggressiveInlining)>
994         Public Shared Operator >(args As CommandLine, name As StringAs String
995             Return args(name)
996         End Operator
997
998         <MethodImpl(MethodImplOptions.AggressiveInlining)>
999         Public Shared Operator <(args As CommandLine, name As StringAs String
1000             Return args(name)
1001         End Operator
1002
1003         Public Shared Operator >=(args As CommandLine, name As StringAs String
1004             Throw New NotSupportedException
1005         End Operator
1006     End Class
1007 End Namespace