static ParseResult CreateTextFacetResult(ParseInput input, ParseRange range) { var textForRange = input.GetTextForRange(range).Trim(); var moniker = new FacetMoniker(typeof(EngineFacetsFactory), typeof(TextFacet), textForRange, textForRange); return(new ParseResult(input, range, moniker, ParseResult.ExactMatchRelevance)); }
protected override IEnumerable <ParseResult> ParseImpl(ParseInput input, IEnumerable <FacetMoniker> indexEntries) { var increment = 1.0 / input.Terms.Count; foreach (var entry in indexEntries) { var relevance = 0.0; var lower = entry.DisplayName.ToLower(); var range = new ParseRange(0, 0); foreach (var term in input.Terms) { if (lower.StartsWith(term.TextLower)) { relevance += increment * 1.5; } else if (lower.Contains(term.TextLower)) { relevance += increment; } else { // require constant progress break; } range = range.Union(term.Range); if (relevance > 0.0) { yield return(new ParseResult(input, range, entry, Math.Min(1.0, relevance))); } } } }
ParseResult CreateParseResult(ParseInput input, ParseRange range, bool isSuggestion, string path, double relevance, bool isDirectory) { var type = "Folder"; if (!isDirectory) { switch (Path.GetExtension(path).ToLower()) { case ".lnk": case ".exe": type = "Program"; break; default: type = "File"; break; } } var moniker = new FacetMoniker(GetType(), typeof(FileSystemItemFacet), path, path, extraData: FacetExtraData.BeginWith(typeof(IFileSystemItemFacet), "Type", type), iconPath: null); return(new ParseResult(input, range, moniker, relevance, isSuggestion)); }
static List <CommandArgument> CreateCommand(ParseInput input, List <ParseRange> rangeList, IDictionary <ParseRange, ParseResult[]> groupedResults, IEnumerable <CommandParameter> parameters) { var argList = new List <CommandArgument>(); var unusedRanges = new List <ParseRange>(rangeList); var textFacetParamIndex = -1; // The arguments don't have to appear in the same order as the parameters, so we loop through // parameters and pull out the first eligible argument for each. At the end of the loop, if all // arguments have been used, we can proceed to the next step. foreach (var param in parameters) { if (param.Type == typeof(ITextFacet)) { textFacetParamIndex = argList.Count; argList.Add(CommandArgument.Unspecified); continue; } var anyInRangeQuery = from r in unusedRanges where r != null && !ReferenceEquals(r, RemainingTextRangeMarker) from pr in groupedResults[r] where param.IsUsableAsArgument(pr.FacetMoniker) select pr; var found = anyInRangeQuery.FirstOrDefault(); if (found == null) { // No match in the parse results // Try ambient facets var ambient = Loader.AmbientFacets .Where(x => param.IsUsableAsArgument(x.Moniker)) .Select(x => x.Moniker) .FirstOrDefault(); if (ambient != null) { argList.Add(new CommandArgument(ambient)); continue; } argList.Add(CommandArgument.Unspecified); continue; } unusedRanges[unusedRanges.IndexOf(found.Range)] = null; // TODO: optimization: leave off the suggestion filtering until we've determined // the command is eligible // Do we have any eligible suggestions in the same ParseRange? IEnumerable <FacetMoniker> suggestions = null; if (groupedResults[found.Range].Length > 1) { suggestions = groupedResults[found.Range] .Where(x => !ReferenceEquals(found, x)) .Where(x => param.IsUsableAsArgument(x.FacetMoniker)) .Select(x => x.FacetMoniker); } argList.Add(new CommandArgument(found, suggestions)); } var unusedCount = unusedRanges.Count(x => x != null); if (unusedCount != 0) { if (textFacetParamIndex == -1) { return(null); } // Can we use all of the unused up as a text facet, and are they all in line at the rightmost // part of the input? var unusedRightmostCount = Enumerable.Reverse(unusedRanges) .TakeWhile(x => x != null) .Count(); if (unusedRightmostCount < unusedCount) { // not all unused ranges are rightmost return(null); } if (ReferenceEquals(unusedRanges.Last(), RemainingTextRangeMarker)) { // rangeList is original - same length and index values as unusedRanges var prev = rangeList[rangeList.Count - 2]; unusedRanges[unusedRanges.Count - 1] = ParseRange.FromIndexes(prev.EndIndex + 1, input.Text.Length - 1); } var unusedIndexStart = unusedRanges.Count - unusedRightmostCount; var unusedIndexEnd = unusedIndexStart + unusedRightmostCount - 1; var textRange = unusedRanges[unusedIndexStart].Union(unusedRanges[unusedIndexEnd]); argList[textFacetParamIndex] = new CommandArgument(CreateTextFacetResult(input, textRange)); } return(argList); }
protected override IEnumerable <ParseResult> ParseImpl(ParseInput input, ParseMode mode, IList <Type> facetTypes) { var startRegex = new Regex(@"\:\\"); foreach (Match startMatch in startRegex.Matches(input.Text)) { if (startMatch.Index == 0) { continue; } var startIndex = startMatch.Index - 1; string best = null; var bestIsFile = false; Func <char, bool> isBreak = ch => char.IsWhiteSpace(ch) || ch == '\\'; for (var idx = startIndex; idx <= input.Text.Length; idx++) { if (idx == input.Text.Length || isBreak(input.Text[idx])) { var len = idx - startIndex; var text = input.Text.Substring(startIndex, len); if (File.Exists(text)) { bestIsFile = true; best = text; } else if (Directory.Exists(text)) { bestIsFile = false; best = text; } else { break; } } } if (best == null) { continue; } var bestRange = new ParseRange(startIndex, best.Length); if (bestIsFile) { yield return(CreateParseResult(input, bestRange, false, RecaseFilePath(best), ParseResult.ExactMatchRelevance, false)); } yield return(CreateParseResult(input, bestRange, false, RecaseFilePath(best), ParseResult.ExactMatchRelevance, true)); if (bestRange.EndIndex == input.Text.Length - 1 || (mode & ParseMode.Suggest) == 0 || input.Text[bestRange.EndIndex + 1] != '\\') { continue; } var remain = new string(Enumerable.Skip <char>(input.Text, bestRange.EndIndex + 2).TakeWhile(ch => !char.IsWhiteSpace(ch)).ToArray()); if (remain.Length > 0) { var bestAndRemainRange = new ParseRange(startIndex, bestRange.Length + 1 + remain.Length); string directory; try { directory = RecaseFilePath(best); } catch (Exception) { continue; } if (directory != null) { var query = Directory .EnumerateFileSystemEntries(directory, remain + "*.*") .Take(10) .Select(x => Path.Combine(directory, Path.GetFileName(x))) .Select(x => CreateParseResult(input, bestAndRemainRange, true, x, 0.5, Directory.Exists(x))); foreach (var result in query) { yield return(result); } } } } }
public static CommandUsage[] GetCommandUsages(IEnumerable <Command> commands, bool commandsOnly = false) { var rvl = new List <CommandUsage>(); using (var selectCommandConnection = DatabaseUtil.GetConnection()) using (var selectArgConnection = DatabaseUtil.GetConnection()) { const string selectCommandText = @"SELECT cu.Id, cu.At, cu.Text AS ParseInput FROM CommandUsages AS cu WHERE cu.CommandId = @CommandId"; const string selectArgText = @"SELECT fm.FactoryTypeId, fm.FacetTypeId, fm.DisplayName, fm.DateTime, fm.FactoryData, fm.Source, fm.ExtraData, cua.Ordinal, cua.RangeStartIndex, cua.RangeLength, cua.Relevance, cua.MatchedText FROM CommandUsageArguments AS cua INNER JOIN FacetMonikers AS fm ON fm.Id = cua.FacetMonikerId WHERE cua.CommandUsageId = @CommandUsageId ORDER BY cua.Ordinal"; using (var selectCommandUsageCmd = new SqlCeCommand(selectCommandText, selectCommandConnection)) using (var selectUsageArgumentsCmd = new SqlCeCommand(selectArgText, selectArgConnection)) { selectCommandUsageCmd.Parameters.AddWithValue("@CommandId", SqlDbType.Int); selectUsageArgumentsCmd.Parameters.AddWithValue("@CommandUsageId", SqlDbType.Int); foreach (var command in commands.Distinct()) { selectCommandUsageCmd.Parameters["@CommandId"].Value = Loader.GetCommandInfo(command).DatabaseId; foreach (var cmdRow in selectCommandUsageCmd.ExecuteReader().AsEnumerable()) { if (commandsOnly) { rvl.Add(new CommandUsage(command, (DateTime)cmdRow["At"])); continue; } var parseInput = new ParseInput((string)cmdRow["ParseInput"]); var arguments = new List <CommandArgument>(); var lastOrdinal = -1; selectUsageArgumentsCmd.Parameters["@CommandUsageId"].Value = (int)cmdRow["Id"]; foreach (var argRow in selectUsageArgumentsCmd.ExecuteReader().AsEnumerable()) { var ordinal = (int)argRow["Ordinal"]; while (++lastOrdinal < ordinal) { arguments.Add(CommandArgument.Unspecified); } // reconstruct facet moniker var moniker = FacetIndex.MaterializeMoniker(argRow); if (moniker == null) { arguments = null; break; } if ((int)argRow["RangeStartIndex"] != -1) { // reconstruct parse range var range = new ParseRange( (int)argRow["RangeStartIndex"], (int)argRow["RangeLength"]); // reconstruct parseresult var parseResult = new ParseResult( parseInput, range, moniker, (double)argRow["Relevance"]); arguments.Add(new CommandArgument(parseResult)); } else { // moniker only arguments.Add(new CommandArgument(moniker)); } } if (arguments != null) { while (++lastOrdinal < command.Parameters.Count) { arguments.Add(CommandArgument.Unspecified); } var cei = new CommandExecutor(parseInput, command, arguments); rvl.Add(new CommandUsage(cei, (DateTime)cmdRow["At"])); } } } } } return(rvl.ToArray()); }
protected override IEnumerable <ParseResult> ParseImpl(ParseInput input, IEnumerable <FacetMoniker> indexEntries) { foreach (var entry in indexEntries) { var ci = ContactInfo.FromXml(entry.FactoryData); var relevance = 0.0; ParseRange firstNameRange = null; ParseRange lastNameRange = null; ParseRange emailRange = null; foreach (var term in input.Terms) { if (firstNameRange == null) { if (ApplyRelevance(ref relevance, ci.FirstName, term.TextLower) > 0) { firstNameRange = term.Range; continue; } } if (lastNameRange == null) { if (ApplyRelevance(ref relevance, ci.LastName, term.TextLower) > 0) { lastNameRange = term.Range; continue; } } if (emailRange == null) { if (ApplyRelevance(ref relevance, ci.Email, term.TextLower) > 0) { emailRange = term.Range; continue; } } } if (relevance == 0.0 || ((firstNameRange != null && lastNameRange != null) && lastNameRange.StartIndex <= firstNameRange.StartIndex)) { continue; } // determine the input range that caused the match ParseRange range; if (firstNameRange != null) { if (lastNameRange != null) { range = firstNameRange.Union(lastNameRange); } else { range = firstNameRange; } } else if (lastNameRange != null) { range = lastNameRange; } else { range = emailRange; } yield return(new ParseResult(input, range, entry, relevance)); } }