예제 #1
0
 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);
     }
 }
예제 #2
0
        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);
        }