From 11ac73633bfec109b7146361759b793475872e6c Mon Sep 17 00:00:00 2001 From: Marcus Hoepfner Date: Tue, 19 Dec 2023 16:37:43 +0100 Subject: [PATCH 1/7] Show ZWSP (zero with space) as code mining Issue: https://github.com/eclipse-platform/eclipse.platform.ui/issues/1002 For more information refer to https://www.compart.com/en/unicode/U+200B To get a ZWSP refer to https://zerowidthspace.me/ --- .../TextEditorDefaultsPreferencePage.java | 17 +++- .../editors/text/TextEditorMessages.java | 1 + .../text/TextEditorMessages.properties | 1 + ...ecoratedTextEditorPreferenceConstants.java | 17 +++- .../plugin.properties | 2 + .../plugin.xml | 10 +- .../ZeroWidthSpaceLineContentCodeMining.java | 37 +++++++ ...dthSpaceLineContentCodeMiningProvider.java | 97 +++++++++++++++++++ .../ui/texteditor/AbstractTextEditor.java | 15 ++- 9 files changed, 192 insertions(+), 5 deletions(-) create mode 100644 bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthSpaceLineContentCodeMining.java create mode 100644 bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthSpaceLineContentCodeMiningProvider.java 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 0c2f05e44c1..01b1a5c6714 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 @@ -68,6 +68,8 @@ import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.widgets.ButtonFactory; +import org.eclipse.jface.widgets.WidgetFactory; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; @@ -451,7 +453,9 @@ private OverlayPreferenceStore createDialogOverlayStore() { overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_ENCLOSED_TABS)); overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_TRAILING_TABS)); overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_CARRIAGE_RETURN)); - overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_LINE_FEED)); + overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_LINE_FEED)); + overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, + AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_ZWSP)); overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.INT, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_WHITESPACE_CHARACTER_ALPHA_VALUE)); OverlayPreferenceStore.OverlayKey[] keys= new OverlayPreferenceStore.OverlayKey[overlayKeys.size()]; @@ -571,6 +575,15 @@ protected Control createDialogArea(Composite parent) { preference= new Preference(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_LINE_FEED, "", null); //$NON-NLS-1$ addCheckBox(tabularComposite, preference, new BooleanDomain(), 0); + WidgetFactory.label(SWT.NONE).text(TextEditorMessages.TextEditorDefaultsPreferencePage_zwsp) + .layoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false)).create(tabularComposite); + ButtonFactory checkboxFactory = WidgetFactory.button(SWT.CHECK) + .supplyLayoutData(() -> new GridData(SWT.CENTER, SWT.CENTER, false, false)).enabled(false); + checkboxFactory.create(tabularComposite); + preference = new Preference(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_ZWSP, "", null); //$NON-NLS-1$ + addCheckBox(tabularComposite, preference, new BooleanDomain(), 0); + checkboxFactory.create(tabularComposite); + Composite alphaComposite= new Composite(composite, SWT.NONE); layout= new GridLayout(); layout.numColumns= 2; @@ -809,6 +822,8 @@ private OverlayPreferenceStore createOverlayStore() { overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_TRAILING_TABS)); overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_CARRIAGE_RETURN)); overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_LINE_FEED)); + overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, + AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_ZWSP)); overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.INT, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_WHITESPACE_CHARACTER_ALPHA_VALUE)); OverlayPreferenceStore.OverlayKey[] keys= new OverlayPreferenceStore.OverlayKey[overlayKeys.size()]; 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..05cbdbefd4f 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 @@ -159,6 +159,7 @@ private TextEditorMessages() { public static String TextEditorDefaultsPreferencePage_ideographicSpace; public static String TextEditorDefaultsPreferencePage_leading; public static String TextEditorDefaultsPreferencePage_lineFeed; + public static String TextEditorDefaultsPreferencePage_zwsp; public static String TextEditorDefaultsPreferencePage_range_indicator; public static String TextEditorDefaultsPreferencePage_smartHomeEnd; public static String TextEditorDefaultsPreferencePage_warn_if_derived; 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 2e5a7267edc..5fea721c2ad 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 @@ -61,6 +61,7 @@ TextEditorDefaultsPreferencePage_enrichHover_onClick=Enrich on click TextEditorDefaultsPreferencePage_ideographicSpace=Ideographic space ( \u00b0 ) TextEditorDefaultsPreferencePage_leading=Leading TextEditorDefaultsPreferencePage_lineFeed=Line Feed ( \u00b6 ) +TextEditorDefaultsPreferencePage_zwsp=ZWSP (Zero-Width Space) TextEditorDefaultsPreferencePage_range_indicator=Show &range indicator TextEditorDefaultsPreferencePage_warn_if_derived= War&n before editing a derived file TextEditorDefaultsPreferencePage_smartHomeEnd= &Smart caret positioning at line start and end 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 3c1a98e38e5..19a68b60f12 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 @@ -502,7 +502,8 @@ private AbstractDecoratedTextEditorPreferenceConstants() { *

