Skip to content

Commit

Permalink
Fix #482 SearchEngine.replace() should set the wrap flag when appropr…
Browse files Browse the repository at this point in the history
…iate
  • Loading branch information
bobbylight committed Jan 2, 2023
1 parent 24a1538 commit 4b0dbd4
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public static SearchResult find(JTextArea textArea, SearchContext context) {
boolean doMarkAll = textArea instanceof RTextArea && context.getMarkAll();

String text = context.getSearchFor();
if (text == null || text.length() == 0 || textArea.getDocument().getLength() == 0) {
if (text == null || text.isEmpty() || textArea.getDocument().getLength() == 0) {
if (doMarkAll) {
// Force "mark all" event to be broadcast so listeners know to
// clear their mark-all markers. The RSTA already cleared its
Expand All @@ -94,7 +94,7 @@ public static SearchResult find(JTextArea textArea, SearchContext context) {
Math.min(c.getDot(), c.getMark());

String findIn = getFindInText(textArea, start, forward);
if (!context.getSearchWrap() && (findIn == null || findIn.length() == 0)) {
if (!context.getSearchWrap() && (findIn == null || findIn.isEmpty())) {
return new SearchResult();
}

Expand Down Expand Up @@ -123,7 +123,7 @@ public static SearchResult find(JTextArea textArea, SearchContext context) {

findIn = getFindInText(textArea, start, forward);

if (findIn == null || findIn.length() == 0) {
if (findIn == null || findIn.isEmpty()) {
SearchResult emptyResult = new SearchResult();
emptyResult.setWrapped(true);
return emptyResult;
Expand Down Expand Up @@ -227,8 +227,8 @@ private static SearchResult findImpl(String findIn, SearchContext context) {
private static CharSequence getFindInCharSequence(RTextArea textArea,
int start, boolean forward) {
RDocument doc = (RDocument)textArea.getDocument();
int csStart = 0;
int csEnd = 0;
int csStart;
int csEnd;
if (forward) {
csStart = start;
csEnd = doc.getLength();
Expand Down Expand Up @@ -340,44 +340,16 @@ public static int getNextMatchPos(String searchFor, String searchIn,

// Make our variables lower case if we're ignoring case.
if (!matchCase) {
return getNextMatchPosImpl(searchFor.toLowerCase(),
searchIn.toLowerCase(), forward,
matchCase, wholeWord);
searchFor = searchFor.toLowerCase();
searchIn = searchIn.toLowerCase();
}

return getNextMatchPosImpl(searchFor, searchIn, forward,
matchCase, wholeWord);

}


/**
* Actually does the work of matching; assumes searchFor and searchIn
* are already upper/lower-cased appropriately.<br>
* The reason this method is here is to attempt to speed up
* <code>FindInFilesDialog</code>; since it repeatedly calls
* this method instead of <code>getNextMatchPos</code>, it gets better
* performance as it no longer has to allocate a lower-cased string for
* every call.
*
* @param searchFor The string to search for.
* @param searchIn The string to search in.
* @param goForward Whether the search is forward or backward.
* @param matchCase Whether the search is case-sensitive.
* @param wholeWord Whether only whole words should be matched.
* @return The location of the next match, or <code>-1</code> if no
* match was found.
*/
private static int getNextMatchPosImpl(String searchFor,
String searchIn, boolean goForward,
boolean matchCase, boolean wholeWord) {

if (wholeWord) {
int len = searchFor.length();
int temp = goForward ? 0 : searchIn.length();
int tempChange = goForward ? 1 : -1;
int temp = forward ? 0 : searchIn.length();
int tempChange = forward ? 1 : -1;
while (true) {
if (goForward) {
if (forward) {
temp = searchIn.indexOf(searchFor, temp);
}
else {
Expand All @@ -396,7 +368,7 @@ private static int getNextMatchPosImpl(String searchFor,
}
}
else {
return goForward ? searchIn.indexOf(searchFor) :
return forward ? searchIn.indexOf(searchFor) :
searchIn.lastIndexOf(searchFor);
}

Expand Down Expand Up @@ -473,7 +445,7 @@ private static Object getNextMatchPosRegExImpl(String regEx,
// Make a pattern that takes into account whether to match case.
int flags = Pattern.MULTILINE; // '^' and '$' are done per line.
flags = RSyntaxUtilities.getPatternFlags(matchCase, flags);
Pattern pattern = null;
Pattern pattern;
try {
pattern = Pattern.compile(regEx, flags);
} catch (PatternSyntaxException pse) {
Expand Down Expand Up @@ -901,7 +873,7 @@ public static SearchResult replace(RTextArea textArea,
}

String toFind = context.getSearchFor();
if (toFind==null || toFind.length()==0) {
if (toFind==null || toFind.isEmpty()) {
return new SearchResult();
}

Expand Down Expand Up @@ -940,6 +912,7 @@ public static SearchResult replace(RTextArea textArea,
DocumentRange range;
if (next.wasFound()) {
range = next.getMatchRange();
res.setWrapped(next.isWrapped());
}
else {
range = new DocumentRange(dot, dot);
Expand Down Expand Up @@ -983,7 +956,7 @@ public static SearchResult replaceAll(RTextArea textArea,

context.setSearchForward(true); // Replace all always searches forward
String toFind = context.getSearchFor();
if (toFind==null || toFind.length()==0) {
if (toFind==null || toFind.isEmpty()) {
return new SearchResult();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;


/**
* Some very basic unit tests for the {@link SearchEngine} used by
* <code>RTextArea</code>/<code>RSyntaxTextArea</code>.
Expand Down Expand Up @@ -101,30 +102,52 @@ private int replaceAllImpl(SearchContext context) {
}


@BeforeEach
void setUp() throws Exception {
@BeforeAll
static void setUpOnce() throws Exception {

// setUp() is called once per test, each with a new instantiation of
// SearchEngineTest, so check a static variable to ensure that
// initialization is only done once.
StringBuilder sb = new StringBuilder();
InputStream in = SearchEngineTest.class.
getResourceAsStream("SearchEngineTest.txt");
try (BufferedReader br = new BufferedReader(new InputStreamReader(in))) {
String s;
while ((s = br.readLine()) != null) {
sb.append(s).append("\n");
}
}

if (text == null || text.length() <= 0) {
// Strip off last newline
text = sb.substring(0, sb.length()-1);

StringBuilder sb = new StringBuilder();
InputStream in = SearchEngineTest.class.
getResourceAsStream("SearchEngineTest.txt");
try (BufferedReader br = new BufferedReader(new InputStreamReader(in))) {
String s;
while ((s = br.readLine()) != null) {
sb.append(s).append("\n");
}
}
}

// Strip off last newline
text = sb.substring(0, sb.length()-1);

}
@Test
void testSearchEngineFindEmptyDocument() {

testSearchEngineFindEmptyDocumentImpl(false, false, false);
testSearchEngineFindEmptyDocumentImpl(false, true, false);
testSearchEngineFindEmptyDocumentImpl(false, true, true);
testSearchEngineFindEmptyDocumentImpl(false, false, true);

testSearchEngineFindEmptyDocumentImpl(true, false, false);
testSearchEngineFindEmptyDocumentImpl(true, true, false);
testSearchEngineFindEmptyDocumentImpl(true, true, true);
testSearchEngineFindEmptyDocumentImpl(true, false, true);
}


private void testSearchEngineFindEmptyDocumentImpl(boolean forward, boolean regex,
boolean wholeWord) {
textArea.setText(null);

SearchContext context = new SearchContext();
context.setSearchFor("test");
context.setSearchForward(forward);
context.setRegularExpression(regex);
context.setWholeWord(wholeWord);
context.setSearchWrap(true);

assertFalse(findImpl(context));
}


Expand Down Expand Up @@ -460,19 +483,11 @@ private void testSearchEngineFindForwardImpl(boolean markAll) {
*/
@Test
void testSearchEngineFindWrap() {
testSearchEngineWrapImpl();
}

/**
* Tests <code>SearchEngine.find()</code> when searching the entire document.
*
*/
private void testSearchEngineWrapImpl() {
textArea.setText(text);

SearchContext context = new SearchContext();

// Search for "Chuck", non matching case.
// Search for "Chuck", non-matching case.
context.setSearchForward(false);
context.setSearchFor("Chuck");
context.setSearchWrap(false);
Expand All @@ -491,7 +506,7 @@ private void testSearchEngineWrapImpl() {
assertTrue(found);
assertTrue(result.isWrapped());

// Search for "Chuck", non matching case.
// Search for "Chuck", non-matching case.
context.setSearchForward(true);
context.setSearchFor("wood");
context.setSearchWrap(false);
Expand Down Expand Up @@ -664,7 +679,7 @@ void testSearchEngineMarkAll() {
*
* @param forward Whether to test searching forward or backward.
*/
private void testSearchEngineReplace(boolean forward) {
private void testSearchEngineReplaceImpl(boolean forward) {

int offs = forward ? 0 : text.length();
SearchContext context = new SearchContext();
Expand Down Expand Up @@ -811,7 +826,7 @@ private void testSearchEngineReplace(boolean forward) {
*/
@Test
void testSearchEngineReplaceBackward() {
testSearchEngineReplace(false);
testSearchEngineReplaceImpl(false);
}

/**
Expand All @@ -833,7 +848,56 @@ void testSearchEngineReplaceBackwardOnEmptyDocument() {
*/
@Test
void testSearchEngineReplaceForward() {
testSearchEngineReplace(true);
testSearchEngineReplaceImpl(true);
}


/**
* Tests <code>SearchEngine.replace()</code> when searching with wrap.
*/
@Test
void testSearchEngineReplaceWrap() {

textArea.setText("oneoneone");
SearchContext context = new SearchContext();

// Replace the second instance of "one"
context.setSearchForward(true);
context.setSearchFor("one");
context.setReplaceWith("two");
context.setSearchWrap(true);
textArea.setCaretPosition(1);
boolean found = replaceImpl(context);
assertTrue(found);
assertFalse(result.isWrapped());
assertEquals("onetwoone", textArea.getText());
// The next match is selected
assertEquals(6, textArea.getSelectionStart());
assertEquals(9, textArea.getSelectionEnd());

// Replace the third/last instance of "one"
found = replaceImpl(context);
assertTrue(found);
assertTrue(result.isWrapped());
assertEquals("onetwotwo", textArea.getText());
// The first match is selected (wrap)
assertEquals(0, textArea.getSelectionStart());
assertEquals(3, textArea.getSelectionEnd());

// Replace the first/only remaining instance of "one"
found = replaceImpl(context);
assertTrue(found);
assertFalse(result.isWrapped());
assertEquals("twotwotwo", textArea.getText());
assertEquals(3, textArea.getSelectionStart());
assertEquals(3, textArea.getSelectionEnd());

// No change if no more matches
found = replaceImpl(context);
assertFalse(found);
assertEquals("twotwotwo", textArea.getText());
assertEquals(3, textArea.getSelectionStart());
assertEquals(3, textArea.getSelectionEnd());
}


Expand Down

0 comments on commit 4b0dbd4

Please sign in to comment.