Skip to content

Commit 6cccc08

Browse files
Show ZWSP (zero with space) as code mining
Issue: #1002 For more information refer to https://www.compart.com/en/unicode/U+200B To get a ZWSP refer to https://zerowidthspace.me/
1 parent b713603 commit 6cccc08

File tree

9 files changed

+191
-3
lines changed

9 files changed

+191
-3
lines changed

bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/text/TextEditorDefaultsPreferencePage.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@
6868
import org.eclipse.jface.viewers.SelectionChangedEvent;
6969
import org.eclipse.jface.viewers.StructuredSelection;
7070
import org.eclipse.jface.viewers.TableViewer;
71+
import org.eclipse.jface.widgets.ButtonFactory;
72+
import org.eclipse.jface.widgets.WidgetFactory;
7173

7274
import org.eclipse.ui.IWorkbench;
7375
import org.eclipse.ui.IWorkbenchPreferencePage;
@@ -439,7 +441,9 @@ private OverlayPreferenceStore createDialogOverlayStore() {
439441
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_ENCLOSED_TABS));
440442
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_TRAILING_TABS));
441443
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_CARRIAGE_RETURN));
442-
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_LINE_FEED));
444+
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_LINE_FEED));
445+
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN,
446+
AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_ZWSP));
443447
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.INT, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_WHITESPACE_CHARACTER_ALPHA_VALUE));
444448

445449
OverlayPreferenceStore.OverlayKey[] keys= new OverlayPreferenceStore.OverlayKey[overlayKeys.size()];
@@ -559,6 +563,15 @@ protected Control createDialogArea(Composite parent) {
559563
preference= new Preference(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_LINE_FEED, "", null); //$NON-NLS-1$
560564
addCheckBox(tabularComposite, preference, new BooleanDomain(), 0);
561565

566+
WidgetFactory.label(SWT.NONE).text(TextEditorMessages.TextEditorDefaultsPreferencePage_zwsp)
567+
.layoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false)).create(tabularComposite);
568+
ButtonFactory checkboxFactory = WidgetFactory.button(SWT.CHECK)
569+
.supplyLayoutData(() -> new GridData(SWT.CENTER, SWT.CENTER, false, false)).enabled(false);
570+
checkboxFactory.create(tabularComposite);
571+
preference = new Preference(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_ZWSP, "", null); //$NON-NLS-1$
572+
addCheckBox(tabularComposite, preference, new BooleanDomain(), 0);
573+
checkboxFactory.create(tabularComposite);
574+
562575
Composite alphaComposite= new Composite(composite, SWT.NONE);
563576
layout= new GridLayout();
564577
layout.numColumns= 2;
@@ -796,6 +809,8 @@ private OverlayPreferenceStore createOverlayStore() {
796809
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_TRAILING_TABS));
797810
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_CARRIAGE_RETURN));
798811
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_LINE_FEED));
812+
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN,
813+
AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_ZWSP));
799814
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.INT, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_WHITESPACE_CHARACTER_ALPHA_VALUE));
800815

801816
OverlayPreferenceStore.OverlayKey[] keys= new OverlayPreferenceStore.OverlayKey[overlayKeys.size()];

bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/text/TextEditorMessages.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ private TextEditorMessages() {
159159
public static String TextEditorDefaultsPreferencePage_ideographicSpace;
160160
public static String TextEditorDefaultsPreferencePage_leading;
161161
public static String TextEditorDefaultsPreferencePage_lineFeed;
162+
public static String TextEditorDefaultsPreferencePage_zwsp;
162163
public static String TextEditorDefaultsPreferencePage_range_indicator;
163164
public static String TextEditorDefaultsPreferencePage_smartHomeEnd;
164165
public static String TextEditorDefaultsPreferencePage_warn_if_derived;

bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/text/TextEditorMessages.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ TextEditorDefaultsPreferencePage_enrichHover_onClick=Enrich on click
6161
TextEditorDefaultsPreferencePage_ideographicSpace=Ideographic space ( \u00b0 )
6262
TextEditorDefaultsPreferencePage_leading=Leading
6363
TextEditorDefaultsPreferencePage_lineFeed=Line Feed ( \u00b6 )
64+
TextEditorDefaultsPreferencePage_zwsp=ZWSP (Zero-Width Space)
6465
TextEditorDefaultsPreferencePage_range_indicator=Show &range indicator
6566
TextEditorDefaultsPreferencePage_warn_if_derived= War&n before editing a derived file
6667
TextEditorDefaultsPreferencePage_smartHomeEnd= &Smart caret positioning at line start and end

bundles/org.eclipse.ui.editors/src/org/eclipse/ui/texteditor/AbstractDecoratedTextEditorPreferenceConstants.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,8 @@ private AbstractDecoratedTextEditorPreferenceConstants() {
502502
* </p>
503503
*
504504
* <p>
505-
* The following preferences can be used for fine-grained configuration when enabled.
505+
* The following preferences can be used for fine-grained configuration when
506+
* enabled.
506507
* </p>
507508
* <ul>
508509
* <li>{@link #EDITOR_SHOW_LEADING_SPACES}</li>
@@ -516,6 +517,7 @@ private AbstractDecoratedTextEditorPreferenceConstants() {
516517
* <li>{@link #EDITOR_SHOW_TRAILING_TABS}</li>
517518
* <li>{@link #EDITOR_SHOW_CARRIAGE_RETURN}</li>
518519
* <li>{@link #EDITOR_SHOW_LINE_FEED}</li>
520+
* <li>{@link #EDITOR_SHOW_ZWSP}</li>
519521
* <li>{@link #EDITOR_WHITESPACE_CHARACTER_ALPHA_VALUE}</li>
520522
* </ul>
521523
*
@@ -647,6 +649,18 @@ private AbstractDecoratedTextEditorPreferenceConstants() {
647649
*/
648650
public static final String EDITOR_SHOW_LINE_FEED= AbstractTextEditor.PREFERENCE_SHOW_LINE_FEED;
649651

652+
/**
653+
* A named preference that controls the display of ZWSP (zero-with space)
654+
* characters. The value is used only if the value of
655+
* {@link #EDITOR_SHOW_WHITESPACE_CHARACTERS} is <code>true</code>.
656+
* <p>
657+
* Value is of type <code>Boolean</code>.
658+
* </p>
659+
*
660+
* @since 3.?
661+
*/
662+
public static final String EDITOR_SHOW_ZWSP = AbstractTextEditor.PREFERENCE_SHOW_ZWSP;
663+
650664
/**
651665
* A named preference that controls the alpha value of whitespace characters. The value is used
652666
* only if the value of {@link #EDITOR_SHOW_WHITESPACE_CHARACTERS} is <code>true</code>.
@@ -858,6 +872,7 @@ public static void initializeDefaultValues(IPreferenceStore store) {
858872
store.setDefault(EDITOR_SHOW_TRAILING_TABS, true);
859873
store.setDefault(EDITOR_SHOW_CARRIAGE_RETURN, true);
860874
store.setDefault(EDITOR_SHOW_LINE_FEED, true);
875+
store.setDefault(EDITOR_SHOW_ZWSP, true);
861876
store.setDefault(EDITOR_WHITESPACE_CHARACTER_ALPHA_VALUE, 80);
862877

863878
store.setDefault(EDITOR_TEXT_DRAG_AND_DROP_ENABLED, true);

bundles/org.eclipse.ui.workbench.texteditor/plugin.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,3 +215,5 @@ blockSelectionModeFont.label= Text Editor Block Selection Font
215215
blockSelectionModeFont.description= The block selection mode font is used by text editors in block (column) mode. A monospace font should be used.
216216

217217
MinimapView.name=Minimap
218+
219+
CodeMining.show.ZWSP=Show ZWSP (Zero-Width Space)

bundles/org.eclipse.ui.workbench.texteditor/plugin.xml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1491,5 +1491,13 @@
14911491
visible="false">
14921492
</view>
14931493
</perspectiveExtension>
1494-
</extension>
1494+
</extension>
1495+
<extension
1496+
point="org.eclipse.ui.workbench.texteditor.codeMiningProviders">
1497+
<codeMiningProvider
1498+
class="org.eclipse.ui.internal.texteditor.codemining.ZeroWidthSpaceLineContentCodeMiningProvider"
1499+
id="org.eclipse.test.codemining.zswpProvider"
1500+
label="%CodeMining.show.ZWSP">
1501+
</codeMiningProvider>
1502+
</extension>
14951503
</plugin>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 SAP S.E. and others.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* SAP S.E. - initial API and implementation
13+
*******************************************************************************/
14+
package org.eclipse.ui.internal.texteditor.codemining;
15+
16+
import org.eclipse.jface.text.Position;
17+
import org.eclipse.jface.text.codemining.ICodeMiningProvider;
18+
import org.eclipse.jface.text.codemining.LineContentCodeMining;
19+
20+
class ZeroWidthSpaceLineContentCodeMining extends LineContentCodeMining {
21+
22+
private static final String ZWSP_ANNOTATION = "ZWSP"; //$NON-NLS-1$
23+
24+
ZeroWidthSpaceLineContentCodeMining(Position position, ICodeMiningProvider provider) {
25+
super(position, true, provider);
26+
}
27+
28+
@Override
29+
public boolean isResolved() {
30+
return true;
31+
}
32+
33+
@Override
34+
public String getLabel() {
35+
return ZWSP_ANNOTATION;
36+
}
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 SAP S.E. and others.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* SAP S.E. - initial API and implementation
13+
*******************************************************************************/
14+
package org.eclipse.ui.internal.texteditor.codemining;
15+
16+
import java.util.ArrayList;
17+
import java.util.Collections;
18+
import java.util.List;
19+
import java.util.concurrent.CompletableFuture;
20+
21+
import org.eclipse.core.runtime.IProgressMonitor;
22+
23+
import org.eclipse.jface.preference.IPreferenceStore;
24+
import org.eclipse.jface.util.IPropertyChangeListener;
25+
import org.eclipse.jface.util.PropertyChangeEvent;
26+
27+
import org.eclipse.jface.text.ITextViewer;
28+
import org.eclipse.jface.text.Position;
29+
import org.eclipse.jface.text.codemining.AbstractCodeMiningProvider;
30+
import org.eclipse.jface.text.codemining.ICodeMining;
31+
import org.eclipse.jface.text.source.ISourceViewerExtension5;
32+
33+
import org.eclipse.ui.texteditor.AbstractTextEditor;
34+
35+
public class ZeroWidthSpaceLineContentCodeMiningProvider extends AbstractCodeMiningProvider
36+
implements IPropertyChangeListener {
37+
38+
private static final char ZWSP_SIGN = '\u200b';
39+
private IPreferenceStore store;
40+
private boolean showZwsp = false;
41+
42+
@Override
43+
public CompletableFuture<List<? extends ICodeMining>> provideCodeMinings(ITextViewer viewer,
44+
IProgressMonitor monitor) {
45+
if (store == null) {
46+
loadStoreAndReadProperty();
47+
}
48+
49+
if (!showZwsp) {
50+
return CompletableFuture.completedFuture(Collections.emptyList());
51+
}
52+
53+
List<ICodeMining> list = new ArrayList<>();
54+
String content = viewer.getDocument().get();
55+
for (int i = 0; i < content.length(); i++) {
56+
if (content.charAt(i) == ZWSP_SIGN) {
57+
list.add(createCodeMining(i));
58+
}
59+
}
60+
return CompletableFuture.completedFuture(list);
61+
}
62+
63+
@Override
64+
public void propertyChange(PropertyChangeEvent event) {
65+
if (event.getProperty().equals(AbstractTextEditor.PREFERENCE_SHOW_ZWSP)) {
66+
readShowZwspFromStore();
67+
updateCodeMinings();
68+
}
69+
}
70+
71+
private void updateCodeMinings() {
72+
ITextViewer viewer = getAdapter(ITextViewer.class);
73+
if (viewer instanceof ISourceViewerExtension5 codeMiningExtension) {
74+
codeMiningExtension.updateCodeMinings();
75+
}
76+
}
77+
78+
@Override
79+
public void dispose() {
80+
store.removePropertyChangeListener(this);
81+
super.dispose();
82+
}
83+
84+
private void loadStoreAndReadProperty() {
85+
store = getAdapter(IPreferenceStore.class);
86+
readShowZwspFromStore();
87+
store.addPropertyChangeListener(this);
88+
}
89+
90+
private ICodeMining createCodeMining(int offset) {
91+
return new ZeroWidthSpaceLineContentCodeMining(new Position(offset, 1), this);
92+
}
93+
94+
private void readShowZwspFromStore() {
95+
showZwsp = store.getBoolean(AbstractTextEditor.PREFERENCE_SHOW_ZWSP);
96+
}
97+
}

bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/AbstractTextEditor.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2189,6 +2189,18 @@ private int computeOffsetAtLocation(ITextViewer textViewer, int x, int y) {
21892189
*/
21902190
public static final String PREFERENCE_SHOW_LINE_FEED= "showLineFeed"; //$NON-NLS-1$
21912191

2192+
/**
2193+
* A named preference that controls the display of ZWSP (zero-width space)
2194+
* characters. The value is used only if the value of
2195+
* {@link #PREFERENCE_SHOW_WHITESPACE_CHARACTERS} is <code>true</code>.
2196+
* <p>
2197+
* Value is of type <code>Boolean</code>.
2198+
* </p>
2199+
*
2200+
* @since 3.?
2201+
*/
2202+
public static final String PREFERENCE_SHOW_ZWSP = "showZwsp"; //$NON-NLS-1$
2203+
21922204
/**
21932205
* A named preference that controls the alpha value of whitespace characters. The value is used
21942206
* only if the value of {@link #PREFERENCE_SHOW_WHITESPACE_CHARACTERS} is <code>true</code>.

0 commit comments

Comments
 (0)