* *

- * The following preferences can be used for fine-grained configuration when enabled. + * The following preferences can be used for fine-grained configuration when + * enabled. *

* * @@ -647,6 +649,18 @@ private AbstractDecoratedTextEditorPreferenceConstants() { */ public static final String EDITOR_SHOW_LINE_FEED= AbstractTextEditor.PREFERENCE_SHOW_LINE_FEED; + /** + * A named preference that controls the display of ZWSP (zero-with space) + * characters. The value is used only if the value of + * {@link #EDITOR_SHOW_WHITESPACE_CHARACTERS} is true. + *

+ * Value is of type Boolean. + *

+ * + * @since 3.? + */ + public static final String EDITOR_SHOW_ZWSP = AbstractTextEditor.PREFERENCE_SHOW_ZWSP; + /** * A named preference that controls the alpha value of whitespace characters. The value is used * only if the value of {@link #EDITOR_SHOW_WHITESPACE_CHARACTERS} is true. @@ -858,6 +872,7 @@ public static void initializeDefaultValues(IPreferenceStore store) { store.setDefault(EDITOR_SHOW_TRAILING_TABS, true); store.setDefault(EDITOR_SHOW_CARRIAGE_RETURN, true); store.setDefault(EDITOR_SHOW_LINE_FEED, true); + store.setDefault(EDITOR_SHOW_ZWSP, true); store.setDefault(EDITOR_WHITESPACE_CHARACTER_ALPHA_VALUE, 80); store.setDefault(EDITOR_TEXT_DRAG_AND_DROP_ENABLED, true); diff --git a/bundles/org.eclipse.ui.workbench.texteditor/plugin.properties b/bundles/org.eclipse.ui.workbench.texteditor/plugin.properties index f647d810d8d..309a98d7429 100644 --- a/bundles/org.eclipse.ui.workbench.texteditor/plugin.properties +++ b/bundles/org.eclipse.ui.workbench.texteditor/plugin.properties @@ -215,3 +215,5 @@ blockSelectionModeFont.label= Text Editor Block Selection Font blockSelectionModeFont.description= The block selection mode font is used by text editors in block (column) mode. A monospace font should be used. MinimapView.name=Minimap + +CodeMining.show.ZWSP=Show ZWSP (Zero-Width Space) diff --git a/bundles/org.eclipse.ui.workbench.texteditor/plugin.xml b/bundles/org.eclipse.ui.workbench.texteditor/plugin.xml index e2ef210299f..e36930a7a0f 100644 --- a/bundles/org.eclipse.ui.workbench.texteditor/plugin.xml +++ b/bundles/org.eclipse.ui.workbench.texteditor/plugin.xml @@ -1491,5 +1491,13 @@ visible="false"> - + + + + + diff --git a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthSpaceLineContentCodeMining.java b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthSpaceLineContentCodeMining.java new file mode 100644 index 00000000000..09ae2ef7204 --- /dev/null +++ b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthSpaceLineContentCodeMining.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2025 SAP S.E. and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * SAP S.E. - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.internal.texteditor.codemining; + +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.codemining.ICodeMiningProvider; +import org.eclipse.jface.text.codemining.LineContentCodeMining; + +class ZeroWidthSpaceLineContentCodeMining extends LineContentCodeMining { + + private static final String ZWSP_ANNOTATION = "ZWSP"; //$NON-NLS-1$ + + ZeroWidthSpaceLineContentCodeMining(Position position, ICodeMiningProvider provider) { + super(position, true, provider); + } + + @Override + public boolean isResolved() { + return true; + } + + @Override + public String getLabel() { + return ZWSP_ANNOTATION; + } +} diff --git a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthSpaceLineContentCodeMiningProvider.java b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthSpaceLineContentCodeMiningProvider.java new file mode 100644 index 00000000000..29bd4d29d86 --- /dev/null +++ b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthSpaceLineContentCodeMiningProvider.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * Copyright (c) 2025 SAP S.E. and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * SAP S.E. - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.internal.texteditor.codemining; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +import org.eclipse.core.runtime.IProgressMonitor; + +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; + +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.codemining.AbstractCodeMiningProvider; +import org.eclipse.jface.text.codemining.ICodeMining; +import org.eclipse.jface.text.source.ISourceViewerExtension5; + +import org.eclipse.ui.texteditor.AbstractTextEditor; + +public class ZeroWidthSpaceLineContentCodeMiningProvider extends AbstractCodeMiningProvider + implements IPropertyChangeListener { + + private static final char ZWSP_SIGN = '\u200b'; + private IPreferenceStore store; + private boolean showZwsp = false; + + @Override + public CompletableFuture> provideCodeMinings(ITextViewer viewer, + IProgressMonitor monitor) { + if (store == null) { + loadStoreAndReadProperty(); + } + + if (!showZwsp) { + return CompletableFuture.completedFuture(Collections.emptyList()); + } + + List list = new ArrayList<>(); + String content = viewer.getDocument().get(); + for (int i = 0; i < content.length(); i++) { + if (content.charAt(i) == ZWSP_SIGN) { + list.add(createCodeMining(i)); + } + } + return CompletableFuture.completedFuture(list); + } + + @Override + public void propertyChange(PropertyChangeEvent event) { + if (event.getProperty().equals(AbstractTextEditor.PREFERENCE_SHOW_ZWSP)) { + readShowZwspFromStore(); + updateCodeMinings(); + } + } + + private void updateCodeMinings() { + ITextViewer viewer = getAdapter(ITextViewer.class); + if (viewer instanceof ISourceViewerExtension5 codeMiningExtension) { + codeMiningExtension.updateCodeMinings(); + } + } + + @Override + public void dispose() { + store.removePropertyChangeListener(this); + super.dispose(); + } + + private void loadStoreAndReadProperty() { + store = getAdapter(IPreferenceStore.class); + readShowZwspFromStore(); + store.addPropertyChangeListener(this); + } + + private ICodeMining createCodeMining(int offset) { + return new ZeroWidthSpaceLineContentCodeMining(new Position(offset, 1), this); + } + + private void readShowZwspFromStore() { + showZwsp = store.getBoolean(AbstractTextEditor.PREFERENCE_SHOW_ZWSP); + } +} diff --git a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/AbstractTextEditor.java b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/AbstractTextEditor.java index db9e8bb4f62..19d9aa9d5a5 100644 --- a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/AbstractTextEditor.java +++ b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/AbstractTextEditor.java @@ -2334,10 +2334,21 @@ private int computeOffsetAtLocation(ITextViewer textViewer, int x, int y) { public static final String PREFERENCE_SHOW_LINE_FEED = "showLineFeed"; //$NON-NLS-1$ /** - * A named preference that controls the alpha value of whitespace characters. - * The value is used only if the value of + * A named preference that controls the display of zero-width characters like + * zero-width space. The value is used only if the value of * {@link #PREFERENCE_SHOW_WHITESPACE_CHARACTERS} is true. *

+ * Value is of type Boolean. + *

+ * + * @since 3.? + */ + public static final String PREFERENCE_SHOW_ZW_CHARACTERS = "showZwsp"; //$NON-NLS-1$ + + /** + * A named preference that controls the alpha value of whitespace characters. The value is used + * only if the value of {@link #PREFERENCE_SHOW_WHITESPACE_CHARACTERS} is true. + *

* Value is of type Integer. *

* From d4a9c3f8453cc205c398030b2402d1753566c61e Mon Sep 17 00:00:00 2001 From: Marcus Hoepfner Date: Mon, 11 Aug 2025 16:05:39 +0200 Subject: [PATCH 2/7] add other characters --- .../ZeroWidthSpaceLineContentCodeMiningProvider.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthSpaceLineContentCodeMiningProvider.java b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthSpaceLineContentCodeMiningProvider.java index 29bd4d29d86..8467138d13d 100644 --- a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthSpaceLineContentCodeMiningProvider.java +++ b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthSpaceLineContentCodeMiningProvider.java @@ -16,6 +16,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Set; import java.util.concurrent.CompletableFuture; import org.eclipse.core.runtime.IProgressMonitor; @@ -35,7 +36,13 @@ public class ZeroWidthSpaceLineContentCodeMiningProvider extends AbstractCodeMiningProvider implements IPropertyChangeListener { - private static final char ZWSP_SIGN = '\u200b'; + private static final char ZW_SPACE = '\u200b'; + private static final char ZW_NON_JOINER = '\u200c'; + private static final char ZW_JOINER = '\u200d'; + private static final char ZW_NO_BREAK_SPACE = '\ufeff'; + + private static final Set ZW_CHARACTERS = Set.of(ZW_SPACE, ZW_NON_JOINER, ZW_JOINER, ZW_NO_BREAK_SPACE); + private IPreferenceStore store; private boolean showZwsp = false; @@ -53,7 +60,8 @@ public CompletableFuture> provideCodeMinings(ITextVi List list = new ArrayList<>(); String content = viewer.getDocument().get(); for (int i = 0; i < content.length(); i++) { - if (content.charAt(i) == ZWSP_SIGN) { + boolean isZwCharacter = ZW_CHARACTERS.contains(content.charAt(i)); + if (isZwCharacter) { list.add(createCodeMining(i)); } } From 017035e9c4d04b59e9b1f14f5604b027b882c3b8 Mon Sep 17 00:00:00 2001 From: Marcus Hoepfner Date: Mon, 11 Aug 2025 16:07:08 +0200 Subject: [PATCH 3/7] rename constants --- .../editors/text/TextEditorDefaultsPreferencePage.java | 6 +++--- ...AbstractDecoratedTextEditorPreferenceConstants.java | 10 +++++----- .../ZeroWidthSpaceLineContentCodeMiningProvider.java | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) 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 01b1a5c6714..cb9cffc1d8c 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 @@ -455,7 +455,7 @@ private OverlayPreferenceStore createDialogOverlayStore() { overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_CARRIAGE_RETURN)); overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_LINE_FEED)); overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, - AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_ZWSP)); + AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_ZW_CHARACTERS)); overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.INT, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_WHITESPACE_CHARACTER_ALPHA_VALUE)); OverlayPreferenceStore.OverlayKey[] keys= new OverlayPreferenceStore.OverlayKey[overlayKeys.size()]; @@ -580,7 +580,7 @@ protected Control createDialogArea(Composite parent) { ButtonFactory checkboxFactory = WidgetFactory.button(SWT.CHECK) .supplyLayoutData(() -> new GridData(SWT.CENTER, SWT.CENTER, false, false)).enabled(false); checkboxFactory.create(tabularComposite); - preference = new Preference(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_ZWSP, "", null); //$NON-NLS-1$ + preference = new Preference(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_ZW_CHARACTERS, "", null); //$NON-NLS-1$ addCheckBox(tabularComposite, preference, new BooleanDomain(), 0); checkboxFactory.create(tabularComposite); @@ -823,7 +823,7 @@ private OverlayPreferenceStore createOverlayStore() { overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_CARRIAGE_RETURN)); overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_LINE_FEED)); overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, - AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_ZWSP)); + AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_ZW_CHARACTERS)); overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.INT, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_WHITESPACE_CHARACTER_ALPHA_VALUE)); OverlayPreferenceStore.OverlayKey[] keys= new OverlayPreferenceStore.OverlayKey[overlayKeys.size()]; 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 19a68b60f12..a1ca2f26191 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 @@ -517,7 +517,7 @@ private AbstractDecoratedTextEditorPreferenceConstants() { *
  • {@link #EDITOR_SHOW_TRAILING_TABS}
  • *
  • {@link #EDITOR_SHOW_CARRIAGE_RETURN}
  • *
  • {@link #EDITOR_SHOW_LINE_FEED}
  • - *
  • {@link #EDITOR_SHOW_ZWSP}
  • + *
  • {@link #EDITOR_SHOW_ZW_CHARACTERS}
  • *
  • {@link #EDITOR_WHITESPACE_CHARACTER_ALPHA_VALUE}
  • * * @@ -650,8 +650,8 @@ private AbstractDecoratedTextEditorPreferenceConstants() { public static final String EDITOR_SHOW_LINE_FEED= AbstractTextEditor.PREFERENCE_SHOW_LINE_FEED; /** - * A named preference that controls the display of ZWSP (zero-with space) - * characters. The value is used only if the value of + * A named preference that controls the display of zero-width characters like + * zero-width space. The value is used only if the value of * {@link #EDITOR_SHOW_WHITESPACE_CHARACTERS} is true. *

    * Value is of type Boolean. @@ -659,7 +659,7 @@ private AbstractDecoratedTextEditorPreferenceConstants() { * * @since 3.? */ - public static final String EDITOR_SHOW_ZWSP = AbstractTextEditor.PREFERENCE_SHOW_ZWSP; + public static final String EDITOR_SHOW_ZW_CHARACTERS = AbstractTextEditor.PREFERENCE_SHOW_ZW_CHARACTERS; /** * A named preference that controls the alpha value of whitespace characters. The value is used @@ -872,7 +872,7 @@ public static void initializeDefaultValues(IPreferenceStore store) { store.setDefault(EDITOR_SHOW_TRAILING_TABS, true); store.setDefault(EDITOR_SHOW_CARRIAGE_RETURN, true); store.setDefault(EDITOR_SHOW_LINE_FEED, true); - store.setDefault(EDITOR_SHOW_ZWSP, true); + store.setDefault(EDITOR_SHOW_ZW_CHARACTERS, true); store.setDefault(EDITOR_WHITESPACE_CHARACTER_ALPHA_VALUE, 80); store.setDefault(EDITOR_TEXT_DRAG_AND_DROP_ENABLED, true); diff --git a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthSpaceLineContentCodeMiningProvider.java b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthSpaceLineContentCodeMiningProvider.java index 8467138d13d..3f48f45c6a2 100644 --- a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthSpaceLineContentCodeMiningProvider.java +++ b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthSpaceLineContentCodeMiningProvider.java @@ -70,7 +70,7 @@ public CompletableFuture> provideCodeMinings(ITextVi @Override public void propertyChange(PropertyChangeEvent event) { - if (event.getProperty().equals(AbstractTextEditor.PREFERENCE_SHOW_ZWSP)) { + if (event.getProperty().equals(AbstractTextEditor.PREFERENCE_SHOW_ZW_CHARACTERS)) { readShowZwspFromStore(); updateCodeMinings(); } @@ -100,6 +100,6 @@ private ICodeMining createCodeMining(int offset) { } private void readShowZwspFromStore() { - showZwsp = store.getBoolean(AbstractTextEditor.PREFERENCE_SHOW_ZWSP); + showZwsp = store.getBoolean(AbstractTextEditor.PREFERENCE_SHOW_ZW_CHARACTERS); } } From fe172425420a402665f3f95a811d6d2776c454a6 Mon Sep 17 00:00:00 2001 From: Marcus Hoepfner Date: Mon, 11 Aug 2025 16:10:39 +0200 Subject: [PATCH 4/7] rename preference --- .../internal/editors/text/TextEditorDefaultsPreferencePage.java | 2 +- .../eclipse/ui/internal/editors/text/TextEditorMessages.java | 2 +- .../ui/internal/editors/text/TextEditorMessages.properties | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) 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 cb9cffc1d8c..2efdf7a5cd3 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 @@ -575,7 +575,7 @@ protected Control createDialogArea(Composite parent) { preference= new Preference(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_LINE_FEED, "", null); //$NON-NLS-1$ addCheckBox(tabularComposite, preference, new BooleanDomain(), 0); - WidgetFactory.label(SWT.NONE).text(TextEditorMessages.TextEditorDefaultsPreferencePage_zwsp) + WidgetFactory.label(SWT.NONE).text(TextEditorMessages.TextEditorDefaultsPreferencePage_zwcharacters) .layoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false)).create(tabularComposite); ButtonFactory checkboxFactory = WidgetFactory.button(SWT.CHECK) .supplyLayoutData(() -> new GridData(SWT.CENTER, SWT.CENTER, false, false)).enabled(false); 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 05cbdbefd4f..fdcd1091798 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 @@ -159,7 +159,7 @@ private TextEditorMessages() { public static String TextEditorDefaultsPreferencePage_ideographicSpace; public static String TextEditorDefaultsPreferencePage_leading; public static String TextEditorDefaultsPreferencePage_lineFeed; - public static String TextEditorDefaultsPreferencePage_zwsp; + public static String TextEditorDefaultsPreferencePage_zwcharacters; public static String TextEditorDefaultsPreferencePage_range_indicator; public static String TextEditorDefaultsPreferencePage_smartHomeEnd; public static String TextEditorDefaultsPreferencePage_warn_if_derived; 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 5fea721c2ad..0193e814379 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 @@ -61,7 +61,7 @@ TextEditorDefaultsPreferencePage_enrichHover_onClick=Enrich on click TextEditorDefaultsPreferencePage_ideographicSpace=Ideographic space ( \u00b0 ) TextEditorDefaultsPreferencePage_leading=Leading TextEditorDefaultsPreferencePage_lineFeed=Line Feed ( \u00b6 ) -TextEditorDefaultsPreferencePage_zwsp=ZWSP (Zero-Width Space) +TextEditorDefaultsPreferencePage_zwcharacters=Zero-Width Characters TextEditorDefaultsPreferencePage_range_indicator=Show &range indicator TextEditorDefaultsPreferencePage_warn_if_derived= War&n before editing a derived file TextEditorDefaultsPreferencePage_smartHomeEnd= &Smart caret positioning at line start and end From a4aebcb95bd7ba1c23145eb93a51133f14add88f Mon Sep 17 00:00:00 2001 From: Marcus Hoepfner Date: Mon, 11 Aug 2025 16:11:51 +0200 Subject: [PATCH 5/7] rename files --- .../plugin.xml | 2 +- ...eroWidthCharactersLineContentCodeMining.java} | 16 +++++++++++----- ...CharactersLineContentCodeMiningProvider.java} | 12 +++++++++--- 3 files changed, 21 insertions(+), 9 deletions(-) rename bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/{ZeroWidthSpaceLineContentCodeMining.java => ZeroWidthCharactersLineContentCodeMining.java} (63%) rename bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/{ZeroWidthSpaceLineContentCodeMiningProvider.java => ZeroWidthCharactersLineContentCodeMiningProvider.java} (89%) diff --git a/bundles/org.eclipse.ui.workbench.texteditor/plugin.xml b/bundles/org.eclipse.ui.workbench.texteditor/plugin.xml index e36930a7a0f..aaf9928b511 100644 --- a/bundles/org.eclipse.ui.workbench.texteditor/plugin.xml +++ b/bundles/org.eclipse.ui.workbench.texteditor/plugin.xml @@ -1495,7 +1495,7 @@ diff --git a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthSpaceLineContentCodeMining.java b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthCharactersLineContentCodeMining.java similarity index 63% rename from bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthSpaceLineContentCodeMining.java rename to bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthCharactersLineContentCodeMining.java index 09ae2ef7204..9f885348728 100644 --- a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthSpaceLineContentCodeMining.java +++ b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthCharactersLineContentCodeMining.java @@ -17,12 +17,18 @@ import org.eclipse.jface.text.codemining.ICodeMiningProvider; import org.eclipse.jface.text.codemining.LineContentCodeMining; -class ZeroWidthSpaceLineContentCodeMining extends LineContentCodeMining { +/** + * A code mining that draws zero-width characters (like zero-width spaces) as + * line content code minings. + * + * @see ZeroWidthCharactersLineContentCodeMiningProvider + */ +class ZeroWidthCharactersLineContentCodeMining extends LineContentCodeMining { - private static final String ZWSP_ANNOTATION = "ZWSP"; //$NON-NLS-1$ + private static final String ZW_CHARACTERS_MINING = "ZWSP"; //$NON-NLS-1$ - ZeroWidthSpaceLineContentCodeMining(Position position, ICodeMiningProvider provider) { - super(position, true, provider); + public ZeroWidthCharactersLineContentCodeMining(int offset, ICodeMiningProvider provider) { + super(new Position(offset, 1), true, provider); } @Override @@ -32,6 +38,6 @@ public boolean isResolved() { @Override public String getLabel() { - return ZWSP_ANNOTATION; + return ZW_CHARACTERS_MINING; } } diff --git a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthSpaceLineContentCodeMiningProvider.java b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthCharactersLineContentCodeMiningProvider.java similarity index 89% rename from bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthSpaceLineContentCodeMiningProvider.java rename to bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthCharactersLineContentCodeMiningProvider.java index 3f48f45c6a2..4e1ef15c102 100644 --- a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthSpaceLineContentCodeMiningProvider.java +++ b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthCharactersLineContentCodeMiningProvider.java @@ -26,14 +26,20 @@ import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.text.ITextViewer; -import org.eclipse.jface.text.Position; import org.eclipse.jface.text.codemining.AbstractCodeMiningProvider; import org.eclipse.jface.text.codemining.ICodeMining; import org.eclipse.jface.text.source.ISourceViewerExtension5; import org.eclipse.ui.texteditor.AbstractTextEditor; -public class ZeroWidthSpaceLineContentCodeMiningProvider extends AbstractCodeMiningProvider +/** + * A code mining provider that draws zero-width characters (like zero-width + * spaces) as line content code minings. + *

    + * The code mining is only shown if configured in the preferences. + *

    + */ +public class ZeroWidthCharactersLineContentCodeMiningProvider extends AbstractCodeMiningProvider implements IPropertyChangeListener { private static final char ZW_SPACE = '\u200b'; @@ -96,7 +102,7 @@ private void loadStoreAndReadProperty() { } private ICodeMining createCodeMining(int offset) { - return new ZeroWidthSpaceLineContentCodeMining(new Position(offset, 1), this); + return new ZeroWidthCharactersLineContentCodeMining(offset, this); } private void readShowZwspFromStore() { From 20dfaeb9145cb61e8a29523a6894cb60a59e8ad3 Mon Sep 17 00:00:00 2001 From: Marcus Hoepfner Date: Thu, 9 Oct 2025 14:56:49 +0200 Subject: [PATCH 6/7] react on toolbar action or general switch-on/off --- ...eroWidthCharactersLineContentCodeMining.java | 17 +++++++++++++++++ ...CharactersLineContentCodeMiningProvider.java | 12 ++++++++---- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthCharactersLineContentCodeMining.java b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthCharactersLineContentCodeMining.java index 9f885348728..31979a0096c 100644 --- a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthCharactersLineContentCodeMining.java +++ b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthCharactersLineContentCodeMining.java @@ -13,6 +13,13 @@ *******************************************************************************/ package org.eclipse.ui.internal.texteditor.codemining; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Display; + import org.eclipse.jface.text.Position; import org.eclipse.jface.text.codemining.ICodeMiningProvider; import org.eclipse.jface.text.codemining.LineContentCodeMining; @@ -26,9 +33,11 @@ class ZeroWidthCharactersLineContentCodeMining extends LineContentCodeMining { private static final String ZW_CHARACTERS_MINING = "ZWSP"; //$NON-NLS-1$ + private Color fgColor; public ZeroWidthCharactersLineContentCodeMining(int offset, ICodeMiningProvider provider) { super(new Position(offset, 1), true, provider); + fgColor = Display.getCurrent().getSystemColor(SWT.COLOR_LIST_FOREGROUND); } @Override @@ -40,4 +49,12 @@ public boolean isResolved() { public String getLabel() { return ZW_CHARACTERS_MINING; } + + @Override + public Point draw(GC gc, StyledText textWidget, Color color, int x, int y) { + gc.setForeground(fgColor); + Point point = super.draw(gc, textWidget, fgColor, x, y); + gc.setForeground(color); + return point; + } } diff --git a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthCharactersLineContentCodeMiningProvider.java b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthCharactersLineContentCodeMiningProvider.java index 4e1ef15c102..49fb9369161 100644 --- a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthCharactersLineContentCodeMiningProvider.java +++ b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthCharactersLineContentCodeMiningProvider.java @@ -13,6 +13,9 @@ *******************************************************************************/ package org.eclipse.ui.internal.texteditor.codemining; +import static org.eclipse.ui.texteditor.AbstractTextEditor.PREFERENCE_SHOW_WHITESPACE_CHARACTERS; +import static org.eclipse.ui.texteditor.AbstractTextEditor.PREFERENCE_SHOW_ZW_CHARACTERS; + import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -30,8 +33,6 @@ import org.eclipse.jface.text.codemining.ICodeMining; import org.eclipse.jface.text.source.ISourceViewerExtension5; -import org.eclipse.ui.texteditor.AbstractTextEditor; - /** * A code mining provider that draws zero-width characters (like zero-width * spaces) as line content code minings. @@ -76,7 +77,8 @@ public CompletableFuture> provideCodeMinings(ITextVi @Override public void propertyChange(PropertyChangeEvent event) { - if (event.getProperty().equals(AbstractTextEditor.PREFERENCE_SHOW_ZW_CHARACTERS)) { + if (PREFERENCE_SHOW_ZW_CHARACTERS.equals(event.getProperty()) + || PREFERENCE_SHOW_WHITESPACE_CHARACTERS.equals(event.getProperty())) { readShowZwspFromStore(); updateCodeMinings(); } @@ -89,6 +91,7 @@ private void updateCodeMinings() { } } + @Override public void dispose() { store.removePropertyChangeListener(this); @@ -106,6 +109,7 @@ private ICodeMining createCodeMining(int offset) { } private void readShowZwspFromStore() { - showZwsp = store.getBoolean(AbstractTextEditor.PREFERENCE_SHOW_ZW_CHARACTERS); + showZwsp = store.getBoolean(PREFERENCE_SHOW_ZW_CHARACTERS) + && store.getBoolean(PREFERENCE_SHOW_WHITESPACE_CHARACTERS); } } From c97d0b4b74f42621046fca59e8da1bd44c0560be Mon Sep 17 00:00:00 2001 From: Marcus Hoepfner Date: Mon, 13 Oct 2025 07:37:03 +0200 Subject: [PATCH 7/7] fix NPE --- .../ZeroWidthCharactersLineContentCodeMining.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthCharactersLineContentCodeMining.java b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthCharactersLineContentCodeMining.java index 31979a0096c..4995b8e707f 100644 --- a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthCharactersLineContentCodeMining.java +++ b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/ZeroWidthCharactersLineContentCodeMining.java @@ -33,11 +33,9 @@ class ZeroWidthCharactersLineContentCodeMining extends LineContentCodeMining { private static final String ZW_CHARACTERS_MINING = "ZWSP"; //$NON-NLS-1$ - private Color fgColor; public ZeroWidthCharactersLineContentCodeMining(int offset, ICodeMiningProvider provider) { super(new Position(offset, 1), true, provider); - fgColor = Display.getCurrent().getSystemColor(SWT.COLOR_LIST_FOREGROUND); } @Override @@ -52,9 +50,14 @@ public String getLabel() { @Override public Point draw(GC gc, StyledText textWidget, Color color, int x, int y) { - gc.setForeground(fgColor); - Point point = super.draw(gc, textWidget, fgColor, x, y); + gc.setForeground(getColor(color)); + Point point = super.draw(gc, textWidget, color, x, y); gc.setForeground(color); return point; } + + private Color getColor(Color predefinedColor) { + return Display.getCurrent() != null ? Display.getCurrent().getSystemColor(SWT.COLOR_LIST_FOREGROUND) + : predefinedColor; + } }