private void FormatCaptureGroups(Paragraph paragraph, GrepMatch match, string fmtLine) { if (paragraph == null || match == null || string.IsNullOrEmpty(fmtLine)) { return; } GroupMap map = new GroupMap(match, fmtLine); foreach (var range in map.Ranges.Where(r => r.Length > 0)) { var run = new Run(range.RangeText); if (range.Group == null) { run.SetResourceReference(Run.ForegroundProperty, "Match.Highlight.Foreground"); run.SetResourceReference(Run.BackgroundProperty, "Match.Highlight.Background"); run.ToolTip = TranslationSource.Format(Resources.Main_ResultList_MatchToolTip1, Parent.MatchIdx, Environment.NewLine, fmtLine); paragraph.Inlines.Add(run); } else { if (!Parent.GroupColors.TryGetValue(range.Group.Name, out string bgColor)) { int groupIdx = Parent.GroupColors.Count % 10; bgColor = $"Match.Group.{groupIdx}.Highlight.Background"; Parent.GroupColors.Add(range.Group.Name, bgColor); } run.SetResourceReference(Run.ForegroundProperty, "Match.Highlight.Foreground"); run.SetResourceReference(Run.BackgroundProperty, bgColor); run.ToolTip = TranslationSource.Format(Resources.Main_ResultList_MatchToolTip2, Parent.MatchIdx, Environment.NewLine, range.Group.Name, range.Group.Value); paragraph.Inlines.Add(run); } } }
public FormattedGrepMatch(GrepMatch match) { Match = match; ReplaceMatch = Match.ReplaceMatch; Background = Match.ReplaceMatch ? Brushes.PaleGreen : Brushes.Bisque; }
protected override void ColorizeLine(DocumentLine line) { if (result.Matches == null || result.Matches.Count == 0) { return; } int lineStartOffset = line.Offset; int lineNumber = line.LineNumber; var lineResult = result.SearchResults.FirstOrDefault(sr => sr.ClippedFileLineNumber == lineNumber && sr.IsContext == false); if (lineResult != null) { foreach (var grepMatch in lineResult.Matches) { try { // get the global file match corresponding to this line match // only the file match has a valid ReplaceMatch flag GrepMatch fileMatch = result.Matches.FirstOrDefault(m => m.FileMatchId == grepMatch.FileMatchId); Color color = fileMatch == null ? Colors.LightGray : fileMatch.ReplaceMatch ? Colors.PaleGreen : Colors.LightSalmon; bool isSelected = grepMatch.FileMatchId.Equals(SelectedGrepMatch.FileMatchId); base.ChangeLinePart( lineStartOffset + grepMatch.StartLocation, // startOffset lineStartOffset + grepMatch.StartLocation + grepMatch.Length, // endOffset (VisualLineElement element) => { // This lambda gets called once for every VisualLineElement // between the specified offsets. element.TextRunProperties.SetBackgroundBrush(new SolidColorBrush(color)); if (isSelected) { TextDecorationCollection coll = new TextDecorationCollection { new TextDecoration( TextDecorationLocation.Underline, new Pen(Brushes.Black, 2), 0, TextDecorationUnit.Pixel, TextDecorationUnit.Pixel) }; element.TextRunProperties.SetTextDecorations(coll); } }); } catch { // Do nothing } } } }
public GroupMap(GrepMatch match, string text) { start = match.StartLocation; MatchText = text; ranges.Add(new Range(0, MatchText.Length, this, null)); foreach (var group in match.Groups.OrderByDescending(g => g.Length)) { Insert(group); } ranges.Sort(); }
/// <inheritdoc /> public FormattedMatch FormatMatch(GrepMatch match) { var preMatch = match.Context.Substring(0, match.Index - 1).TrimStart(); var postMatch = match.Context.Substring(match.Index + match.Value.Length - 1).TrimEnd(); return(new FormattedMatch( match, new List <FormattedSpan> { new FormattedSpan(preMatch, ConsoleColor.DarkGray), new FormattedSpan(match.Value, ConsoleColor.Blue), new FormattedSpan(postMatch, ConsoleColor.DarkGray), })); }
private IEnumerable <GrepMatch> TextSearchIteratorBoolean(int lineNumber, int filePosition, string text, BooleanExpression expression, List <int> lineEndIndexes, bool isWholeWord, StringComparison comparisonType) { List <GrepMatch> results = new List <GrepMatch>(); foreach (var operand in expression.Operands) { var matches = TextSearchIterator(lineNumber, filePosition, text, operand.Value, lineEndIndexes, isWholeWord, comparisonType); operand.EvaluatedResult = matches.Any(); operand.Matches = matches.ToList(); if (!expression.IsComplete && expression.IsShortCircuitFalse()) { return(results); } } if (expression.IsComplete) { var evalResult = expression.Evaluate(); if (evalResult == EvaluationResult.True) { foreach (var operand in expression.Operands) { if (operand.Matches != null) { results.AddRange(operand.Matches); } } // if the expression evaluated to true, then the expression is searching // for things that do not match the operands. Return the whole line if (results.Count == 0) { string temp = text.TrimEndOfLine(); results.Add(new GrepMatch(string.Empty, lineNumber, filePosition, temp.Length)); } GrepMatch.Normalize(results); } } return(results); }
private IEnumerable <GrepMatch> TextSearchIteratorOr(int lineNumber, int filePosition, string text, List <string> orClauses, List <int> lineEndIndexes, bool isWholeWord, StringComparison comparisonType) { List <GrepMatch> results = new List <GrepMatch>(); foreach (string searchText in orClauses) { var matches = TextSearchIterator(lineNumber, filePosition, text, searchText, lineEndIndexes, isWholeWord, comparisonType); if (matches.Any()) { results.AddRange(matches); } } GrepMatch.Normalize(results); return(results); }
private IEnumerable <GrepMatch> RegexSearchIteratorOr(int lineNumber, int filePosition, string text, List <string> orClauses, bool isWholeWord, RegexOptions regexOptions) { List <GrepMatch> results = new List <GrepMatch>(); foreach (string searchPattern in orClauses) { var matches = RegexSearchIterator(lineNumber, filePosition, text, searchPattern, isWholeWord, regexOptions); if (matches.Any()) { results.AddRange(matches); } } GrepMatch.Normalize(results); return(results); }
private InlineCollection FormatLine(GrepLine line) { Paragraph paragraph = new Paragraph(); string fullLine = line.LineText; if (line.LineText.Length > MaxLineLength) { fullLine = line.LineText.Substring(0, MaxLineLength); } if (line.Matches.Count == 0) { Run mainRun = new Run(fullLine); paragraph.Inlines.Add(mainRun); } else { int counter = 0; GrepMatch[] lineMatches = new GrepMatch[line.Matches.Count]; line.Matches.CopyTo(lineMatches); foreach (GrepMatch m in lineMatches) { Parent.MatchIdx++; try { string regLine = null; string fmtLine = null; if (m.StartLocation < fullLine.Length) { regLine = fullLine.Substring(counter, m.StartLocation - counter); } if (m.StartLocation + m.Length <= fullLine.Length) { fmtLine = fullLine.Substring(m.StartLocation, m.Length); } else if (fullLine.Length > m.StartLocation) { // match may include the non-printing newline chars at the end of the line: don't overflow the length fmtLine = fullLine.Substring(m.StartLocation, fullLine.Length - m.StartLocation); } else { // binary file? regLine = fullLine; } if (regLine != null) { Run regularRun = new Run(regLine); paragraph.Inlines.Add(regularRun); } if (fmtLine != null) { if (HighlightCaptureGroups && m.Groups.Count > 0) { FormatCaptureGroups(paragraph, m, fmtLine); } else { var run = new Run(fmtLine); run.SetResourceReference(Run.ForegroundProperty, "Match.Highlight.Foreground"); run.SetResourceReference(Run.BackgroundProperty, "Match.Highlight.Background"); paragraph.Inlines.Add(run); } } else { break; } } catch { Run regularRun = new Run(fullLine); paragraph.Inlines.Add(regularRun); } finally { counter = m.StartLocation + m.Length; } } if (counter < fullLine.Length) { try { string regLine = fullLine.Substring(counter); Run regularRun = new Run(regLine); paragraph.Inlines.Add(regularRun); } catch { Run regularRun = new Run(fullLine); paragraph.Inlines.Add(regularRun); } } if (line.LineText.Length > MaxLineLength) { string msg = TranslationSource.Format(Resources.Main_ResultList_CountAdditionalCharacters, line.LineText.Length - MaxLineLength); var msgRun = new Run(msg); msgRun.SetResourceReference(Run.ForegroundProperty, "TreeView.Message.Highlight.Foreground"); msgRun.SetResourceReference(Run.BackgroundProperty, "TreeView.Message.Highlight.Background"); paragraph.Inlines.Add(msgRun); var hiddenMatches = line.Matches.Where(m => m.StartLocation > MaxLineLength).Select(m => m); int count = hiddenMatches.Count(); if (count > 0) { paragraph.Inlines.Add(new Run(" " + Resources.Main_ResultList_AdditionalMatches)); } // if close to getting them all, then take them all, // otherwise, stop at 20 and just show the remaining count int takeCount = count > 25 ? 20 : count; foreach (GrepMatch m in hiddenMatches.Take(takeCount)) { if (m.StartLocation + m.Length <= line.LineText.Length) { paragraph.Inlines.Add(new Run(" ")); string fmtLine = line.LineText.Substring(m.StartLocation, m.Length); var run = new Run(fmtLine); run.SetResourceReference(Run.ForegroundProperty, "Match.Highlight.Foreground"); run.SetResourceReference(Run.BackgroundProperty, "Match.Highlight.Background"); paragraph.Inlines.Add(run); if (m.StartLocation + m.Length == line.LineText.Length) { paragraph.Inlines.Add(new Run(" " + Resources.Main_ResultList_AtEndOfLine)); } else { paragraph.Inlines.Add(new Run(" " + TranslationSource.Format(Resources.Main_ResultList_AtPosition, m.StartLocation))); } } } if (count > takeCount) { paragraph.Inlines.Add(new Run(TranslationSource.Format(Resources.Main_ResultList_PlusCountMoreMatches, count - takeCount))); } } } return(paragraph.Inlines); }
public GrepMatch[] GetFilePositions(string text, List <XPathPosition> positions) { bool[] endFound = new bool[positions.Count]; // Getting line lengths List <int> lineLengths = new List <int>(); using (StringReader baseReader = new StringReader(text)) { using (EolReader reader = new EolReader(baseReader)) { while (!reader.EndOfStream) { lineLengths.Add(reader.ReadLine().Length); } } } // These are absolute positions GrepMatch[] results = new GrepMatch[positions.Count]; if (positions.Count == 0) { return(results); } using (StringReader textReader = new StringReader(text)) using (XmlReader reader = XmlReader.Create(textReader)) { List <int> currPos = new List <int>(); try { IXmlLineInfo lineInfo = ((IXmlLineInfo)reader); if (lineInfo.HasLineInfo()) { // Parse the XML and display each node. while (reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: case XmlNodeType.Comment: if (currPos.Count <= reader.Depth) { currPos.Add(1); } else { currPos[reader.Depth]++; } break; case XmlNodeType.EndElement: while (reader.Depth < currPos.Count - 1) { currPos.RemoveAt(reader.Depth + 1); // currPos.Count - 1 would work too. } for (int i = 0; i < positions.Count; i++) { if (XPathPositionsMatch(currPos, positions[i].Path)) { endFound[i] = true; } } break; default: break; } if (reader.NodeType == XmlNodeType.EndElement || reader.NodeType == XmlNodeType.Comment) { int tokenOffset = reader.NodeType == XmlNodeType.Element ? 3 : 5; for (int i = 0; i < positions.Count; i++) { if (endFound[i] && !XPathPositionsMatch(currPos, positions[i].Path)) { if (results[i] != null) { results[i].EndPosition = GetAbsoluteCharPosition(lineInfo.LineNumber - 1, lineInfo.LinePosition - tokenOffset, text, lineLengths, true) + 1; } endFound[i] = false; } } } if (reader.NodeType == XmlNodeType.Element) { for (int i = 0; i < positions.Count; i++) { if (endFound[i]) { if (results[i] != null) { results[i].EndPosition = GetAbsoluteCharPosition(lineInfo.LineNumber - 1, lineInfo.LinePosition - 3, text, lineLengths, true) + 1; } endFound[i] = false; } if (XPathPositionsMatch(currPos, positions[i].Path)) { results[i] = new GrepMatch(string.Empty, lineInfo.LineNumber, GetAbsoluteCharPosition(lineInfo.LineNumber - 1, lineInfo.LinePosition - 2, text, lineLengths, false), 0); } // If empty element (e.g.<element/>) if (reader.IsEmptyElement) { if (XPathPositionsMatch(currPos, positions[i].Path)) { endFound[i] = true; } } } } } } } finally { for (int i = 0; i < positions.Count; i++) { if (results[i] != null && results[i].Length == 0) { results[i].EndPosition = text.Length - 1; } } reader.Close(); } // Close the reader. } return(results); }
private IEnumerable <GrepMatch> RegexSearchIterator(int lineNumber, int filePosition, string text, string searchPattern, bool isWholeWord, RegexOptions regexOptions) { if (isWholeWord) { if (!searchPattern.Trim().StartsWith("\\b")) { searchPattern = "\\b" + searchPattern.Trim(); } if (!searchPattern.Trim().EndsWith("\\b")) { searchPattern = searchPattern.Trim() + "\\b"; } } // Issue #210 .net regex will only match the $ end of line token with a \n, not \r\n or \r // see https://msdn.microsoft.com/en-us/library/yd1hzczs.aspx#Multiline // http://stackoverflow.com/questions/8618557/why-doesnt-in-net-multiline-regular-expressions-match-crlf // https://docs.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-language-quick-reference // Note: in Singleline mode, need to capture the new line chars bool searchPatternEndsWithDot = searchPattern.EndsWith(".") || searchPattern.EndsWith(".*") || searchPattern.EndsWith(".?") || searchPattern.EndsWith(".+"); int extraChars = 0; if (text.Contains("\r\n")) { if (searchPattern.Contains("$")) { if (regexOptions.HasFlag(RegexOptions.Singleline)) { searchPattern = searchPattern.Replace("$", "\r?$"); } else { searchPattern = searchPattern.Replace("$", "(?=\r?$)"); // can't make this pattern work if the multi line text does not end in a newline if (regexOptions.HasFlag(RegexOptions.Multiline) && !text.EndsWith("\r\n")) { text += "\r\n"; extraChars = 2; } } } // if the patten ends with a dot in some form, it will match the \r path of \r\n // modify the search pattern to capture or exclude the \r if (searchPatternEndsWithDot) { if (regexOptions.HasFlag(RegexOptions.Singleline)) { searchPattern += "\r?$"; } else { searchPattern += "(?=\r?$)"; // can't make this pattern work if the multi line text does not end in a newline if (regexOptions.HasFlag(RegexOptions.Multiline) && !text.EndsWith("\r\n")) { text += "\r\n"; extraChars = 2; } } } } else if (text.Contains("\r") && (searchPattern.Contains("$") || searchPatternEndsWithDot)) { // for this case, it's easiest to change the newline char while searching searchPattern = searchPattern.Replace('\r', '\n'); text = text.Replace('\r', '\n'); } var lineEndIndexes = GetLineEndIndexes((initParams.VerboseMatchCount && lineNumber == -1) ? text : null); List <GrepMatch> globalMatches = new List <GrepMatch>(); var regex = new Regex(searchPattern, regexOptions, MatchTimeout); var matches = regex.Matches(text); foreach (Match match in matches) { if (initParams.VerboseMatchCount && lineEndIndexes.Count > 0) { lineNumber = lineEndIndexes.FindIndex(i => i > match.Index) + 1; } int length = match.Length; if (match.Index + filePosition + match.Length > text.Length) { length -= extraChars; } // The pattern (?=\r?$) fixes most problems trying to make \r\n process like \n // but it does capture the leading \r in the match. When that happens, set the // match length back one to exclude it if (!regexOptions.HasFlag(RegexOptions.Singleline) && match.Value.EndsWith("\r")) { length -= 1; } var grepMatch = new GrepMatch(searchPattern, lineNumber, match.Index + filePosition, length); if (match.Groups.Count > 1) { // Note that group 0 is always the whole match for (int idx = 1; idx < match.Groups.Count; idx++) { var group = match.Groups[idx]; if (group.Success) { length = group.Length; if (!regexOptions.HasFlag(RegexOptions.Singleline) && group.Value.EndsWith("\r")) { length -= 1; } grepMatch.Groups.Add( new GrepCaptureGroup(regex.GroupNameFromNumber(idx), group.Index, length, group.Value)); } } } yield return(grepMatch); } }
private IEnumerable <GrepMatch> RegexSearchIterator(int lineNumber, int filePosition, string text, string searchPattern, bool isWholeWord, RegexOptions regexOptions) { if (isWholeWord) { if (!searchPattern.Trim().StartsWith("\\b")) { searchPattern = "\\b" + searchPattern.Trim(); } if (!searchPattern.Trim().EndsWith("\\b")) { searchPattern = searchPattern.Trim() + "\\b"; } } // Issue #210 .net regex will only match the $ end of line token with a \n, not \r\n or \r // see https://msdn.microsoft.com/en-us/library/yd1hzczs.aspx#Multiline // http://stackoverflow.com/questions/8618557/why-doesnt-in-net-multiline-regular-expressions-match-crlf // https://docs.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-language-quick-reference // Note: in Singleline mode, need to capture the new line chars bool searchPatternEndsWithDot = (searchPattern.EndsWith(".") && !searchPattern.EndsWith(@"\.")) || (searchPattern.EndsWith(".*") && !searchPattern.EndsWith(@"\.*")) || (searchPattern.EndsWith(".?") && !searchPattern.EndsWith(@"\.?")) || (searchPattern.EndsWith(".+") && !searchPattern.EndsWith(@"\.+")); string textToSearch = text; bool convertedFromWindowsNewline = false; List <int> newlineIndexes = null; if (searchPattern.ConstainsNotEscaped("$") || searchPatternEndsWithDot) { if (text.Contains("\r\n")) { // the match index will be off by one for each line where the \r was dropped searchPattern = searchPattern.Replace("\r\n", "\n").Replace('\r', '\n'); textToSearch = ConvertNewLines(text, out newlineIndexes); convertedFromWindowsNewline = true; } else if (text.Contains("\r")) { // this will be the same length, just change the newline char while searching searchPattern = searchPattern.Replace("\r\n", "\n").Replace('\r', '\n'); textToSearch = text.Replace('\r', '\n'); } } var lineEndIndexes = GetLineEndIndexes((initParams.VerboseMatchCount && lineNumber == -1) ? textToSearch : null); List <GrepMatch> globalMatches = new List <GrepMatch>(); var regex = new Regex(searchPattern, regexOptions, MatchTimeout); var matches = regex.Matches(textToSearch); foreach (Match match in matches) { if (match.Length < 1) { continue; } if (initParams.VerboseMatchCount && lineEndIndexes.Count > 0) { lineNumber = lineEndIndexes.FindIndex(i => i > match.Index) + 1; } int matchStart = match.Index; int length = match.Length; if (convertedFromWindowsNewline && newlineIndexes != null) { // since the search text is shorter by one for each converted newline, // move the match start by one for each converted Windows newline matchStart += CountWindowsNewLines(0, match.Index, newlineIndexes); length += CountWindowsNewLines(match.Index, match.Index + length, newlineIndexes); } var grepMatch = new GrepMatch(searchPattern, lineNumber, matchStart + filePosition, length); if (match.Groups.Count > 1) { // Note that group 0 is always the whole match for (int idx = 1; idx < match.Groups.Count; idx++) { var group = match.Groups[idx]; if (group.Success) { length = group.Length; if (!regexOptions.HasFlag(RegexOptions.Singleline) && group.Value.EndsWith("\r")) { length -= 1; } grepMatch.Groups.Add( new GrepCaptureGroup(regex.GroupNameFromNumber(idx), group.Index, length, group.Value)); } } } yield return(grepMatch); } }
/// <summary> /// Initializes a new instance of the <see cref="FormattedMatch"/> class. /// </summary> /// <param name="match">The source <see cref="GrepMatch"/>.</param> /// <param name="spans">The resulting <see cref="FormattedSpan"/>s.</param> public FormattedMatch(GrepMatch match, IList <FormattedSpan> spans) { this.Match = match; this.Spans = spans; }
protected override void ColorizeLine(DocumentLine line) { if (result.Matches == null || result.Matches.Count == 0) { return; } int lineStartOffset = line.Offset; int lineNumber = line.LineNumber; var lineResult = result.SearchResults.FirstOrDefault(sr => sr.ClippedFileLineNumber == lineNumber && sr.IsContext == false); if (lineResult != null) { Brush skipBackground = Application.Current.Resources["Match.Skip.Background"] as Brush; Brush skipForeground = Application.Current.Resources["Match.Skip.Foreground"] as Brush; Brush replBackground = Application.Current.Resources["Match.Replace.Background"] as Brush; Brush replForeground = Application.Current.Resources["Match.Replace.Foreground"] as Brush; foreach (var grepMatch in lineResult.Matches) { try { // get the global file match corresponding to this line match // only the file match has a valid ReplaceMatch flag GrepMatch fileMatch = result.Matches.FirstOrDefault(m => m.FileMatchId == grepMatch.FileMatchId); Brush foreground = fileMatch == null ? Brushes.Black : fileMatch.ReplaceMatch ? replForeground : skipForeground; Brush background = fileMatch == null ? Brushes.LightGray : fileMatch.ReplaceMatch ? replBackground : skipBackground; bool isSelected = grepMatch.FileMatchId.Equals(SelectedGrepMatch.FileMatchId); base.ChangeLinePart( lineStartOffset + grepMatch.StartLocation, // startOffset // match may include the non-printing newline chars at the end of the line, don't overflow the length Math.Min(line.EndOffset, lineStartOffset + grepMatch.StartLocation + grepMatch.Length), // endOffset (VisualLineElement element) => { // This lambda gets called once for every VisualLineElement // between the specified offsets. element.TextRunProperties.SetBackgroundBrush(background); element.TextRunProperties.SetForegroundBrush(foreground); if (isSelected) { TextDecorationCollection coll = new TextDecorationCollection { new TextDecoration( TextDecorationLocation.Underline, new Pen(foreground, 2), 0, TextDecorationUnit.Pixel, TextDecorationUnit.Pixel) }; element.TextRunProperties.SetTextDecorations(coll); } }); } catch { // Do nothing } } } }
private InlineCollection FormatLine(GrepLine line) { Paragraph paragraph = new Paragraph(); const int MAX_LINE_LENGTH = 500; string fullLine = line.LineText; if (line.LineText.Length > MAX_LINE_LENGTH) { fullLine = line.LineText.Substring(0, MAX_LINE_LENGTH); } if (line.Matches.Count == 0) { Run mainRun = new Run(fullLine); paragraph.Inlines.Add(mainRun); } else { int counter = 0; GrepMatch[] lineMatches = new GrepMatch[line.Matches.Count]; line.Matches.CopyTo(lineMatches); foreach (GrepMatch m in lineMatches) { try { string regLine = null; string fmtLine = null; if (fullLine.Length < m.StartLocation + m.Length) { regLine = fullLine.Substring(counter, fullLine.Length - counter); } else { regLine = fullLine.Substring(counter, m.StartLocation - counter); fmtLine = fullLine.Substring(m.StartLocation, m.Length); } Run regularRun = new Run(regLine); paragraph.Inlines.Add(regularRun); if (fmtLine != null) { paragraph.Inlines.Add(new Run(fmtLine) { Background = Brushes.Yellow }); } else { break; } } catch { Run regularRun = new Run(fullLine); paragraph.Inlines.Add(regularRun); } finally { counter = m.StartLocation + m.Length; } } if (counter < fullLine.Length) { try { string regLine = fullLine.Substring(counter); Run regularRun = new Run(regLine); paragraph.Inlines.Add(regularRun); } catch { Run regularRun = new Run(fullLine); paragraph.Inlines.Add(regularRun); } } if (line.LineText.Length > MAX_LINE_LENGTH) { string msg = string.Format("...(+{0:n0} characters)", line.LineText.Length - MAX_LINE_LENGTH); paragraph.Inlines.Add(new Run(msg) { Background = Brushes.AliceBlue }); var hiddenMatches = line.Matches.Where(m => m.StartLocation > MAX_LINE_LENGTH).Select(m => m); int count = hiddenMatches.Count(); if (count > 0) { paragraph.Inlines.Add(new Run(" additional matches:")); } // if close to getting them all, then take them all, // otherwise, stop at 20 and just show the remaining count int takeCount = count > 25 ? 20 : count; foreach (GrepMatch m in hiddenMatches.Take(takeCount)) { if (m.StartLocation + m.Length <= line.LineText.Length) { paragraph.Inlines.Add(new Run(" ")); string fmtLine = line.LineText.Substring(m.StartLocation, m.Length); paragraph.Inlines.Add(new Run(fmtLine) { Background = Brushes.Yellow }); if (m.StartLocation + m.Length == line.LineText.Length) { paragraph.Inlines.Add(new Run(" (at end of line)")); } else { paragraph.Inlines.Add(new Run($" at position {m.StartLocation}")); } } } if (count > takeCount) { paragraph.Inlines.Add(new Run($", +{count - takeCount} more matches")); } } } return(paragraph.Inlines); }
private InlineCollection FormatLine(GrepLine line) { Paragraph paragraph = new Paragraph(); const int MAX_LINE_LENGTH = 500; string fullLine = line.LineText; if (line.LineText.Length > MAX_LINE_LENGTH) { fullLine = line.LineText.Substring(0, MAX_LINE_LENGTH); } if (line.Matches.Count == 0) { Run mainRun = new Run(fullLine); paragraph.Inlines.Add(mainRun); } else { int counter = 0; GrepMatch[] lineMatches = new GrepMatch[line.Matches.Count]; line.Matches.CopyTo(lineMatches); foreach (GrepMatch m in lineMatches) { Parent.MatchIdx++; try { string regLine = null; string fmtLine = null; if (m.StartLocation < fullLine.Length) { regLine = fullLine.Substring(counter, m.StartLocation - counter); } if (m.StartLocation + m.Length <= fullLine.Length) { fmtLine = fullLine.Substring(m.StartLocation, m.Length); } else { // match may include the non-printing newline chars at the end of the line: don't overflow the length fmtLine = fullLine.Substring(m.StartLocation, fullLine.Length - m.StartLocation); } if (regLine != null) { Run regularRun = new Run(regLine); paragraph.Inlines.Add(regularRun); } if (fmtLine != null) { if (HighlightCaptureGroups && m.Groups.Count > 0) { FormatCaptureGroups(paragraph, m, fmtLine); } else { var run = new Run(fmtLine); run.SetResourceReference(Run.ForegroundProperty, "Match.Highlight.Foreground"); run.SetResourceReference(Run.BackgroundProperty, "Match.Highlight.Background"); paragraph.Inlines.Add(run); } } else { break; } } catch { Run regularRun = new Run(fullLine); paragraph.Inlines.Add(regularRun); } finally { counter = m.StartLocation + m.Length; } } if (counter < fullLine.Length) { try { string regLine = fullLine.Substring(counter); Run regularRun = new Run(regLine); paragraph.Inlines.Add(regularRun); } catch { Run regularRun = new Run(fullLine); paragraph.Inlines.Add(regularRun); } } if (line.LineText.Length > MAX_LINE_LENGTH) { string msg = string.Format("...(+{0:n0} characters)", line.LineText.Length - MAX_LINE_LENGTH); var msgRun = new Run(msg); msgRun.SetResourceReference(Run.ForegroundProperty, "TreeView.Message.Highlight.Foreground"); msgRun.SetResourceReference(Run.BackgroundProperty, "TreeView.Message.Highlight.Background"); paragraph.Inlines.Add(msgRun); var hiddenMatches = line.Matches.Where(m => m.StartLocation > MAX_LINE_LENGTH).Select(m => m); int count = hiddenMatches.Count(); if (count > 0) { paragraph.Inlines.Add(new Run(" additional matches:")); } // if close to getting them all, then take them all, // otherwise, stop at 20 and just show the remaining count int takeCount = count > 25 ? 20 : count; foreach (GrepMatch m in hiddenMatches.Take(takeCount)) { if (m.StartLocation + m.Length <= line.LineText.Length) { paragraph.Inlines.Add(new Run(" ")); string fmtLine = line.LineText.Substring(m.StartLocation, m.Length); var run = new Run(fmtLine); run.SetResourceReference(Run.ForegroundProperty, "Match.Highlight.Foreground"); run.SetResourceReference(Run.BackgroundProperty, "Match.Highlight.Background"); paragraph.Inlines.Add(run); if (m.StartLocation + m.Length == line.LineText.Length) { paragraph.Inlines.Add(new Run(" (at end of line)")); } else { paragraph.Inlines.Add(new Run($" at position {m.StartLocation}")); } } } if (count > takeCount) { paragraph.Inlines.Add(new Run($", +{count - takeCount} more matches")); } } } return(paragraph.Inlines); }