static IEnumerable <ParseResult> TryParse(CommandGeneratorResult result, LoaderFacetFactory lff, ParseInput input, ParseMode mode, IList <TypeMoniker> facetTypes) { try { return(lff.Factory.Parse(input.RewriteInput(lff, false), mode, facetTypes)); } catch (RequiresConfigurationException ex) { result.AddRCException(ex); return(null); } catch (OutOfMemoryException) { throw; } catch { return(null); } }
public static CommandGeneratorResult GenerateCommands(string commandText, int insertionPointIndex) { // TODO: plinq the whole thing if (commandText == null) { throw new ArgumentNullException("commandText"); } if (insertionPointIndex < -1 || insertionPointIndex > commandText.Length) { throw new ArgumentOutOfRangeException("insertionPointIndex"); } if (commandText.Length == 0) { return(new CommandGeneratorResult()); } Command[] potentialCommands; CommandExecutor[] potentialPartialCommands; var commandsFiltered = false; // TODO: delimiter for TextFacet -- possibly a colon. Solves for problem illustrated in example // here, which is that the second "Bob" may be parsed as a contact and excluded from the // "remaining text" logic: >email bob: Bob, Lunch? if (commandText[0] == '>') { var cmdName = commandText.Skip(1).TakeWhile(x => !Char.IsWhiteSpace(x)).CharsToString(); if (cmdName.Length == 0) { return(new CommandGeneratorResult()); } var trimmed = commandText.Substring(cmdName.Length + 1).TrimStart(); insertionPointIndex -= commandText.Length - trimmed.Length; commandText = trimmed; var pca = (from cinfo in Loader.Commands from a in cinfo.Aliases where a.StartsWith(cmdName, StringComparison.CurrentCultureIgnoreCase) select cinfo.Command).ToArray(); var ppca = CommandHistory.LoadPartialCommands(cmdName).ToArray(); if (pca.Length == 0 && ppca.Length == 0) { return(new CommandGeneratorResult()); } potentialCommands = pca; potentialPartialCommands = ppca; commandsFiltered = true; } else { potentialCommands = Loader.Commands.Select(x => x.Command).ToArray(); potentialPartialCommands = CommandHistory.LoadPartialCommands().ToArray(); } var pptRegularCommands = potentialCommands .SelectMany(x => x.Parameters) .Select(x => x.TypeDescriptor); var pptPartialCommands = potentialPartialCommands .SelectMany(x => x.UnspecifiedParameters) .Select(x => x.TypeDescriptor); var potentialParameterTypes = pptRegularCommands .Union(pptPartialCommands) .ToArray(); var potentialFacetTypes = Loader.GetFacetTypesForParameterTypes(potentialParameterTypes) .Select(x => x.TypeDescriptor) .Concat(TypeDescriptor.Get(typeof(TextFacet))) .Distinct() .ToArray(); var potentialFactories = Loader .GetFacetFactoriesForFacetTypes(potentialFacetTypes) .ToArray(); if (potentialFacetTypes.Length == 0) { return(new CommandGeneratorResult()); } var input = new ParseInput(commandText, insertionPointIndex); var allResults = new List <ParseResult>(); var rvl = new CommandGeneratorResult(); if (commandText.Length > 0) { var outConfigurationExceptions = new List <RequiresConfigurationException>(); // TODO: parallelize the different forms of parsing (perfect multithreading opportunity) var potentialFacetMonikers = potentialFacetTypes.Select(x => x.Moniker).ToArray(); var dynamicResults = (from f in potentialFactories where !(f.Factory is IFacetFactoryWithIndex) let result = TryParse(rvl, f, input, ParseMode.All, potentialFacetMonikers) where result != null from r in result select r).ToArray(); var indexResults = FacetIndex.Parse( potentialFactories.Select(x => x.Factory).OfType <IFacetFactoryWithIndex>(), potentialFacetTypes, input, ParseMode.All, outConfigurationExceptions).ToArray(); var historyResults = FacetIndex.ParseFromHistory(potentialFacetTypes, input).ToArray(); allResults = (from r in dynamicResults.Union(indexResults).Union(historyResults) orderby r.Range.StartIndex select r).ToList(); foreach (var ex in outConfigurationExceptions) { rvl.AddRCException(ex); } // is this right commented out? //if (allResults.Count == 0) { allResults.Add(CreateTextFacetResult(input, new ParseRange(0, input.Text.Length))); } } var groupedResults = allResults .GroupBy(x => x.Range) .ToDictionary(x => x.Key, x => x.ToArray()); var rangeLists = CreateRangeLists(input, groupedResults.Keys); var commands = CreateCommandsFromResultLists(input, rangeLists, groupedResults, potentialCommands, potentialPartialCommands, commandsFiltered); foreach (var cmd in commands.Distinct()) { rvl.AddExecutor(cmd); } return(rvl); }