Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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_ZW_CHARACTERS));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.INT, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_WHITESPACE_CHARACTER_ALPHA_VALUE));

OverlayPreferenceStore.OverlayKey[] keys= new OverlayPreferenceStore.OverlayKey[overlayKeys.size()];
Expand Down Expand Up @@ -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_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);
checkboxFactory.create(tabularComposite);
preference = new Preference(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_ZW_CHARACTERS, "", 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;
Expand Down Expand Up @@ -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_ZW_CHARACTERS));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.INT, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_WHITESPACE_CHARACTER_ALPHA_VALUE));

OverlayPreferenceStore.OverlayKey[] keys= new OverlayPreferenceStore.OverlayKey[overlayKeys.size()];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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_zwcharacters;
public static String TextEditorDefaultsPreferencePage_range_indicator;
public static String TextEditorDefaultsPreferencePage_smartHomeEnd;
public static String TextEditorDefaultsPreferencePage_warn_if_derived;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ TextEditorDefaultsPreferencePage_enrichHover_onClick=Enrich on click
TextEditorDefaultsPreferencePage_ideographicSpace=Ideographic space ( \u00b0 )
TextEditorDefaultsPreferencePage_leading=Leading
TextEditorDefaultsPreferencePage_lineFeed=Line Feed ( \u00b6 )
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,8 @@ private AbstractDecoratedTextEditorPreferenceConstants() {
* </p>
*
* <p>
* The following preferences can be used for fine-grained configuration when enabled.
* The following preferences can be used for fine-grained configuration when
* enabled.
* </p>
* <ul>
* <li>{@link #EDITOR_SHOW_LEADING_SPACES}</li>
Expand All @@ -516,6 +517,7 @@ private AbstractDecoratedTextEditorPreferenceConstants() {
* <li>{@link #EDITOR_SHOW_TRAILING_TABS}</li>
* <li>{@link #EDITOR_SHOW_CARRIAGE_RETURN}</li>
* <li>{@link #EDITOR_SHOW_LINE_FEED}</li>
* <li>{@link #EDITOR_SHOW_ZW_CHARACTERS}</li>
* <li>{@link #EDITOR_WHITESPACE_CHARACTER_ALPHA_VALUE}</li>
* </ul>
*
Expand Down Expand Up @@ -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 zero-width characters like
* zero-width space. The value is used only if the value of
* {@link #EDITOR_SHOW_WHITESPACE_CHARACTERS} is <code>true</code>.
* <p>
* Value is of type <code>Boolean</code>.
* </p>
*
* @since 3.?
*/
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
* only if the value of {@link #EDITOR_SHOW_WHITESPACE_CHARACTERS} is <code>true</code>.
Expand Down Expand Up @@ -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_ZW_CHARACTERS, true);
store.setDefault(EDITOR_WHITESPACE_CHARACTER_ALPHA_VALUE, 80);

store.setDefault(EDITOR_TEXT_DRAG_AND_DROP_ENABLED, true);
Expand Down
2 changes: 2 additions & 0 deletions bundles/org.eclipse.ui.workbench.texteditor/plugin.properties
Original file line number Diff line number Diff line change
Expand Up @@ -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)
10 changes: 9 additions & 1 deletion bundles/org.eclipse.ui.workbench.texteditor/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1491,5 +1491,13 @@
visible="false">
</view>
</perspectiveExtension>
</extension>
</extension>
<extension
point="org.eclipse.ui.workbench.texteditor.codeMiningProviders">
<codeMiningProvider
class="org.eclipse.ui.internal.texteditor.codemining.ZeroWidthCharactersLineContentCodeMiningProvider"
id="org.eclipse.test.codemining.zswpProvider"
label="%CodeMining.show.ZWSP">
</codeMiningProvider>
</extension>
</plugin>
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*******************************************************************************
* 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.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;

/**
* 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 ZW_CHARACTERS_MINING = "ZWSP"; //$NON-NLS-1$

public ZeroWidthCharactersLineContentCodeMining(int offset, ICodeMiningProvider provider) {
super(new Position(offset, 1), true, provider);
}

@Override
public boolean isResolved() {
return true;
}

@Override
public String getLabel() {
return ZW_CHARACTERS_MINING;
}

@Override
public Point draw(GC gc, StyledText textWidget, Color color, int x, int 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;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*******************************************************************************
* 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 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;
import java.util.Set;
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.codemining.AbstractCodeMiningProvider;
import org.eclipse.jface.text.codemining.ICodeMining;
import org.eclipse.jface.text.source.ISourceViewerExtension5;

/**
* A code mining provider that draws zero-width characters (like zero-width
* spaces) as line content code minings.
* <p>
* The code mining is only shown if configured in the preferences.
* </p>
*/
public class ZeroWidthCharactersLineContentCodeMiningProvider extends AbstractCodeMiningProvider
implements IPropertyChangeListener {

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<Character> ZW_CHARACTERS = Set.of(ZW_SPACE, ZW_NON_JOINER, ZW_JOINER, ZW_NO_BREAK_SPACE);

private IPreferenceStore store;
private boolean showZwsp = false;

@Override
public CompletableFuture<List<? extends ICodeMining>> provideCodeMinings(ITextViewer viewer,
IProgressMonitor monitor) {
if (store == null) {
loadStoreAndReadProperty();
}

if (!showZwsp) {
return CompletableFuture.completedFuture(Collections.emptyList());
}

List<ICodeMining> list = new ArrayList<>();
String content = viewer.getDocument().get();
for (int i = 0; i < content.length(); i++) {
boolean isZwCharacter = ZW_CHARACTERS.contains(content.charAt(i));
if (isZwCharacter) {
list.add(createCodeMining(i));
}
}
return CompletableFuture.completedFuture(list);
}

@Override
public void propertyChange(PropertyChangeEvent event) {
if (PREFERENCE_SHOW_ZW_CHARACTERS.equals(event.getProperty())
|| PREFERENCE_SHOW_WHITESPACE_CHARACTERS.equals(event.getProperty())) {
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 ZeroWidthCharactersLineContentCodeMining(offset, this);
}

private void readShowZwspFromStore() {
showZwsp = store.getBoolean(PREFERENCE_SHOW_ZW_CHARACTERS)
&& store.getBoolean(PREFERENCE_SHOW_WHITESPACE_CHARACTERS);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 <code>true</code>.
* <p>
* Value is of type <code>Boolean</code>.
* </p>
*
* @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 <code>true</code>.
* <p>
* Value is of type <code>Integer</code>.
* </p>
*
Expand Down
Loading