public ConsoleCommand FindSubNodeByName(string name) { ConsoleCommand found = null; foreach (ConsoleCommand sub in SubCommands) { if (sub.Name == name) { found = sub; break; } } return(found); }
/// <summary> /// Builds the debugger command tree. /// </summary> private void BuildCommandTree() { // Build the flat list which will be built into the tree, by walking // the classes that provide the methods _commandList = new List <ConsoleCommand>(); Type[] commandTypes = { typeof(ConsoleCommands), typeof(ConsoleExecutor), }; foreach (Type type in commandTypes) { foreach (MethodInfo info in type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { object[] attribs = info.GetCustomAttributes(typeof(ConsoleFunction), true); if (attribs.Length > 1) { throw new InvalidOperationException(String.Format("More than one ConsoleFunction attribute set on {0}", info.Name)); } else if (attribs.Length == 1) { // we have a debugger attribute set on this method // this cast should always succeed given that we're filtering for this type above. ConsoleFunction function = (ConsoleFunction)attribs[0]; ConsoleCommand newCommand = new ConsoleCommand(function.CommandName, function.Description, function.Usage, info); _commandList.Add(newCommand); } } } // Now actually build the command tree from the above list! _commandRoot = new ConsoleCommand("Root", null, null, null); foreach (ConsoleCommand c in _commandList) { string[] commandWords = c.Name.Split(' '); // This is kind of ugly, we know that at this point every command built above have only // one method. When building the tree, overloaded commands may end up with more than one. _commandRoot.AddSubNode(new List <string>(commandWords), c.Methods[0]); } }
private List <MethodInfo> GetMethodsFromCommandString(string command, out string[] args) { args = null; List <string> cmdArgs = SplitArgs(command); ConsoleCommand current = _commandRoot; int commandIndex = 0; while (true) { // If this node has an executor, then we're done // (We assume that the tree is correctly built and that only // leaves have executors) if (current.Methods.Count > 0) { break; } if (commandIndex > cmdArgs.Count - 1) { // Out of args! return(null); } // Otherwise we continue down the tree. current = current.FindSubNodeByName(cmdArgs[commandIndex]); commandIndex++; if (current == null) { // If the node was not found, then the command is invalid. return(null); } } //Now current should point to the command with the executor //and commandIndex should point to the first argument to the command. cmdArgs.RemoveRange(0, commandIndex); args = cmdArgs.ToArray(); return(current.Methods); }
private string FuzzyMatch(ConsoleCommand root, List <string> tokens, bool silent) { if (tokens.Count == 0) { if (!silent) { // If there are no tokens, just show the completion for the root. PrintCompletions(root.SubCommands); } return(String.Empty); } ConsoleCommand match = null; bool exactMatch = false; // Search for exact matches. If we find one it's guaranteed to be unique // so we can follow that node. foreach (ConsoleCommand c in root.SubCommands) { if (c.Name.ToLower() == tokens[0].ToLower()) { match = c; exactMatch = true; break; } } if (match == null) { // No exact match. Try a substring match. // If we have an unambiguous match then we can complete it automatically. // If the match is ambiguous, display possible completions and return String.Empty. List <ConsoleCommand> completions = new List <ConsoleCommand>(); foreach (ConsoleCommand c in root.SubCommands) { if (c.Name.StartsWith(tokens[0], StringComparison.InvariantCultureIgnoreCase)) { completions.Add(c); } } if (completions.Count == 1) { // unambiguous match. use it. match = completions[0]; } else if (completions.Count > 1) { // ambiguous match. display possible completions. if (!silent) { PrintCompletions(completions); } } } if (match == null) { // If we reach this point then no matches are available. return the tokens we have... StringBuilder sb = new StringBuilder(); for (int i = 0; i < tokens.Count; i++) { if (i < tokens.Count - 1) { sb.AppendFormat("{0} ", tokens[i]); } else { sb.AppendFormat("{0}", tokens[i]); } } return(sb.ToString()); } else { // A match was found tokens.RemoveAt(0); string subMatch = String.Empty; if (tokens.Count > 0) { subMatch = FuzzyMatch(match, tokens, silent); } else if (exactMatch) { if (!silent && match.SubCommands.Count > 0) { // Just show the completions for this node. PrintCompletions(match.SubCommands); } } if (subMatch == String.Empty) { return(String.Format("{0} ", match.Name)); } else { return(String.Format("{0} {1}", match.Name, subMatch)); } } }
public ConsolePrompt(ConsoleCommand root) { _commandTree = root; _commandHistory = new List <string>(64); _historyIndex = 0; }