private CommandNode CreateOrGetNodeFromClass(Type type) { string[] namespaces = type.FullName.Split('.'); int matchingIndex = 0; CommandNode node = this.parser.Root; for (int i = 0; i < node.children.Count; i++) { if (node.children[i].name == namespaces[matchingIndex]) { ++matchingIndex; if (namespaces.Length == matchingIndex) { return(node.children[i]); } node = node.children[i]; i = -1; } } while (matchingIndex < namespaces.Length) { CommandNode subNode = new CommandNode(null, namespaces[matchingIndex], string.Empty); this.SortedAdd(node, subNode); node = subNode; ++matchingIndex; } return(node); }
public CommandNode[] GetMatchingChildren(string[] commands) { List <CommandNode> result = new List <CommandNode>(); int highestNode = 0; CommandNode highestCommand = this.GetHighestValidCommand(commands, false, out highestNode); // Whereas there is no highest input or it is empty. if (highestNode >= commands.Length) { for (int i = 0; i < highestCommand.children.Count; i++) { result.Add(highestCommand.children[i]); } } else if (highestCommand != null) { for (int i = 0; i < highestCommand.children.Count; i++) { if (highestCommand.children[i].name.StartsWith(commands[highestNode], StringComparison.OrdinalIgnoreCase) == true) { result.Add(highestCommand.children[i]); } } } return(result.ToArray()); }
private void BrowseOut(ByteBuffer buffer, CommandNode node) { buffer.AppendUnicodeString(node.name); buffer.AppendUnicodeString(node.description); buffer.Append(node.IsLeaf); buffer.Append(node.children.Count); for (int i = 0; i < node.children.Count; i++) { this.BrowseOut(buffer, node.children[i]); } }
private void SortedAdd(CommandNode parent, CommandNode child) { for (int i = 0; i < parent.children.Count; i++) { //if (string.Compare(parent.children[i].name, child.name) >= 0) if (parent.children[i].name.CompareTo(child.name) >= 0) { parent.children.Insert(i, child); return; } } parent.children.Add(child); }
protected CommandNode GetHighestValidCommand(string[] inputs, bool matchExact, out int i) { CommandNode highestCommand = this.root; List <CommandNode> matching = new List <CommandNode>(); int max = (matchExact == true) ? inputs.Length : inputs.Length - 1; for (i = 0; i < max; i++) { matching.Clear(); if (inputs[i] == string.Empty) { return(null); } for (int j = 0; j < highestCommand.children.Count; j++) { if (i + 1 == inputs.Length) { if ((matchExact == true && highestCommand.children[j].name == inputs[i]) || (matchExact == false && highestCommand.children[j].name.StartsWith(inputs[i]) == true)) { matching.Add(highestCommand.children[j]); } } else if (highestCommand.children[j].name == inputs[i]) { matching.Add(highestCommand.children[j]); } } if (matching.Count == 0) { return(null); } if (matching.Count == 1 && matching[0].name == inputs[i]) { highestCommand = matching[0]; } else { break; } } return(highestCommand); }
/// <summary>Removes nodes that does not contain any leaf commands.</summary> /// <param name="node"></param> /// <returns></returns> private bool CleanEmptyNodes(CommandNode node) { bool empty = true; for (int i = 0; i < node.children.Count; i++) { if (node.children[i].IsLeaf == false && this.CleanEmptyNodes(node.children[i]) == true) { node.children.RemoveAt(i); --i; continue; } else { empty = false; } } return(empty); }
/// <summary></summary> /// <param name="input"></param> /// <param name="result"></param> /// <returns></returns> public ExecResult Exec(string input, ref string result) { for (int j = 0; j < CommandParser.DefaultHelpCommands.Length; j++) { if (CommandParser.DefaultHelpCommands[j].Equals(input) == true) { StringBuilder buffer = Utility.GetBuffer(); buffer.AppendLine("Usage:"); buffer.AppendLine("command.subCommand"); buffer.AppendLine("command.subCommand arg1"); buffer.AppendLine("command.subCommand arg1 \"foo bar\" 12 3.45"); buffer.AppendLine(); buffer.AppendLine("Commands available:"); for (int k = 0; k < this.root.children.Count; k++) { buffer.AppendLine(this.root.children[k].name); } buffer.Length -= Environment.NewLine.Length; result = Utility.ReturnBuffer(buffer); return(ExecResult.Success); } } string[] commands; string[] arguments; this.ParseInput(input, out commands, out arguments); int i; CommandNode command = this.GetHighestValidCommand(commands, true, out i); this.historic.Add(input); this.currentHistoric = -1; if (commands.Length != i) { result = input + " is not recognized as a valid command. Type \"" + string.Join("\", \"", CommandParser.DefaultHelpCommands) + "\" to display usage."; return(ExecResult.InvalidCommand); } if (command.IsLeaf == false) { result = input + " is not recognized as a valid command. Type \"" + string.Join("\", \"", CommandParser.DefaultHelpCommands) + "\" to display usage."; return(ExecResult.NonLeafCommand); } try { result = command.GetSetInvoke(arguments); } catch (ArgumentException ex) { if (ex.Message.StartsWith("Set Method not found") == true) { result = "Member is readonly."; } else { result = ex.Message; } return(ExecResult.InvalidCommand); } catch (Exception ex) { result = ex.Message; return(ExecResult.InvalidCommand); } return(ExecResult.Success); }
public void RemoveRootCommand(CommandNode command) { this.root.RemoveChild(command); }
public void AddRootCommand(CommandNode command) { this.root.AddChild(command); }
public void SetRoot(CommandNode root) { this.root = root; }
public CommandParser() { this.root = new CommandNode(null, "root", string.Empty); this.historic = new List <string>(); this.currentHistoric = -1; }
public void RemoveChild(CommandNode command) { this.invalidate |= Invalidate.Children; this.children.Remove(command); }
public void AddChild(CommandNode command) { this.invalidate |= Invalidate.Children; this.children.Add(command); }
private void InitializeCommands() { if (this.rootCommands != null && this.rootCommands.Length > 0) { for (int i = 0; i < this.rootCommands.Length; i++) { if (string.IsNullOrEmpty(this.rootCommands[i].alias) == true) { InternalNGDebug.Log(Errors.CLI_RootCommandEmptyAlias, "Root command #" + i + " as an empty alias."); continue; } if (this.rootCommands[i].behaviour == null) { InternalNGDebug.Log(Errors.CLI_RootCommandNullBehaviour, "Root command \"" + this.rootCommands[i].alias + "\" has no behaviour."); continue; } ICommandHelper helper = this.rootCommands[i].behaviour as ICommandHelper; string description = string.Empty; if (helper != null) { description = helper.Helper; } this.parser.AddRootCommand(new BehaviourCommand(this.rootCommands[i].alias, description, this.rootCommands[i].behaviour)); } } if (this.includeStaticTypes == true) { StringBuilder buffer = Utility.GetBuffer(); foreach (Type type in Utility.EachAllSubClassesOf(typeof(object))) { if (type.IsEnum == true || type.Name.StartsWith("<Private") == true || (type.Name == "Consts" && type.Namespace == null)) // This particular hidden type is redundant as f**k, and it has no namespace! { continue; } FieldInfo[] fields = type.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); PropertyInfo[] properties = type.GetProperties(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (fields.Length > 0 || properties.Length > 0) { CommandNode node = this.CreateOrGetNodeFromClass(type); for (int i = 0; i < fields.Length; i++) { try { this.SortedAdd(node, new MemberCommand(new FieldModifier(fields[i]), null)); } catch (NotSupportedMemberTypeException ex) { if (buffer.Length == 0) { buffer.Append("#" + Errors.CLI_UnsupportedPropertyType + " - "); } buffer.AppendLine("Field \"" + ex.member.Name + "\" of type \"" + ex.member.Type.Name + "\" from \"" + ex.member.MemberInfo.DeclaringType.Name + "\" is unsupported."); } } for (int i = 0; i < properties.Length; i++) { try { this.SortedAdd(node, new MemberCommand(new PropertyModifier(properties[i]), null)); } catch (NotSupportedMemberTypeException ex) { if (buffer.Length == 0) { buffer.Append("#" + Errors.CLI_UnsupportedPropertyType + " - "); } buffer.AppendLine("Property \"" + ex.member.Name + "\" of type \"" + ex.member.Type.Name + "\" from \"" + ex.member.MemberInfo.DeclaringType.Name + "\" is unsupported."); } } } } if (buffer.Length > 0) { buffer.Length -= Environment.NewLine.Length; InternalNGDebug.VerboseLog(Utility.ReturnBuffer(buffer)); } else { Utility.RestoreBuffer(buffer); } } this.CleanEmptyNodes(this.parser.Root); if (this.parser.Root.children.Count == 0) { InternalNGDebug.Log(Errors.CLI_EmptyRootCommand, "There is not root command in your CLI."); } }