using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Tofvesson.Crypto; namespace Server { public sealed class Command { public string Name { get; } public Action>> OnInvoke { get; set; } private List parameters = new List(); public string CommandString { get { StringBuilder builder = new StringBuilder(Name); foreach (var p in parameters) { builder.Append(' '); if (p.optional) builder.Append('{'); builder.Append('-').Append(p.flag); if (p.type != Parameter.ParamType.NONE) builder.Append(' ').Append(p.name); if (p.optional) builder.Append('}'); } return builder.ToString(); } } public Command(string name) => Name = name; public Command WithParameter(string pName, char flag, Parameter.ParamType type, bool optional = false) { if (GetByFlag(flag) != null) throw new Exception("Cannot have two parameters with the same flag"); parameters.Add(new Parameter(pName, flag, type, optional)); return this; } public Command WithParameter(Parameter parameter) { if (GetByFlag(parameter.flag) != null) throw new Exception("Cannot have two parameters with the same flag"); parameters.Add(parameter); return this; } public Command SetAction(Action>> action) { OnInvoke = action; return this; } public Command SetAction(Action a) => SetAction((_, __) => a?.Invoke()); public bool Matches(string cmd) => cmd.Split(' ')[0].EqualsIgnoreCase(Name); public Parameter? GetByFlag(char flag) { foreach (var param in parameters) if (param.flag == flag) return param; return null; } public bool Invoke(string cmd) { if (!Matches(cmd)) return false; string[] parts = cmd.Split(' '); List> p = new List>(); StringBuilder reconstruct = new StringBuilder(); Parameter? p1 = null; bool wasFlag = true; for (int i = 1; i(reconstruct.ToString(), p1.Value)); reconstruct.Length = 0; wasFlag = true; } if((p1 = GetByFlag(parts[i][1])) == null) { ShowError(); return false; } } else { if(p1!=null && p1.Value.type == Parameter.ParamType.NONE) { ShowError(); return false; } if (!wasFlag) reconstruct.Append(' '); reconstruct.Append(parts[i]); wasFlag = false; } } if (reconstruct.Length != 0 || (p1 != null && !p.HasFlag(p1.Value.flag))) { if ( p1 == null || (p1.Value.type == Parameter.ParamType.NUMBER && !double.TryParse(reconstruct.ToString(), out double _)) || (p1.Value.type == Parameter.ParamType.BOOLEAN && !bool.TryParse(reconstruct.ToString(), out bool _)) ) { ShowError(); return true; } p.Add(new Tuple(reconstruct.ToString(), p1.Value)); reconstruct.Length = 0; } foreach (var check in parameters) if (check.optional) continue; else { foreach (var check1 in p) if (check1.Item2.Equals(check)) goto found; // Could not find a match for a required parameter ShowError(); return false; found: { } } OnInvoke?.Invoke(this, p); return true; } public void ShowError() => Output.Error($"Usage: {CommandString}", true, false); } public static class Commands { public static string GetFlag(this List> l, char flag) { foreach (var flagcheck in l) if (flagcheck.Item2.flag == flag) return flagcheck.Item1; return null; } public static bool HasFlag(this List> l, char flag) { foreach (var flagcheck in l) if (flagcheck.Item2.flag == flag) return true; return false; } } }