string ReplaceOneMatch(string src, string replacement, List <SearchMatch> matches, int matchIndex) { if (matches == null || matches.Count == 0) { return(src); } SearchMatch match = matches[matchIndex]; // replace text if (isEscaped) { replacement = Unescape(replacement); } if (isRegex) { replacement = ExpandGroups(replacement, match); } src = src.Substring(0, match.Index) + replacement + src.Substring(match.Index + match.Length); // update next matches if (matches.Count > matchIndex + 1) { PadIndexes(matches, matchIndex + 1, match.Value, replacement); } return(src); }
/// <summary> /// Finds the next result based on direction /// </summary> public void FindNext(Boolean forward, Boolean update, Boolean simple) { this.currentMatch = null; if (update) this.UpdateFindText(); if (Globals.SciControl == null) return; ScintillaControl sci = Globals.SciControl; List<SearchMatch> matches = this.GetResults(sci, simple); if (matches != null && matches.Count != 0) { FRDialogGenerics.UpdateComboBoxItems(this.findComboBox); SearchMatch match = FRDialogGenerics.GetNextDocumentMatch(sci, matches, forward, false); if (match != null) { this.currentMatch = match; FRDialogGenerics.SelectMatch(sci, match); this.lookupIsDirty = false; } if (this.Visible) { Int32 index = FRDialogGenerics.GetMatchIndex(match, matches); String message = TextHelper.GetString("Info.ShowingResult"); String formatted = String.Format(message, index, matches.Count); this.ShowMessage(formatted, 0); } } else { if (this.Visible) { String message = TextHelper.GetString("Info.NoMatchesFound"); this.ShowMessage(message, 0); } } this.SelectText(); }
/** TODO : needs something like SearchOptions flags to be functional * * /// <summary> * /// Quick search * /// </summary> * /// <param name="pattern">Search pattern</param> * /// <param name="input">Source text</param> * /// <returns>First result</returns> * static public SearchMatch Match(string pattern, string input, SearchOptions options) * { * Search search = new Search(pattern); * // eval options * return search.Match(input); * } * * /// <summary> * /// Quick search * /// </summary> * /// <param name="pattern">Search pattern</param> * /// <param name="input">Source text</param> * /// <returns>All results</returns> * static public List<SearchMatch> Matches(string pattern, string input, SearchOptions options) * { * Search search = new Search(pattern); * // eval options * return search.Matches(input); * } * * /// <summary> * /// Quick replace * /// </summary> * /// <param name="pattern">Search pattern</param> * /// <param name="input">Source text</param> * /// <param name="replacement">Replacement pattern</param> * /// <returns></returns> * static public string Replace(string pattern, string input, string replacement, SearchOptions options) * { * Search search = new Search(pattern); * // eval options * List<SearchMatch> matches = search.Matches(input); * return search.ReplaceAll(input, replacement, matches); * } */ #endregion #region Public Replace Methods /// <summary> /// Replace one search result /// </summary> /// <param name="input">Source text</param> /// <param name="replacement">Replacement pattern</param> /// <param name="match">Search result to replace</param> /// <returns>Updated text</returns> public string Replace(string input, string replacement, SearchMatch match) { List <SearchMatch> matches = new List <SearchMatch>(); matches.Add(match); return(ReplaceOneMatch(input, replacement, matches, 0)); }
/// <summary> /// Selects a search match /// </summary> public static void SelectMatch(ScintillaControl sci, SearchMatch match) { Int32 start = sci.MBSafePosition(match.Index); // wchar to byte position Int32 end = start + sci.MBSafeTextLength(match.Value); // wchar to byte text length Int32 line = sci.LineFromPosition(start); sci.EnsureVisible(line); sci.SetSel(start, end); }
/// <summary> /// Gets an index of the search match /// </summary> public static Int32 GetMatchIndex(SearchMatch match, List<SearchMatch> matches) { for (Int32 i = 0; i < matches.Count; i++) { if (match == matches[i]) return i + 1; } return -1; }
/// <summary> /// Replace regular expressions groups in replacement text /// </summary> /// <param name="escapedText">Text to expand</param> /// <param name="match">Search result (for reinjecting groups)</param> static public string ExpandGroups(string text, SearchMatch match) { if (text.IndexOf('$') < 0) { return(text); } for (int i = 0; i < match.Groups.Length; i++) { text = text.Replace("$" + i, match.Groups[i].Value); } return(text); }
/** TODO : needs something like SearchOptions flags to be functional /// <summary> /// Quick search /// </summary> /// <param name="pattern">Search pattern</param> /// <param name="input">Source text</param> /// <returns>First result</returns> static public SearchMatch Match(string pattern, string input, SearchOptions options) { Search search = new Search(pattern); // eval options return search.Match(input); } /// <summary> /// Quick search /// </summary> /// <param name="pattern">Search pattern</param> /// <param name="input">Source text</param> /// <returns>All results</returns> static public List<SearchMatch> Matches(string pattern, string input, SearchOptions options) { Search search = new Search(pattern); // eval options return search.Matches(input); } /// <summary> /// Quick replace /// </summary> /// <param name="pattern">Search pattern</param> /// <param name="input">Source text</param> /// <param name="replacement">Replacement pattern</param> /// <returns></returns> static public string Replace(string pattern, string input, string replacement, SearchOptions options) { Search search = new Search(pattern); // eval options List<SearchMatch> matches = search.Matches(input); return search.ReplaceAll(input, replacement, matches); } */ #endregion #region Public Replace Methods /// <summary> /// Replace one search result /// </summary> /// <param name="input">Source text</param> /// <param name="replacement">Replacement pattern</param> /// <param name="match">Search result to replace</param> /// <returns>Updated text</returns> public string Replace(string input, string replacement, SearchMatch match) { List<SearchMatch> matches = new List<SearchMatch>(); matches.Add(match); return ReplaceOneMatch(input, replacement, matches, 0); }
/// <summary> /// Marks the lookup as dirty /// </summary> private void LookupChanged(Object sender, System.EventArgs e) { if (this.Visible) { this.lookupIsDirty = true; this.currentMatch = null; } if (sender == this.matchCaseCheckBox && !Globals.Settings.DisableFindOptionSync) { Globals.MainForm.SetMatchCase(this, this.matchCaseCheckBox.Checked); } if (sender == this.wholeWordCheckBox && !Globals.Settings.DisableFindOptionSync) { Globals.MainForm.SetWholeWord(this, this.wholeWordCheckBox.Checked); } }
public static bool IsInsideCommentOrString(SearchMatch match, ScintillaControl sci, bool includeComments, bool includeStrings) { int style = sci.BaseStyleAt(match.Index); return includeComments && IsCommentStyle(style) || includeStrings && IsStringStyle(style); }
/// <summary> /// Checks if a given search match actually points to the given target source /// </summary /// <returns>True if the SearchMatch does point to the target source.</returns> public static bool DoesMatchPointToTarget(ScintillaNet.ScintillaControl Sci, SearchMatch match, ASResult target, DocumentHelper associatedDocumentHelper) { if (Sci == null || target == null) return false; FileModel targetInFile = null; if (target.InFile != null) targetInFile = target.InFile; else if (target.Member != null && target.InClass == null) targetInFile = target.Member.InFile; Boolean matchMember = targetInFile != null && target.Member != null; Boolean matchType = target.Member == null && target.IsStatic && target.Type != null; if (!matchMember && !matchType) return false; ASResult result = null; // get type at match position if (match.Index < Sci.Text.Length) // TODO: find out rare cases of incorrect index reported { result = DeclarationLookupResult(Sci, Sci.MBSafePosition(match.Index) + Sci.MBSafeTextLength(match.Value)); if (associatedDocumentHelper != null) { // because the declaration lookup opens a document, we should register it with the document helper to be closed later associatedDocumentHelper.RegisterLoadedDocument(PluginBase.MainForm.CurrentDocument); } } // check if the result matches the target if (result == null || (result.InFile == null && result.Type == null)) return false; if (matchMember) { if (result.Member == null) return false; var resultInFile = result.InClass != null ? result.InFile : result.Member.InFile; return resultInFile.BasePath == targetInFile.BasePath && resultInFile.FileName == targetInFile.FileName && result.Member.LineFrom == target.Member.LineFrom && result.Member.Name == target.Member.Name; } else // type { if (result.Type == null) return false; if (result.Type.QualifiedName == target.Type.QualifiedName) return true; return false; } }
/// <summary> /// Display the match into the treelistview /// </summary> /// <param name="match"></param> /// <param name="index"></param> private void TestRegExpMatch_DisplayResults(Match match, Int32 index) { Debug.WriteLine("TestRegExp_DisplayResults(2)"); MyNode item; MyNode node; Group group; SearchMatch s_match; if (match.Success) { item = new MyNode("Group " + index + " Group(0)", match.Index + "-" + (match.Index + match.Length), match.Value); item.Spans = new int[] { match.Index, match.Length }; if (match.Groups.Count > 1) { for (int k = 1; k < match.Groups.Count; k++) { group = match.Groups[k]; node = new MyNode("Group " + index + " Group(" + k + ")", group.Index + "-" + (group.Index + group.Length), group.Value); node.Spans = new int[] { group.Index, group.Length }; item.Nodes.Add(node); } s_match = new SearchMatch(); s_match.Index = match.Index; s_match.Length = match.Length; s_match.Value = match.Value; AddHighlight(this.matchTextSci, s_match); } this.matchResultModel.Nodes.Add(item); } }
/// <summary> /// Selection changed into the treelistview /// then hilight the selection into the scintilla control /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void matchResultTree_SelectionChanged(object sender, System.EventArgs e) { Debug.WriteLine("matchResultTree_SelectionChanged"); MyNode node; if (this.matchResultTree.SelectedNode != null) { if (this.matchResultTree.SelectedNode.Tag != null) { node = (MyNode)this.matchResultTree.SelectedNode.Tag; SearchMatch match = new SearchMatch(); match.Index = node.Spans[0]; match.Length = node.Spans[1]; match.Value = node.Text; SelectMatch(this.matchTextSci, match); } } }
/// <summary> /// Highlight a regexp match group /// </summary> /// <param name="sci"></param> /// <param name="matches"></param> private void AddHighlight(ScintillaControl sci, SearchMatch match) { Int32 start = sci.MBSafePosition(match.Index); // wchar to byte position Int32 end = start + sci.MBSafeTextLength(match.Value); // wchar to byte text length Int32 line = sci.LineFromPosition(start); Int32 position = start; Int32 es = sci.EndStyled; Int32 mask = 1 << sci.StyleBits; sci.SetIndicStyle(0, (Int32)ScintillaNet.Enums.IndicatorStyle.Max); sci.SetIndicFore(0, 0xff0000); sci.StartStyling(position, mask); sci.SetStyling(end - start, mask); sci.StartStyling(es, mask - 1); }
private List <SearchMatch> SearchSource(string src, int startIndex, int startLine) { List <SearchMatch> results = new List <SearchMatch>(); // raw search results if (needParsePattern) { BuildRegex(pattern); } if (operation == null) { return(results); } MatchCollection matches = operation.Matches(src, startIndex); if (matches.Count == 0) { return(results); } // index sources int len = src.Length; int pos = startIndex - 1; int line = startLine; List <int> lineStart = new List <int>(); for (int i = 0; i < startLine; i++) { lineStart.Add(startIndex); } char c = ' '; bool hadNL = false; int matchIndex = 0; int matchCount = matches.Count; Match match = matches[0]; int nextPos = match.Index; // filters bool inComments = (filter & SearchFilter.InCodeComments) > 0; bool outComments = (filter & SearchFilter.OutsideCodeComments) > 0; bool filterComments = inComments || outComments; int commentMatch = 0; bool inLiterals = (filter & SearchFilter.InStringLiterals) > 0; bool outLiterals = (filter & SearchFilter.OutsideStringLiterals) > 0; bool filterLiterals = inLiterals || outLiterals; int literalMatch = 0; while (pos < len - 1) { c = src[++pos]; // counting lines hadNL = false; if (c == '\n') { line++; hadNL = true; } else if (c == '\r') { if (pos < len - 1 && src[pos + 1] != '\n') { line++; hadNL = true; } } if (hadNL) { lineStart.Add(pos + 1); } // filters if (filterComments || filterLiterals) { if (literalMatch == 0) // discover comments if not in a literal { if (commentMatch == 0) { if (c == '/' && pos < len - 1) { if (src[pos + 1] == '*') { commentMatch = 1; } else if (src[pos + 1] == '/') { commentMatch = 2; } else { LookupRegex(src, ref pos); } } } else if (commentMatch == 1) { if (c == '*' && pos < len - 1 && src[pos + 1] == '/') { commentMatch = 0; } } else if (commentMatch == 2) { if (hadNL) { commentMatch = 0; } } if ((inComments && commentMatch == 0) || (outComments && commentMatch > 0)) { continue; } } if (commentMatch == 0) // discover literals if not in a comment { if (literalMatch == 0) { if (c == '"') { literalMatch = 1; } else if (c == '\'') { literalMatch = 2; } } else if (pos > 1) { if (literalMatch == 1) { if (src[pos - 1] != '\\' && c == '"') { literalMatch = 0; } } else if (literalMatch == 2) { if (src[pos - 1] != '\\' && c == '\'') { literalMatch = 0; } } } if ((inLiterals && literalMatch == 0) || (outLiterals && literalMatch > 0)) { continue; } } } // wait for next match while (pos > nextPos) { if (++matchIndex == matchCount) { match = null; break; } match = matches[matchIndex]; nextPos = match.Index; } if (match == null) { break; } if (pos < nextPos) { continue; } // store match data SearchMatch sm = new SearchMatch(); sm.Index = match.Index; sm.Value = match.Value; sm.Length = match.Length; sm.Line = line; sm.LineStart = sm.LineEnd = lineStart[line - 1]; sm.Column = match.Index - sm.LineStart; int gcount = match.Groups.Count; sm.Groups = new SearchGroup[gcount]; for (int i = 0; i < gcount; i++) { Group group = match.Groups[i]; sm.Groups[i] = new SearchGroup(group.Index, group.Length, group.Value); } results.Add(sm); if (!returnAllMatches) { break; } } // last line end while (pos < len && c != '\r' && c != '\n') { c = src[pos++]; } if (c == '\r' || c == '\n') { pos--; } lineStart.Add(pos); // extract line texts int maxLine = lineStart.Count; foreach (SearchMatch sm in results) { int endIndex = sm.Index + sm.Length; int endLine = sm.Line + 1; while (endLine < maxLine && lineStart[endLine - 1] < endIndex) { endLine++; } sm.LineEnd = lineStart[endLine - 1]; } return(results); }
private List<SearchMatch> SearchSource(string src, int startIndex, int startLine) { List<SearchMatch> results = new List<SearchMatch>(); // raw search results if (needParsePattern) BuildRegex(pattern); if (operation == null) return results; MatchCollection matches = operation.Matches(src, startIndex); if (matches.Count == 0) return results; // index sources int len = src.Length; int pos = startIndex - 1; int line = startLine; List<int> lineStart = new List<int>(); for (int i = 0; i < startLine; i++) lineStart.Add(startIndex); char c = ' '; bool hadNL = false; int matchIndex = 0; int matchCount = matches.Count; Match match = matches[0]; int nextPos = match.Index; // filters bool inComments = (filter & SearchFilter.InCodeComments) > 0; bool outComments = (filter & SearchFilter.OutsideCodeComments) > 0; bool filterComments = inComments || outComments; int commentMatch = 0; bool inLiterals = (filter & SearchFilter.InStringLiterals) > 0; bool outLiterals = (filter & SearchFilter.OutsideStringLiterals) > 0; bool filterLiterals = inLiterals || outLiterals; int literalMatch = 0; while (pos < len - 1) { c = src[++pos]; // counting lines hadNL = false; if (c == '\n') { line++; hadNL = true; } else if (c == '\r') { if (pos < len - 1 && src[pos + 1] != '\n') { line++; hadNL = true; } } if (hadNL) { lineStart.Add(pos + 1); } // filters if (filterComments || filterLiterals) { if (literalMatch == 0) // discover comments if not in a literal { if (commentMatch == 0) { if (c == '/' && pos < len - 1) if (src[pos + 1] == '*') commentMatch = 1; else if (src[pos + 1] == '/') commentMatch = 2; else LookupRegex(src, ref pos); } else if (commentMatch == 1) { if (c == '*' && pos < len - 1 && src[pos + 1] == '/') commentMatch = 0; } else if (commentMatch == 2) { if (hadNL) commentMatch = 0; } if ((inComments && commentMatch == 0) || (outComments && commentMatch > 0)) continue; } if (commentMatch == 0) // discover literals if not in a comment { if (literalMatch == 0) { if (c == '"') literalMatch = 1; else if (c == '\'') literalMatch = 2; } else if (pos > 1) if (literalMatch == 1) { if (src[pos - 1] != '\\' && c == '"') literalMatch = 0; } else if (literalMatch == 2) { if (src[pos - 1] != '\\' && c == '\'') literalMatch = 0; } if ((inLiterals && literalMatch == 0) || (outLiterals && literalMatch > 0)) continue; } } // wait for next match while (pos > nextPos) { if (++matchIndex == matchCount) { match = null; break; } match = matches[matchIndex]; nextPos = match.Index; } if (match == null) break; if (pos < nextPos) continue; // store match data SearchMatch sm = new SearchMatch(); sm.Index = match.Index; sm.Value = match.Value; sm.Length = match.Length; sm.Line = line; sm.LineStart = sm.LineEnd = lineStart[line - 1]; sm.Column = match.Index - sm.LineStart; int gcount = match.Groups.Count; sm.Groups = new SearchGroup[gcount]; for (int i = 0; i < gcount; i++) { Group group = match.Groups[i]; sm.Groups[i] = new SearchGroup(group.Index, group.Length, group.Value); } results.Add(sm); if (!returnAllMatches) break; } // last line end while (pos < len && c != '\r' && c != '\n') c = src[pos++]; if (c == '\r' || c == '\n') pos--; lineStart.Add(pos); // extract line texts int maxLine = lineStart.Count; foreach(SearchMatch sm in results) { int endIndex = sm.Index + sm.Length; int endLine = sm.Line + 1; while (endLine < maxLine && lineStart[endLine - 1] < endIndex) endLine++; sm.LineEnd = lineStart[endLine - 1]; } return results; }
private void TestRegExpSearch_DisplayResults(Match match) { Debug.WriteLine("TestRegExpSearch_DisplayResults"); MyNode item; SearchMatch s_match; if (match.Success) { item = new MyNode("Result (" + match.Index + ")", match.Index + "-" + (match.Index + match.Length), match.Value); item.Spans = new int[] { match.Index, match.Length }; s_match = new SearchMatch(); s_match.Index = match.Index; s_match.Length = match.Length; s_match.Value = match.Value; AddHighlight(this.matchTextSci, s_match); this.matchResultModel.Nodes.Add(item); } }
/// <summary> /// Replace regular expressions groups in replacement text /// </summary> /// <param name="escapedText">Text to expand</param> /// <param name="match">Search result (for reinjecting groups)</param> static public string ExpandGroups(string text, SearchMatch match) { if (text.IndexOf('$') < 0) return text; for (int i = 0; i < match.Groups.Length; i++) text = text.Replace("$" + i, match.Groups[i].Value); return text; }
/// <summary> /// Gets the replacement text and escapes it if needed /// </summary> private String GetReplaceText(SearchMatch match) { String replace = this.replaceComboBox.Text; if (this.escapedCheckBox.Checked) replace = FRSearch.Unescape(replace); if (this.useRegexCheckBox.Checked) replace = FRSearch.ExpandGroups(replace, match); return replace; }
/// <summary> /// Checks if the given match actually is the declaration. /// </summary> public static bool IsMatchTheTarget(ScintillaNet.ScintillaControl Sci, SearchMatch match, ASResult target) { if (Sci == null || target == null || target.InFile == null || target.Member == null) { return false; } String originalFile = Sci.FileName; // get type at match position ASResult declaration = DeclarationLookupResult(Sci, Sci.MBSafePosition(match.Index) + Sci.MBSafeTextLength(match.Value)); return (declaration.InFile != null && originalFile == declaration.InFile.FileName) && (Sci.CurrentPos == (Sci.MBSafePosition(match.Index) + Sci.MBSafeTextLength(match.Value))); }
/// <summary> /// Checks if a given search match actually points to the given target source /// </summary /// <returns>True if the SearchMatch does point to the target source.</returns> static public bool DoesMatchPointToTarget(ScintillaNet.ScintillaControl Sci, SearchMatch match, ASResult target, DocumentHelper associatedDocumentHelper) { if (Sci == null || target == null || target.inFile == null || target.Member == null) { return false; } // get type at match position ASResult result = DeclarationLookupResult(Sci, Sci.MBSafePosition(match.Index) + Sci.MBSafeTextLength(match.Value)); if (associatedDocumentHelper != null) { // because the declaration lookup opens a document, we should register it with the document helper to be closed later associatedDocumentHelper.RegisterLoadedDocument(PluginBase.MainForm.CurrentDocument); } // check if the result matches the target // TODO: this method of checking their equality seems pretty crude -- is there a better way? if (result == null || result.inFile == null || result.Member == null) { return false; } Boolean doesMatch = result.inFile.BasePath == target.inFile.BasePath && result.inFile.FileName == target.inFile.FileName && result.Member.LineFrom == target.Member.LineFrom && result.Member.Name == target.Member.Name; return (doesMatch); }