diff --git a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/text/IFindReplaceTarget.java b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/text/IFindReplaceTarget.java
index 00042b61a4c..b2804270a34 100644
--- a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/text/IFindReplaceTarget.java
+++ b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/text/IFindReplaceTarget.java
@@ -100,4 +100,23 @@ public interface IFindReplaceTarget {
* @param text the substitution text
*/
void replaceSelection(String text);
+
+ /**
+ * @return true, if its able to handle batch replacements.
+ */
+ default boolean canBatchReplace() {
+ return false;
+ }
+
+ /**
+ * @param findString the string to find.
+ * @param replaceString the string to replace found occurrences.
+ * @param wholeWordSearch search for whole words.
+ * @param caseSensitiveSearch case sensitive search.
+ * @param regexSearch RegEex search.
+ * @param incrementalSearch search in selected lines.
+ */
+ default int batchReplace(String findString, String replaceString, boolean wholeWordSearch, boolean caseSensitiveSearch, boolean regexSearch, boolean incrementalSearch) {
+ return -1;
+ }
}
diff --git a/bundles/org.eclipse.text/META-INF/MANIFEST.MF b/bundles/org.eclipse.text/META-INF/MANIFEST.MF
index cd4309faac7..923f0a1dd86 100644
--- a/bundles/org.eclipse.text/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.text/META-INF/MANIFEST.MF
@@ -9,6 +9,7 @@ Export-Package:
org.eclipse.jface.text; text="split"; mandatory:="text",
org.eclipse.jface.text.link; text="split"; mandatory:="text",
org.eclipse.jface.text.projection,
+ org.eclipse.jface.text.internal,
org.eclipse.jface.text.rules; text="split"; mandatory:="text",
org.eclipse.jface.text.source; text="split"; mandatory:="text",
org.eclipse.jface.text.templates; text="split"; mandatory:="text",
diff --git a/bundles/org.eclipse.text/src/org/eclipse/jface/text/FindReplaceDocumentAdapter.java b/bundles/org.eclipse.text/src/org/eclipse/jface/text/FindReplaceDocumentAdapter.java
index 6cbe87da3dc..8c19df2ee23 100644
--- a/bundles/org.eclipse.text/src/org/eclipse/jface/text/FindReplaceDocumentAdapter.java
+++ b/bundles/org.eclipse.text/src/org/eclipse/jface/text/FindReplaceDocumentAdapter.java
@@ -21,6 +21,8 @@
import org.eclipse.core.runtime.Assert;
+import org.eclipse.jface.text.internal.RegExUtils;
+
/**
* Provides search and replace operations on
@@ -163,14 +165,14 @@ private IRegion findReplace(final FindReplaceOperationCode operationCode, int st
if (regExSearch) {
patternFlags |= Pattern.MULTILINE;
- findString= substituteLinebreak(findString);
+ findString= RegExUtils.substituteLinebreak(findString);
}
if (!caseSensitive)
patternFlags |= Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE;
if (!regExSearch)
- findString= asRegPattern(findString);
+ findString= RegExUtils.asRegPattern(findString);
if (wholeWord)
findString= "\\b" + findString + "\\b"; //$NON-NLS-1$ //$NON-NLS-2$
@@ -262,85 +264,6 @@ private IRegion findReplace(final FindReplaceOperationCode operationCode, int st
return null;
}
- /**
- * Substitutes \R in a regex find pattern with {@code (?>\r\n?|\n)}
- *
- * @param findString the original find pattern
- * @return the transformed find pattern
- * @throws PatternSyntaxException if \R is added at an illegal position (e.g. in a character set)
- * @since 3.4
- */
- private String substituteLinebreak(String findString) throws PatternSyntaxException {
- int length= findString.length();
- StringBuilder buf= new StringBuilder(length);
-
- int inCharGroup= 0;
- int inBraces= 0;
- boolean inQuote= false;
- for (int i= 0; i < length; i++) {
- char ch= findString.charAt(i);
- switch (ch) {
- case '[':
- buf.append(ch);
- if (! inQuote)
- inCharGroup++;
- break;
-
- case ']':
- buf.append(ch);
- if (! inQuote)
- inCharGroup--;
- break;
-
- case '{':
- buf.append(ch);
- if (! inQuote && inCharGroup == 0)
- inBraces++;
- break;
-
- case '}':
- buf.append(ch);
- if (! inQuote && inCharGroup == 0)
- inBraces--;
- break;
-
- case '\\':
- if (i + 1 < length) {
- char ch1= findString.charAt(i + 1);
- if (inQuote) {
- if (ch1 == 'E')
- inQuote= false;
- buf.append(ch).append(ch1);
- i++;
-
- } else if (ch1 == 'R') {
- if (inCharGroup > 0 || inBraces > 0) {
- String msg= TextMessages.getString("FindReplaceDocumentAdapter.illegalLinebreak"); //$NON-NLS-1$
- throw new PatternSyntaxException(msg, findString, i);
- }
- buf.append("(?>\\r\\n?|\\n)"); //$NON-NLS-1$
- i++;
-
- } else {
- if (ch1 == 'Q') {
- inQuote= true;
- }
- buf.append(ch).append(ch1);
- i++;
- }
- } else {
- buf.append(ch);
- }
- break;
-
- default:
- buf.append(ch);
- break;
- }
-
- }
- return buf.toString();
- }
/**
* Interprets current Retain Case mode (all upper-case,all lower-case,capitalized or mixed)
@@ -556,39 +479,6 @@ else if(Character.isUpperCase(foundText.charAt(0))) // is first character upper-
return i;
}
- /**
- * Converts a non-regex string to a pattern
- * that can be used with the regex search engine.
- *
- * @param string the non-regex pattern
- * @return the string converted to a regex pattern
- */
- private String asRegPattern(String string) {
- StringBuilder out= new StringBuilder(string.length());
- boolean quoting= false;
-
- for (int i= 0, length= string.length(); i < length; i++) {
- char ch= string.charAt(i);
- if (ch == '\\') {
- if (quoting) {
- out.append("\\E"); //$NON-NLS-1$
- quoting= false;
- }
- out.append("\\\\"); //$NON-NLS-1$
- continue;
- }
- if (!quoting) {
- out.append("\\Q"); //$NON-NLS-1$
- quoting= true;
- }
- out.append(ch);
- }
- if (quoting)
- out.append("\\E"); //$NON-NLS-1$
-
- return out.toString();
- }
-
/**
* Substitutes the previous match with the given text.
* Sends a DocumentEvent
to all registered IDocumentListener
.
diff --git a/bundles/org.eclipse.text/src/org/eclipse/jface/text/internal/Messages.java b/bundles/org.eclipse.text/src/org/eclipse/jface/text/internal/Messages.java
new file mode 100644
index 00000000000..a4462f7abd2
--- /dev/null
+++ b/bundles/org.eclipse.text/src/org/eclipse/jface/text/internal/Messages.java
@@ -0,0 +1,18 @@
+package org.eclipse.jface.text.internal;
+
+import org.eclipse.osgi.util.NLS;
+
+public class Messages extends NLS {
+ private static final String BUNDLE_NAME= Messages.class.getPackageName() + ".messages"; //$NON-NLS-1$
+
+ public static String RegExUtils_0;
+
+ public static String RegExUtils_IllegalPositionForRegEx;
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ private Messages() {
+ }
+}
diff --git a/bundles/org.eclipse.text/src/org/eclipse/jface/text/internal/RegExUtils.java b/bundles/org.eclipse.text/src/org/eclipse/jface/text/internal/RegExUtils.java
new file mode 100644
index 00000000000..1744262d521
--- /dev/null
+++ b/bundles/org.eclipse.text/src/org/eclipse/jface/text/internal/RegExUtils.java
@@ -0,0 +1,148 @@
+package org.eclipse.jface.text.internal;
+
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+public class RegExUtils {
+
+ /**
+ * Converts a non-regex string to a pattern
+ * that can be used with the regex search engine.
+ *
+ * @param string the non-regex pattern
+ * @return the string converted to a regex pattern
+ */
+ public static String asRegPattern(String string) {
+ StringBuilder out= new StringBuilder(string.length());
+ boolean quoting= false;
+
+ for (int i= 0, length= string.length(); i < length; i++) {
+ char ch= string.charAt(i);
+ if (ch == '\\') {
+ if (quoting) {
+ out.append("\\E"); //$NON-NLS-1$
+ quoting= false;
+ }
+ out.append("\\\\"); //$NON-NLS-1$
+ continue;
+ }
+ if (!quoting) {
+ out.append("\\Q"); //$NON-NLS-1$
+ quoting= true;
+ }
+ out.append(ch);
+ }
+ if (quoting)
+ out.append("\\E"); //$NON-NLS-1$
+
+ return out.toString();
+ }
+
+ /**
+ * Substitutes \R in a regex find pattern with {@code (?>\r\n?|\n)}
+ *
+ * @param findString the original find pattern
+ * @return the transformed find pattern
+ * @throws PatternSyntaxException if \R is added at an illegal position (e.g. in a character set)
+ * @since 3.4
+ */
+ public static String substituteLinebreak(String findString) throws PatternSyntaxException {
+ int length= findString.length();
+ StringBuilder buf= new StringBuilder(length);
+
+ int inCharGroup= 0;
+ int inBraces= 0;
+ boolean inQuote= false;
+ for (int i= 0; i < length; i++) {
+ char ch= findString.charAt(i);
+ switch (ch) {
+ case '[':
+ buf.append(ch);
+ if (! inQuote)
+ inCharGroup++;
+ break;
+
+ case ']':
+ buf.append(ch);
+ if (! inQuote)
+ inCharGroup--;
+ break;
+
+ case '{':
+ buf.append(ch);
+ if (! inQuote && inCharGroup == 0)
+ inBraces++;
+ break;
+
+ case '}':
+ buf.append(ch);
+ if (! inQuote && inCharGroup == 0)
+ inBraces--;
+ break;
+
+ case '\\':
+ if (i + 1 < length) {
+ char ch1= findString.charAt(i + 1);
+ if (inQuote) {
+ if (ch1 == 'E')
+ inQuote= false;
+ buf.append(ch).append(ch1);
+ i++;
+
+ } else if (ch1 == 'R') {
+ if (inCharGroup > 0 || inBraces > 0) {
+ String msg= Messages.RegExUtils_IllegalPositionForRegEx;
+ throw new PatternSyntaxException(msg, findString, i);
+ }
+ buf.append("(?>\\r\\n?|\\n)"); //$NON-NLS-1$
+ i++;
+
+ } else {
+ if (ch1 == 'Q') {
+ inQuote= true;
+ }
+ buf.append(ch).append(ch1);
+ i++;
+ }
+ } else {
+ buf.append(ch);
+ }
+ break;
+
+ default:
+ buf.append(ch);
+ break;
+ }
+
+ }
+ return buf.toString();
+ }
+
+ /**
+ * Creates the Pattern according to the flags.
+ * @param findString the find string.
+ * @param wholeWord find whole words.
+ * @param caseSensitive search case sensitive.
+ * @param regExSearch is RegEx search
+ * @return a Pattern which can directly be used.
+ */
+ public static Pattern createRegexSearchPattern(String findString, boolean wholeWord, boolean caseSensitive, boolean regExSearch) {
+ int patternFlags = 0;
+ if (regExSearch) {
+ patternFlags |= Pattern.MULTILINE;
+ findString = RegExUtils.substituteLinebreak(findString);
+ }
+
+ if (!caseSensitive)
+ patternFlags |= Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE;
+
+ if (!regExSearch)
+ findString = RegExUtils.asRegPattern(findString);
+
+ if (wholeWord)
+ findString = "\\b" + findString + "\\b"; //$NON-NLS-1$ //$NON-NLS-2$
+
+ return Pattern.compile(findString, patternFlags);
+ }
+
+}
diff --git a/bundles/org.eclipse.text/src/org/eclipse/jface/text/internal/messages.properties b/bundles/org.eclipse.text/src/org/eclipse/jface/text/internal/messages.properties
new file mode 100644
index 00000000000..7dd20a1aa79
--- /dev/null
+++ b/bundles/org.eclipse.text/src/org/eclipse/jface/text/internal/messages.properties
@@ -0,0 +1 @@
+RegExUtils_IllegalPositionForRegEx=Illegal position for \\\\R
\ No newline at end of file
diff --git a/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/text/TextEditorDefaultsPreferencePage.java b/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/text/TextEditorDefaultsPreferencePage.java
index 1e2ea237271..4eb738b1912 100644
--- a/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/text/TextEditorDefaultsPreferencePage.java
+++ b/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/text/TextEditorDefaultsPreferencePage.java
@@ -731,6 +731,7 @@ private OverlayPreferenceStore createOverlayStore() {
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, AbstractTextEditor.PREFERENCE_COLOR_FIND_SCOPE));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE_COLOR));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_BATCH_REPLACE));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_USE_FIND_REPLACE_OVERLAY));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_FIND_REPLACE_OVERLAY_AT_BOTTOM));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE));
@@ -866,6 +867,10 @@ public void widgetSelected(SelectionEvent e) {
IntegerDomain lineSpaceDomain= new IntegerDomain(0, 1000);
addTextField(appearanceComposite, lineSpacing, lineSpaceDomain, 15, 0);
+ label= TextEditorMessages.TextEditorDefaultsPreferencePage_batchReplace;
+ Preference batchReplace= new Preference(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_BATCH_REPLACE, label, null);
+ addCheckBox(appearanceComposite, batchReplace, new BooleanDomain(), 0);
+
label= TextEditorMessages.TextEditorPreferencePage_useFindReplaceOverlay;
Preference useFindReplaceOverlay= new Preference(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_USE_FIND_REPLACE_OVERLAY, label, null);
final Button useOverlay= addCheckBox(appearanceComposite, useFindReplaceOverlay, new BooleanDomain(), 0);
diff --git a/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/text/TextEditorMessages.java b/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/text/TextEditorMessages.java
index 92a3d48a385..89db0066895 100644
--- a/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/text/TextEditorMessages.java
+++ b/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/text/TextEditorMessages.java
@@ -138,6 +138,7 @@ private TextEditorMessages() {
NLS.initializeMessages(BUNDLE_NAME, TextEditorMessages.class);
}
+ public static String TextEditorDefaultsPreferencePage_batchReplace;
public static String TextEditorDefaultsPreferencePage_carriageReturn;
public static String TextEditorDefaultsPreferencePage_transparencyLevel;
public static String TextEditorDefaultsPreferencePage_codeMinings_description;
diff --git a/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/text/TextEditorMessages.properties b/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/text/TextEditorMessages.properties
index c0141258985..cdfbe8f9c9c 100644
--- a/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/text/TextEditorMessages.properties
+++ b/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/text/TextEditorMessages.properties
@@ -40,6 +40,7 @@ TextEditorPreferencePage_findScopeColor=Find scope
TextEditorPreferencePage_accessibility_disableCustomCarets= Use &custom caret
TextEditorPreferencePage_accessibility_wideCaret= &Enable thick caret
TextEditorPreferencePage_accessibility_useSaturatedColorsInOverviewRuler=U&se saturated colors in overview ruler
+TextEditorDefaultsPreferencePage_batchReplace=Enable batch replace for search and replace all.
TextEditorDefaultsPreferencePage_carriageReturn=Carriage Return ( \u00a4 )
TextEditorDefaultsPreferencePage_transparencyLevel=&Transparency level (0 is transparent and 255 is opaque):
TextEditorDefaultsPreferencePage_codeMinings_description=How annotations should be shown in-line in text editors which support code minings
diff --git a/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/texteditor/AbstractDecoratedTextEditorPreferenceConstants.java b/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/texteditor/AbstractDecoratedTextEditorPreferenceConstants.java
index ebae43ed79c..2f1e224be93 100644
--- a/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/texteditor/AbstractDecoratedTextEditorPreferenceConstants.java
+++ b/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/texteditor/AbstractDecoratedTextEditorPreferenceConstants.java
@@ -221,6 +221,19 @@ private AbstractDecoratedTextEditorPreferenceConstants() {
*/
public final static String EDITOR_LINE_NUMBER_RULER= "lineNumberRuler"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls the enablement of batch replace.
+ *
+ *
+ * The preference value is of type Boolean
+ *