microsoft-visualbasic-runtime/CommandLine/Interpreters/Interpreter.vb

786 lines
33 KiB
VB.net
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#Region "Microsoft.VisualBasic::df65fc6d6d1673fb8a8dc40143fd7213, Microsoft.VisualBasic.Core\CommandLine\Interpreters\Interpreter.vb"
' Author:
'
' asuka (amethyst.asuka@gcmodeller.org)
' xie (genetics@smrucc.org)
' xieguigang (xie.guigang@live.com)
'
' Copyright (c) 2018 GPL3 Licensed
'
'
' GNU GENERAL PUBLIC LICENSE (GPL3)
'
'
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
' GNU General Public License for more details.
'
' You should have received a copy of the GNU General Public License
' along with this program. If not, see <http://www.gnu.org/licenses/>.
' /********************************************************************************/
' Summaries:
' Class Interpreter
'
' Properties: APIList, APINameList, Count, ExecuteEmptyCli, ExecuteFile
' ExecuteNotFound, Info, IsReadOnly, ListCommandInfo, Stack
' Type
'
' Constructor: (+1 Overloads) Sub New
'
' Function: __executeEmpty, __getsAllCommands, apiInvoke, Contains, CreateEmptyCLIObject
' (+3 Overloads) CreateInstance, (+3 Overloads) Execute, ExistsCommand, GetAllCommands, getAPI
' GetEnumerator, GetEnumerator1, GetPossibleCommand, Help, ListingRelated
' (+2 Overloads) Remove, SDKdocs, ToDictionary, ToString, TryGetValue
'
' Sub: (+2 Overloads) Add, AddCommand, Clear, CopyTo, (+2 Overloads) Dispose
'
'
' /********************************************************************************/
#End Region
Imports System.Reflection
Imports System.Runtime.CompilerServices
Imports System.Text
Imports Microsoft.VisualBasic.ApplicationServices.Debugging
Imports Microsoft.VisualBasic.CommandLine.ManView
Imports Microsoft.VisualBasic.CommandLine.Reflection
Imports Microsoft.VisualBasic.CommandLine.Reflection.EntryPoints
Imports Microsoft.VisualBasic.ComponentModel.Settings
Imports Microsoft.VisualBasic.Language
Imports Microsoft.VisualBasic.Language.UnixBash
Imports Microsoft.VisualBasic.Linq.Extensions
Imports Microsoft.VisualBasic.Serialization.JSON
Imports Microsoft.VisualBasic.Text
Imports Microsoft.VisualBasic.Text.Levenshtein
Imports VB = Microsoft.VisualBasic.CommandLine.InteropService.SharedORM.VisualBasic
#Const NET_45 = 0
Namespace CommandLine
''' <summary>
''' Command line interpreter for your **CLI** program.
''' (命令行解释器请注意在调试模式之下命令行解释器会在运行完命令之后暂停而Release模式之下则不会。
''' 假若在调试模式之下发现程序有很长一段时间处于cpu占用为零的静止状态则很有可能已经运行完命令并且等待
''' 回车退出)
''' </summary>
''' <remarks></remarks>
'''
<[Namespace]("Interpreter")> Public Class Interpreter
Implements IDisposable
Implements IDictionary(Of String, APIEntryPoint)
''' <summary>
''' 在添加之前请确保键名是小写的字符串
''' </summary>
Protected Friend __API_table As New Dictionary(Of String, APIEntryPoint)
Protected __rootNamespace$
#Region "Optional delegates"
''' <summary>
''' Public Delegate Function __ExecuteFile(path As String, args As String()) As Integer,
''' (<seealso cref="VisualBasic.CommandLine.ExecuteFile"/>: 假若所传入的命令行的name是文件路径解释器就会执行这个函数指针)
''' 这个函数指针一般是用作于执行脚本程序的
''' </summary>
''' <returns></returns>
Public Property ExecuteFile As ExecuteFile
''' <summary>
''' Public Delegate Function __ExecuteEmptyCli() As Integer,
''' (<seealso cref="VisualBasic.CommandLine.ExecuteEmptyCLI"/>: 假若所传入的命令行是空的,就会执行这个函数指针)
''' </summary>
''' <returns></returns>
Public Property ExecuteEmptyCli As ExecuteEmptyCLI
Public Property ExecuteNotFound As ExecuteNotFound
#End Region
''' <summary>
''' Gets the dictionary data which contains all of the available command information in this assembly module.
''' (获取从本模块之中获取得到的所有的命令行信息)
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
'''
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Public Function ToDictionary() As Dictionary(Of String, APIEntryPoint)
Return __API_table
End Function
Public Overrides Function ToString() As String
Return "CLI://" & __rootNamespace
End Function
''' <summary>
''' Execute the specific command line using this interpreter.
''' </summary>
''' <param name="args">The user input command line string.</param>
''' <returns></returns>
''' <remarks></remarks>
Public Overridable Function Execute(args As CommandLine) As Integer
If Not args.IsNullOrEmpty Then
Dim i As Integer = apiInvoke(args.Name.ToLower, {args}, args.Parameters)
#If DEBUG Then
#Else
If Stack.TextEquals("Main") Then
If DebuggerArgs.AutoPaused Then
Call Pause()
End If
End If
#End If
Return i
Else
Return __executeEmpty() ' 命令行是空的
End If
End Function
''' <summary>
''' 命令行是空的话,假若<see cref="ExecuteEmptyCli"/>不是空值的话,会优先执行<see cref="ExecuteEmptyCli"/>函数指针
''' 否则打印出所有的命令名称信息
''' </summary>
''' <returns></returns>
Private Function __executeEmpty() As Integer
If Not ExecuteEmptyCli Is Nothing Then
Try
Return _ExecuteEmptyCli()
Catch ex As Exception
Call App.LogException(ex)
Call ex.PrintException
End Try
Return -100
Else
' 当用户什么也不输入的时候,打印出所有的命令名称帮助信息
Return Help("")
End If
End Function
''' <summary>
''' The interpreter runs all of the command from here.(所有的命令行都从这里开始执行)
''' </summary>
''' <param name="commandName"></param>
''' <param name="argvs">就只有一个命令行对象</param>
''' <param name="help_argvs"></param>
''' <returns></returns>
Private Function apiInvoke(commandName$, argvs As Object(), help_argvs$()) As Integer
Dim CLI As CommandLine = DirectCast(argvs(Scan0), CommandLine)
If __API_table.ContainsKey(commandName) Then _
Return __API_table(commandName).Execute(argvs)
If "??vars".TextEquals(commandName) Then
Dim vars = App.GetAppVariables
Call Console.WriteLine()
Call Console.WriteLine(PS1.Fedora12.ToString)
Call Console.WriteLine()
Call Console.WriteLine($"Print environment variables for {GetType(App).FullName}:")
Call Console.WriteLine(ConfigEngine.Prints(vars))
Return 0
ElseIf "??history".TextEquals(commandName) Then
Dim logs$ = (App.LogErrDIR.ParentPath & "/.shells.log")
With DirectCast(argvs(Scan0), CommandLine)
If .Parameters.IsNullOrEmpty Then
Call Console.WriteLine()
Call logs.ReadAllText.EchoLine
Call Console.WriteLine()
Else
With .ParameterList.First
Select Case .Name.ToLower
Case "/clear"
Call New Byte() {}.FlushStream(logs)
Case "/search"
Dim term$ = .Value
Call Console.WriteLine()
Call logs.IterateAllLines _
.Where(Function(line)
Return InStr(line, term, CompareMethod.Text) > 0
End Function) _
.JoinBy(vbCrLf) _
.EchoLine
Call Console.WriteLine()
Case Else
Console.WriteLine("Unknown command!")
End Select
End With
End If
End With
Return 0
ElseIf String.Equals(commandName, "?") OrElse commandName = "??" OrElse commandName.TextEquals("--help") Then
If help_argvs.IsNullOrEmpty Then
Return Help("")
Else
Return Help(help_argvs.First)
End If
ElseIf InStr(commandName, "??") = 1 Then ' 支持类似于R语言里面的 ??帮助命令
commandName = Mid(commandName, 3) ' 去除前面的两个??问号得到查询的term
Return Help(commandName)
ElseIf String.Equals(commandName, "~") Then
' 打印出应用程序的位置linux里面的HOME
Call Console.WriteLine(App.ExecutablePath)
Return 0
ElseIf String.Equals(commandName, "man") Then
' 默认是分段打印帮助信息,假若加上了 --print参数的话则才会一次性的打印所有的信息出来
Dim doc As String = SDKdocs()
Dim output$ = CLI("/out") Or "./"
If Not CLI.GetBoolean("--file") Then
If CLI.GetBoolean("--print") Then
Call Console.WriteLine(doc)
Else
Call SDKManual.LaunchManual(CLI:=Me)
End If
Else
' 只会写文件而不会在终端打开帮助窗口
End If
Return doc.SaveTo($"{output}/{App.AssemblyName}.md", Encoding.UTF8).CLICode
ElseIf String.Equals(commandName, "/linux-bash", StringComparison.OrdinalIgnoreCase) Then
Return BashShell()
ElseIf String.Equals(commandName, "/CLI.dev", StringComparison.OrdinalIgnoreCase) Then
Dim namespace$ = CLI("/namespace") Or "CLI"
Dim vb$ = New VB(App:=Me, [namespace]:=[namespace]).GetSourceCode
If CLI.IsTrue("---echo") Then
Console.WriteLine(vb)
Return 0
Else
Dim sourcefile$ = $"{App.HOME}/{Type.Assembly.CodeBase.BaseName}.vb"
Return vb _
.SaveTo(sourcefile, Encodings.UTF8WithoutBOM.CodePage) _
.CLICode
End If
Else
' 命令行的名称和上面的都不符合,但是可以在文件系统之中找得到一个相应的文件,则执行文件句柄
If (commandName.FileExists OrElse commandName.DirectoryExists) AndAlso Not Me.ExecuteFile Is Nothing Then
Try
App.InputFile = commandName
Return ExecuteFile()(path:=commandName, args:=DirectCast(argvs(Scan0), CommandLine))
Catch ex As Exception
ex = New Exception("Execute file failure!", ex)
ex = New Exception(argvs(Scan0).ToString, ex)
Call App.LogException(ex)
Call ex.PrintException
End Try
Return -120
ElseIf Not ExecuteNotFound Is Nothing Then
Try
Return ExecuteNotFound()(DirectCast(argvs(Scan0), CommandLine))
Catch ex As Exception
ex = New Exception("Execute not found failure!", ex)
ex = New Exception(argvs(Scan0).ToString, ex)
Call App.LogException(ex)
Call ex.PrintException
End Try
Return -1000
Else
Dim list$() = Me.ListingRelated(commandName)
If list.IsNullOrEmpty Then
Call Console.WriteLine(BAD_COMMAND_NAME, commandName)
Call Console.WriteLine()
Call Console.WriteLine(PS1.Fedora12.ToString & " " & DirectCast(argvs(Scan0), CommandLine).ToString)
Else
Call listingCommands(list, commandName)
End If
End If
End If
Return -1
End Function
Const BAD_COMMAND_NAME$ = "Bad command, no such a command named ""{0}"", ? for command list or ""man"" for all of the commandline detail informations."
''' <summary>
''' Generate the sdk document for the target program assembly.(生成目标应用程序的命令行帮助文档markdown格式的)
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
'''
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Public Function SDKdocs() As String
Return Me.MarkdownDoc
End Function
''' <summary>
''' Process the command option arguments of the main function:
''' <code>Public Function Main(argvs As String()) As Integer
''' </code>
''' </summary>
''' <param name="CommandLineArgs">The cli command line parameter string value collection.</param>
''' <returns></returns>
''' <remarks></remarks>
Public Function Execute(CommandLineArgs As String()) As Integer
Dim CommandName As String = CommandLineArgs.First
Dim argvs As String() = CommandLineArgs.Skip(1).ToArray
Dim i As Integer = apiInvoke(CommandName, argvs, help_argvs:=argvs)
#If DEBUG Then
If Not App.GetVariable("pause.disable").ParseBoolean = True Then
Call Pause()
End If
#Else
If Stack.TextEquals("Main") Then
If AutoPaused Then
Call Pause()
End If
End If
#End If
Return i
End Function
Public Function Execute(CommandName As String, args As String()) As Integer
Return apiInvoke(CommandName.ToLower, args, help_argvs:=args)
End Function
''' <summary>
''' Add a command in current cli interpreter.(x向当前的这个CLI命令行解释器之中添加一个命令)
''' </summary>
''' <param name="Command"></param>
''' <remarks></remarks>
Public Sub AddCommand(Command As APIEntryPoint)
Dim key$ = Command.Name.ToLower
If Not __API_table.ContainsKey(key) Then
Call __API_table.Add(key, Command)
End If
End Sub
''' <summary>
''' Gets the help information of a specific command using its name property value.(获取某一个命令的帮助信息)
''' </summary>
''' <param name="CommandName">If the paramteer command name value is a empty string then this function
''' will list all of the commands' help information.(假若本参数为空则函数会列出所有的命令的帮助信息)</param>
''' <returns>Error code, ZERO for no error</returns>
''' <remarks></remarks>
<ExportAPI("?", Usage:="? [CommandName]", Info:="Show Application help", Example:="? example_commandName")>
Public Function Help(CommandName As String) As Integer
If String.IsNullOrEmpty(CommandName) Then
' List all commands when command name is empty.
Call Console.WriteLine(HelpSummary(False))
Else
' listing the help for specific command name
Call PrintCommandHelp(CommandName)
End If
Return 0
End Function
''' <summary>
''' Returns the command entry info list array.
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public ReadOnly Property ListCommandInfo As EntryPoints.APIEntryPoint()
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Get
Return __API_table.Values.ToArray
End Get
End Property
Public ReadOnly Property Stack As String
Public ReadOnly Property Info As [Namespace]
''' <summary>
'''
''' </summary>
''' <param name="type">A module or a class which contains some shared method for the command entry.
''' (包含有若干使用<see cref="Reflection.ExportAPIAttribute"></see>进行标记的命令行执行入口点的Module或者Class对象类型
''' 可以使用 Object.GetType/GetType 关键词操作来获取所需要的类型信息)</param>
''' <remarks></remarks>
Sub New(type As Type, <CallerMemberName> Optional caller As String = Nothing)
For Each cInfo As APIEntryPoint In __getsAllCommands(type, False)
If __API_table.ContainsKey(cInfo.Name.ToLower) Then
Throw New Exception(cInfo.Name & " is duplicated with other command!")
Else
Call __API_table.Add(cInfo.Name.ToLower, cInfo)
End If
Next
Me.__rootNamespace = type.Namespace
Me._Stack = caller
Me._Type = type
Me._Info = type.NamespaceEntry(True)
End Sub
''' <summary>
''' The CLI API container Module/Class type information.(申明这个解释器的命令行API容器类型)
''' </summary>
''' <returns></returns>
Public ReadOnly Property Type As Type
''' <summary>
''' 导出所有符合条件的静态方法
''' </summary>
''' <param name="Type"></param>
''' <param name="[Throw]"></param>
''' <returns></returns>
Protected Overridable Function __getsAllCommands(Type As Type, Optional [Throw] As Boolean = True) As List(Of EntryPoints.APIEntryPoint)
Return GetAllCommands(Type, [Throw])
End Function
''' <summary>
''' 导出所有符合条件的静态方法,请注意,在这里已经将外部的属性标记和所属的函数的入口点进行连接了
''' </summary>
''' <param name="type"></param>
''' <param name="[Throw]"></param>
''' <returns></returns>
Public Shared Function GetAllCommands(type As Type, Optional [Throw] As Boolean = True) As List(Of EntryPoints.APIEntryPoint)
If type Is Nothing Then
Return New List(Of APIEntryPoint)
End If
Dim methods As MethodInfo() = type.GetMethods(BindingFlags.Public Or BindingFlags.Static)
Dim commandAttribute As Type = GetType(ExportAPIAttribute)
Dim commandsInfo = LinqAPI.MakeList(Of APIEntryPoint) <=
_
From methodInfo As MethodInfo
In methods
Let commandInfo As APIEntryPoint =
getAPI(methodInfo, commandAttribute, [Throw])
Where Not commandInfo Is Nothing
Select commandInfo
Order By commandInfo.Name Ascending
Return commandsInfo
End Function
''' <summary>
''' 从方法定义<see cref="MethodInfo"/>之中解析出命令行的定义
''' </summary>
''' <param name="methodInfo"></param>
''' <param name="commandAttribute"></param>
''' <param name="[throw]"></param>
''' <returns></returns>
Private Shared Function getAPI(methodInfo As MethodInfo, commandAttribute As Type, [throw] As Boolean) As APIEntryPoint
Dim cmdAttr As ExportAPIAttribute = Nothing
Dim commandInfo As APIEntryPoint
Try
Dim attrs As Object() = methodInfo.GetCustomAttributes(commandAttribute, False)
If attrs.IsNullOrEmpty Then
Return Nothing
End If
cmdAttr = DirectCast(attrs(0), ExportAPIAttribute)
commandInfo = New APIEntryPoint(cmdAttr, methodInfo, [throw]) ' 在这里将外部的属性标记和所属的函数的入口点进行连接
If cmdAttr.Info.StringEmpty Then
cmdAttr.Info = methodInfo.Description ' 帮助信息的获取兼容系统的Description方法
End If
If cmdAttr.Usage.StringEmpty Then
cmdAttr.Usage = methodInfo.Usage
End If
If cmdAttr.Example.StringEmpty Then
cmdAttr.Example = methodInfo.ExampleInfo
End If
Return commandInfo
Catch ex As Exception
If Not cmdAttr Is Nothing Then
ex = New Exception("This command API can not be imports: " & cmdAttr.GetJson, ex)
ex = New Exception(CheckNotice, ex)
End If
Call App.LogException(New Exception(methodInfo.FullName(True), ex))
Call ex.PrintException
Return Nothing
End Try
End Function
Const CheckNotice As String = "Please checks for the export api definition on your CLI interface function."
''' <summary>
''' Create an empty cli command line interpreter object which contains no commands entry.
''' (创建一个没有包含有任何命令入口点的空的CLI命令行解释器)
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
'''
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Public Shared Function CreateEmptyCLIObject() As Interpreter
Return New Interpreter(GetType(Interpreter))
End Function
''' <summary>
''' Create a new interpreter instance from a specific type information.
''' (从目标类型之中构造出一个命令行解释器)
''' </summary>
''' <param name="Type"></param>
''' <returns></returns>
''' <remarks></remarks>
<MethodImpl(MethodImplOptions.AggressiveInlining)>
<ExportAPI("CreateObject")>
Public Shared Function CreateInstance(type As Type) As Interpreter
Return New Interpreter(type)
End Function
''' <summary>
''' Create a new interpreter instance using the specific type information.
''' (使用所制定的目标类型信息构造出一个CLI命令行解释器)
''' </summary>
''' <typeparam name="T"></typeparam>
''' <returns></returns>
''' <remarks></remarks>
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Public Shared Function CreateInstance(Of T As Class)() As Interpreter
Return New Interpreter(type:=GetType(Type))
End Function
#If NET_40 = 0 Then
''' <summary>
''' Create a new interpreter instance from a specific dll/exe path, this program assembly file should be a standard .NET assembly.
''' (从一个标准的.NET程序文件之中构建出一个命令行解释器)
''' </summary>
''' <param name="assmPath">DLL/EXE file path.(标准的.NET程序集文件的文件路径)</param>
''' <returns></returns>
''' <remarks></remarks>
'''
<ExportAPI("rundll")>
Public Shared Function CreateInstance(assmPath As String) As Interpreter
Dim assembly As Assembly = Assembly.LoadFrom(assmPath)
Dim dllMain As Type = GetType(RunDllEntryPoint)
Dim main As Type = LinqAPI.DefaultFirst(Of Type) _
_
() <= From [mod] As Type
In assembly.DefinedTypes
Let attributes As Object() = [mod].GetCustomAttributes(dllMain, inherit:=False)
Where Not attributes Is Nothing AndAlso
attributes.Length = 1
Select [mod]
If main Is Nothing Then
Return Nothing ' 没有找到执行入口点
Else
Return New Interpreter(main)
End If
End Function
#End If
#Region "IDisposable Support"
Private disposedValue As Boolean ' To detect redundant calls
' IDisposable
Protected Sub Dispose(disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
' TODO: dispose managed state (managed objects).
End If
' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
' TODO: set large fields to null.
End If
Me.disposedValue = True
End Sub
' TODO: override Finalize() only if Dispose( disposing As Boolean) above has code to free unmanaged resources.
'Protected Overrides Sub Finalize()
' ' Do not change this code. Put cleanup code in Dispose( disposing As Boolean) above.
' Dispose(False)
' MyBase.Finalize()
'End Sub
' This code added by Visual Basic to correctly implement the disposable pattern.
Public Sub Dispose() Implements IDisposable.Dispose
' Do not change this code. Put cleanup code in Dispose(disposing As Boolean) above.
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
#Region "Implements System.Collections.Generic.IReadOnlyDictionary(Of String, CommandInfo)"
Public Iterator Function GetEnumerator() As IEnumerator(Of KeyValuePair(Of String, EntryPoints.APIEntryPoint)) Implements IEnumerable(Of KeyValuePair(Of String, EntryPoints.APIEntryPoint)).GetEnumerator
For Each key As String In Me.__API_table.Keys
Yield New KeyValuePair(Of String, EntryPoints.APIEntryPoint)(key, Me.__API_table(key))
Next
End Function
Public Iterator Function GetEnumerator1() As IEnumerator Implements IEnumerable.GetEnumerator
Yield Me.GetEnumerator
End Function
Public Sub Add(item As KeyValuePair(Of String, EntryPoints.APIEntryPoint)) Implements ICollection(Of KeyValuePair(Of String, EntryPoints.APIEntryPoint)).Add
Call __API_table.Add(item.Key, item.Value)
End Sub
''' <summary>
''' Clear the hash table of the cli command line interpreter command entry points.(清除本CLI解释器之中的所有的命令行执行入口点的哈希数据信息)
''' </summary>
''' <remarks></remarks>
Public Sub Clear() Implements ICollection(Of KeyValuePair(Of String, EntryPoints.APIEntryPoint)).Clear
Call __API_table.Clear()
End Sub
Public Function Contains(item As KeyValuePair(Of String, EntryPoints.APIEntryPoint)) As Boolean Implements ICollection(Of KeyValuePair(Of String, EntryPoints.APIEntryPoint)).Contains
Return __API_table.Contains(item)
End Function
Public Sub CopyTo(array() As KeyValuePair(Of String, EntryPoints.APIEntryPoint), arrayIndex As Integer) Implements ICollection(Of KeyValuePair(Of String, EntryPoints.APIEntryPoint)).CopyTo
Call __API_table.ToArray.CopyTo(array, arrayIndex)
End Sub
''' <summary>
''' Gets the command counts in current cli interpreter.(返回本CLI命令行解释器之中所包含有的命令的数目)
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public ReadOnly Property Count As Integer Implements ICollection(Of KeyValuePair(Of String, EntryPoints.APIEntryPoint)).Count
Get
Return Me.__API_table.Count
End Get
End Property
Public ReadOnly Property IsReadOnly As Boolean Implements ICollection(Of KeyValuePair(Of String, EntryPoints.APIEntryPoint)).IsReadOnly
Get
Return False
End Get
End Property
Public Function Remove(item As KeyValuePair(Of String, EntryPoints.APIEntryPoint)) As Boolean Implements ICollection(Of KeyValuePair(Of String, EntryPoints.APIEntryPoint)).Remove
Return __API_table.Remove(item.Key)
End Function
Public Sub Add(key As String, value As EntryPoints.APIEntryPoint) Implements IDictionary(Of String, EntryPoints.APIEntryPoint).Add
Call __API_table.Add(key, value)
End Sub
''' <summary>
''' The target command line command is exists in this cli interpreter using it name property?(判断目标命令行命令是否存在于本CLI命令行解释器之中)
''' </summary>
''' <param name="CommandName">The command name value is not case sensitive.(命令的名称对大小写不敏感的)</param>
''' <returns></returns>
''' <remarks></remarks>
Public Function ExistsCommand(CommandName As String) As Boolean Implements IDictionary(Of String, EntryPoints.APIEntryPoint).ContainsKey
Return Me.__API_table.ContainsKey(CommandName.ToLower)
End Function
''' <summary>
'''
''' </summary>
''' <param name="key">调用前需要转换为小写字母的形式</param>
''' <returns></returns>
Default Public Overloads Property Item(key As String) As EntryPoints.APIEntryPoint Implements IDictionary(Of String, EntryPoints.APIEntryPoint).Item
Get
Return Me.__API_table(key)
End Get
Set(value As EntryPoints.APIEntryPoint)
'DO NOTHING
End Set
End Property
Public Function GetPossibleCommand(name As Value(Of String)) As APIEntryPoint
Dim commands = ListingRelated(name)
If commands.Length = 0 Then
Return Nothing
Else
Return __API_table(commands.First.ToLower)
End If
End Function
''' <summary>
''' 列举出所有可能的命令
''' </summary>
''' <param name="query">模糊匹配</param>
''' <returns></returns>
Public Function ListingRelated(query$) As String()
Dim key As New LevenshteinString(query.ToLower)
Dim LQuery = From x As String
In __API_table.Keys.AsParallel
Let compare = key Like x
Where Not compare Is Nothing AndAlso
compare.Score > 0.3
Select compare.Score,
x
Order By Score Descending
Dim levenshteins = LQuery _
.Select(Function(x) x.x) _
.AsList
levenshteins += __API_table _
.Keys _
.Where(Function(s)
Return InStr(s, query, CompareMethod.Text) > 0 OrElse
InStr(query, s, CompareMethod.Text) > 0
End Function)
Return levenshteins _
.Distinct _
.Select(Function(name)
Return __API_table(name).Name
End Function) _
.ToArray
End Function
''' <summary>
''' List all of the command line entry point name which were contains in this cli interpreter.
''' (列举出本CLI命令行解释器之中的所有的命令行执行入口点的名称)
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public ReadOnly Property APINameList As ICollection(Of String) Implements IDictionary(Of String, EntryPoints.APIEntryPoint).Keys
Get
Return Me.__API_table.Keys
End Get
End Property
Public Function Remove(CommandName As String) As Boolean Implements IDictionary(Of String, EntryPoints.APIEntryPoint).Remove
Return __API_table.Remove(CommandName)
End Function
Public Function TryGetValue(key As String, ByRef value As EntryPoints.APIEntryPoint) As Boolean Implements IDictionary(Of String, EntryPoints.APIEntryPoint).TryGetValue
Return Me.__API_table.TryGetValue(key, value)
End Function
''' <summary>
''' 当前的解释器内所容纳的所有的CLI API列表
''' </summary>
''' <returns></returns>
Public ReadOnly Property APIList As ICollection(Of EntryPoints.APIEntryPoint) Implements IDictionary(Of String, EntryPoints.APIEntryPoint).Values
Get
Return Me.__API_table.Values
End Get
End Property
#End Region
End Class
End Namespace