Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
78 lines (70 sloc) 3.54 KB
Namespace Commands
''' <summary>
''' A command which passes arguments to subcommands specified by arguments' first words.
''' </summary>
Public Class CommandSet(Of T)
Inherits PartialCommand(Of T)
Private ReadOnly _commandMap As New Dictionary(Of InvariantString, ICommand(Of T))
Private ReadOnly _help As New HelpCommand(Of T)
Private ReadOnly lock As New Object()
<ContractInvariantMethod()> Private Sub ObjectInvariant()
Contract.Invariant(_commandMap IsNot Nothing)
Contract.Invariant(_help IsNot Nothing)
End Sub
Public Sub New(Optional name As InvariantString? = Nothing)
MyBase.New(name:=If(name Is Nothing, New InvariantString("CommandSet"), name.Value),
Description:="Picks a sub-command using the first word in the argument and invokes it with the remaining argument.")
End Sub
Public Overrides Function IsArgumentPrivate(argument As String) As Boolean
Dim i = argument.IndexOf(" "c)
If i = -1 Then i = argument.Length
Dim head = argument.Substring(0, i)
Dim rest = argument.Substring(Math.Min(i + 1, argument.Length))
Dim command As ICommand(Of T) = Nothing
SyncLock lock
If Not _commandMap.TryGetValue(head, command) Then Return False
End SyncLock
Contract.Assume(command IsNot Nothing)
Return command.IsArgumentPrivate(rest)
End Function
Public ReadOnly Property CommandMap As Dictionary(Of InvariantString, ICommand(Of T))
Contract.Ensures(Contract.Result(Of Dictionary(Of InvariantString, ICommand(Of T)))() IsNot Nothing)
Return _commandMap
End Get
End Property
Public Function IncludeCommand(command As ICommand(Of T)) As IDisposable
Contract.Requires(command IsNot Nothing)
Contract.Ensures(Contract.Result(Of IDisposable)() IsNot Nothing)
SyncLock lock
If _commandMap.ContainsKey(command.Name) Then
Throw New InvalidOperationException("Command already registered to {0}.".Frmt(command.Name))
End If
_commandMap(command.Name) = command
End SyncLock
Return New DelegatedDisposable(Sub() RemoveCommand(command))
End Function
Public Sub RemoveCommand(command As ICommand(Of T))
Contract.Requires(command IsNot Nothing)
SyncLock lock
If Not _commandMap.ContainsKey(command.Name) Then Return
If Not _commandMap(command.Name) Is command Then Return
End SyncLock
End Sub
Protected NotOverridable Overrides Function PerformInvoke(target As T, user As BotUser, argumentHead As String, argumentRest As String) As Task(Of String)
Dim command As ICommand(Of T) = Nothing
SyncLock lock
If Not _commandMap.TryGetValue(argumentHead, command) Then
Throw New ArgumentException("Unrecognized Command: {0}.".Frmt(argumentHead))
End If
Contract.Assume(command IsNot Nothing)
End SyncLock
Return command.Invoke(target, user, argumentRest)
End Function
End Class
End Namespace