Skip to content

Instantly share code, notes, and snippets.

@pigeonhands
Created August 17, 2017 04:29
Show Gist options
  • Save pigeonhands/92fb20cc7b28d23931ba6ea200a31360 to your computer and use it in GitHub Desktop.
Save pigeonhands/92fb20cc7b28d23931ba6ea200a31360 to your computer and use it in GitHub Desktop.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Assets.scripts {
class ActionHandler : IEnumerable {
/// <summary>
/// List of inner commands
/// e.g.
/// the "left" in "move left"
/// </summary>
private List<ActionHandler> SubHandlers = new List<ActionHandler>();
/// <summary>
/// handler for actions with no \adverb\
/// e.g.
/// "look"
/// </summary>
private ActionHandler DefaultHandler = null;
/// <summary>
/// Keywords that is used to identify the command
/// e.g.
/// "move" and "go"
/// </summary>
public string[] Triggers { get; private set; }
/// <summary>
/// new instance of an action handler and setting the <see cref="Triggers"/>
/// </summary>
/// <param name="commandTriggers"><see cref="Triggers"/> to be set</param>
public ActionHandler(params string[] commandTriggers) {
Triggers = commandTriggers;
}
/// <summary>
/// new instance of an action with no <see cref="Triggers"/>
/// </summary>
public ActionHandler() : this(string.Empty) {
}
/// <summary>
/// Add a subcommand/adverb
///
/// e.g.
/// "up" in "look up"
/// </summary>
/// <param name="handler">The subhandler.</param>
public void Add(ActionHandler handler) {
SubHandlers.Add(handler);
}
/// <summary>
/// Add a method handler for an action
/// </summary>
/// <param name="cmd"><see cref="Triggers"/> for command to be identified by</param>
/// <param name="callback">Method callback</param>
public void Add(string[] cmd, Action<string> callback) {
SubHandlers.Add(new ActionMethodHandler(cmd, callback));
}
/// <summary>
/// Add a method handler for an action with a single trigger
/// </summary>
/// <param name="cmd">The trigger</param>
/// <param name="callback">method callback</param>
public void Add(string cmd, Action<string> callback) {
Add(new string[] { cmd }, callback);
}
/// <summary>
/// Add a default method handler for when no adverb/subcommand is specified
/// </summary>
/// <param name="callback">method callback</param>
public void Add(Action<string> callback) {
DefaultHandler = new ActionMethodHandler(new string[] { string.Empty }, callback);
}
/// <summary>
/// Handle the command input
/// </summary>
/// <param name="subcommands"></param>
/// <returns></returns>
public virtual bool Handle(string subcommands) {
//Split the input string by " " but only on the first space. commandParts length will only ever be 1 or 2
//e.g.
//"move up and down" -> "move", "up and down"
string[] commandParts = subcommands.Split(new char[] { ' ' }, 2);
string command = commandParts[0].Trim();
//?: = ternary operator. (if) ? (then) : (else)
//So, if commandParts has a second item, set commandParameters to that item, else set it to ""
string commandParameters = commandParts.Length == 2 ? commandParts[1].Trim() : string.Empty;
//Find the handler in the SubHandlers where one of its Triggers macthes the command
ActionHandler handler = SubHandlers.FirstOrDefault(x => x.Triggers.Contains(command));
if (handler != null) {
//If a subhandler was found, run its Handle method with the rest of the command
return handler.Handle(commandParameters);
} else {
//No handler found. Is there a default handler set?
if (DefaultHandler != null && string.IsNullOrEmpty(commandParameters)) {
//Ye, call it
return DefaultHandler.Handle(commandParameters);
} else {
//No
return false;
}
}
}
public IEnumerator GetEnumerator() { //Implimenting IEnumerable interface. Required for smooth interaction with the "Add" method.
return SubHandlers.GetEnumerator();
}
#region " Private action handlers for methods "
/// <summary>
/// wraps a method with a void(string) signature to a ActionHandler so that it can be added to another handlers SubHandlers
/// </summary>
private class ActionMethodHandler : ActionHandler {
//Methdo that will be called when this method is Handled
private Action<string> handleCallBack;
/// <summary>
/// Create a new ActionMethodHandler
/// "base" is the constructor of the base type. In this case its ActionHandler
/// </summary>
/// <param name="cmd">the triggers</param>
/// <param name="_handleCallBack">the method to call</param>
public ActionMethodHandler(string[] cmd, Action<string> _handleCallBack) : base(cmd) {
handleCallBack = _handleCallBack;
}
/// <summary>
/// Override ActionHandler's Handle method.
/// </summary>
/// <param name="subcommands"></param>
/// <returns></returns>
public override bool Handle(string subcommands) {
if (handleCallBack != null) { //Has a method atcualy been set?
handleCallBack(subcommands); //Call it
}
return true;
}
}
#endregion
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment