Skip to content

Commit 0096bed

Browse files
committed
Add support to Compare/Replace selection or editor with clipboard
Allows users to compare or replace either the selected text or the entire editor content against the clipboard content
1 parent 27a1efe commit 0096bed

File tree

4 files changed

+296
-1
lines changed

4 files changed

+296
-1
lines changed
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 IBM Corporation 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+
* IBM Corporation - initial API and implementation
13+
*******************************************************************************/
14+
package org.eclipse.compare.internal;
15+
16+
import java.io.ByteArrayInputStream;
17+
import java.io.IOException;
18+
import java.io.InputStream;
19+
import java.lang.reflect.InvocationTargetException;
20+
import java.nio.charset.StandardCharsets;
21+
22+
import org.eclipse.compare.CompareConfiguration;
23+
import org.eclipse.compare.CompareEditorInput;
24+
import org.eclipse.compare.CompareUI;
25+
import org.eclipse.compare.IStreamContentAccessor;
26+
import org.eclipse.compare.ITypedElement;
27+
import org.eclipse.compare.structuremergeviewer.DiffNode;
28+
import org.eclipse.core.resources.IFile;
29+
import org.eclipse.core.runtime.CoreException;
30+
import org.eclipse.core.runtime.IProgressMonitor;
31+
import org.eclipse.jface.dialogs.MessageDialog;
32+
import org.eclipse.jface.text.ITextSelection;
33+
import org.eclipse.jface.viewers.ISelection;
34+
import org.eclipse.swt.dnd.Clipboard;
35+
import org.eclipse.swt.dnd.TextTransfer;
36+
import org.eclipse.swt.graphics.Image;
37+
import org.eclipse.swt.widgets.Display;
38+
import org.eclipse.swt.widgets.Shell;
39+
import org.eclipse.ui.IEditorInput;
40+
import org.eclipse.ui.IEditorPart;
41+
import org.eclipse.ui.IFileEditorInput;
42+
import org.eclipse.ui.IWorkbenchPage;
43+
import org.eclipse.ui.PlatformUI;
44+
import org.eclipse.ui.texteditor.ITextEditor;
45+
46+
public class ClipboardCompare extends BaseCompareAction{
47+
48+
private String clipboard = "Clipboard"; //$NON-NLS-1$
49+
50+
@Override
51+
protected void run(ISelection selection) {
52+
IFile[] files = Utilities.getFiles(selection);
53+
for (IFile file : files) {
54+
try {
55+
processComparison(file);
56+
} catch (Exception e) {
57+
Shell parentShell = CompareUIPlugin.getShell();
58+
MessageDialog.openError(parentShell, "Comparision Failed", e.getMessage()); //$NON-NLS-1$
59+
}
60+
}
61+
}
62+
@Override
63+
protected boolean isEnabled(ISelection selection) {
64+
return Utilities.getFiles(selection).length == 1 && getClipboard() != null;
65+
}
66+
67+
/**
68+
* Process comparison with selection or entire editor contents with contents in
69+
* clipboard
70+
*
71+
* @param file Editor file
72+
* @throws IOException, CoreException
73+
*/
74+
private void processComparison(IFile file) throws IOException, CoreException {
75+
String cb = getClipboard().toString();
76+
String fileName = file.getName();
77+
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
78+
IEditorPart editor = page.getActiveEditor();
79+
IEditorInput input = editor.getEditorInput();
80+
if (input instanceof IFileEditorInput ed) {
81+
IFile file2 = ed.getFile();
82+
String fileName2 = file2.getName();
83+
if (!file.getName().equals(fileName2)) {
84+
String fileContents = new String(file.getContents().readAllBytes(), file.getCharset());
85+
showComparison(fileContents, fileName, cb);
86+
return;
87+
}
88+
}
89+
final String selectionContents;
90+
if (editor instanceof ITextEditor txtEditor) {
91+
ISelection selection = txtEditor.getSelectionProvider().getSelection();
92+
if (selection instanceof ITextSelection textSelection) {
93+
selectionContents = textSelection.getText();
94+
if (selectionContents.isEmpty()) {
95+
String fileContents = new String(file.getContents().readAllBytes(), file.getCharset());
96+
showComparison(fileContents, fileName, cb);
97+
} else {
98+
showComparison(selectionContents, fileName, cb);
99+
}
100+
return;
101+
}
102+
}
103+
if (editor instanceof CompareEditor existingCompare) { // if selection is from compare editor itself
104+
ISelection selection = existingCompare.getSite().getSelectionProvider().getSelection();
105+
if (selection instanceof ITextSelection textSelection) {
106+
String selectedText = textSelection.getText();
107+
String fileContents = new String(file.getContents().readAllBytes(), file.getCharset());
108+
showComparison(fileContents, fileName, selectedText);
109+
}
110+
}
111+
}
112+
113+
/**
114+
* Shows comparison result
115+
*
116+
* @param source Either selection from current editor or entire
117+
* editor if no selection
118+
* @param fileName Editor file name
119+
* @param clipboardContents Contents in clipboard
120+
*/
121+
private void showComparison(String source, String fileName, String clipboardContents) {
122+
class ClipboardTypedElement implements ITypedElement, IStreamContentAccessor {
123+
private final String name;
124+
private final String content;
125+
126+
public ClipboardTypedElement(String name, String content) {
127+
this.name = name;
128+
this.content = content;
129+
}
130+
131+
@Override
132+
public String getName() {
133+
return name;
134+
}
135+
136+
@Override
137+
public Image getImage() {
138+
return null;
139+
}
140+
141+
@Override
142+
public String getType() {
143+
return null;
144+
}
145+
146+
@Override
147+
public InputStream getContents() throws CoreException {
148+
return new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
149+
}
150+
151+
}
152+
CompareConfiguration config = new CompareConfiguration();
153+
config.setLeftLabel(fileName);
154+
config.setRightLabel(clipboard);
155+
config.setLeftEditable(true);
156+
config.setRightEditable(true);
157+
CompareEditorInput compareInput = new CompareEditorInput(config) {
158+
@Override
159+
protected Object prepareInput(IProgressMonitor monitor)
160+
throws InvocationTargetException, InterruptedException {
161+
return new DiffNode(new ClipboardTypedElement(fileName, source),
162+
new ClipboardTypedElement(clipboard, clipboardContents));
163+
164+
}
165+
};
166+
CompareUI.openCompareEditor(compareInput);
167+
}
168+
169+
/**
170+
* Returns Clipboard Object or null if there is nothing in clipboard
171+
*
172+
* @returns Clipboard Object or null
173+
*/
174+
private Object getClipboard() {
175+
Clipboard clip = new Clipboard(Display.getDefault());
176+
return clip.getContents(TextTransfer.getInstance());
177+
}
178+
179+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 IBM Corporation 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+
* IBM Corporation - initial API and implementation
13+
*******************************************************************************/
14+
package org.eclipse.compare.internal;
15+
16+
import java.io.ByteArrayInputStream;
17+
import java.nio.charset.StandardCharsets;
18+
19+
import org.eclipse.core.resources.IFile;
20+
import org.eclipse.core.resources.IResource;
21+
import org.eclipse.jface.dialogs.MessageDialog;
22+
import org.eclipse.jface.text.IDocument;
23+
import org.eclipse.jface.text.ITextSelection;
24+
import org.eclipse.jface.viewers.ISelection;
25+
import org.eclipse.swt.dnd.Clipboard;
26+
import org.eclipse.swt.dnd.TextTransfer;
27+
import org.eclipse.swt.widgets.Display;
28+
import org.eclipse.swt.widgets.Shell;
29+
import org.eclipse.ui.IEditorInput;
30+
import org.eclipse.ui.IEditorPart;
31+
import org.eclipse.ui.IFileEditorInput;
32+
import org.eclipse.ui.IWorkbenchPage;
33+
import org.eclipse.ui.PlatformUI;
34+
import org.eclipse.ui.texteditor.ITextEditor;
35+
36+
public class ClipboardReplace extends BaseCompareAction {
37+
38+
@Override
39+
protected void run(ISelection selection) {
40+
IFile[] files = Utilities.getFiles(selection);
41+
for (IFile file : files) {
42+
try {
43+
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
44+
IEditorPart editor = page.getActiveEditor();
45+
IEditorInput input = editor.getEditorInput();
46+
if (input instanceof IFileEditorInput ed) {
47+
IFile file2 = ed.getFile();
48+
String fileName2 = file2.getName();
49+
if (!file.getName().equals(fileName2)) {
50+
ByteArrayInputStream source = new ByteArrayInputStream(
51+
getClipboard().toString().getBytes(StandardCharsets.UTF_8));
52+
file.setContents(source, IResource.FORCE, null);
53+
return;
54+
}
55+
}
56+
if (editor instanceof ITextEditor txtEditor) {
57+
ISelection selection2 = txtEditor.getSelectionProvider().getSelection();
58+
if (selection2 instanceof ITextSelection textSelection) {
59+
int offset = textSelection.getOffset();
60+
int len = textSelection.getLength();
61+
if (len > 0) {
62+
IDocument doc = ((ITextEditor) editor).getDocumentProvider()
63+
.getDocument(editor.getEditorInput());
64+
doc.replace(offset, len, getClipboard().toString());
65+
return;
66+
}
67+
ByteArrayInputStream source = new ByteArrayInputStream(
68+
getClipboard().toString().getBytes(StandardCharsets.UTF_8));
69+
file.setContents(source, IResource.FORCE, null);
70+
}
71+
}
72+
73+
} catch (Exception e) {
74+
Shell parentShell = CompareUIPlugin.getShell();
75+
MessageDialog.openError(parentShell, "Replace Failed", e.getMessage()); //$NON-NLS-1$
76+
}
77+
}
78+
}
79+
@Override
80+
protected boolean isEnabled(ISelection selection) {
81+
return Utilities.getFiles(selection).length == 1 && getClipboard() != null;
82+
}
83+
84+
/**
85+
* Returns Clipboard Object or null if there is nothing in clipboard
86+
*
87+
* @returns Clipboard Object or null
88+
*/
89+
private Object getClipboard() {
90+
Clipboard clip = new Clipboard(Display.getDefault());
91+
return clip.getContents(TextTransfer.getInstance());
92+
}
93+
94+
}

team/bundles/org.eclipse.compare/plugin.properties

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
###############################################################################
2-
# Copyright (c) 2000, 2016 IBM Corporation and others.
2+
# Copyright (c) 2000, 2025 IBM Corporation and others.
33
#
44
# This program and the accompanying materials
55
# are made available under the terms of the Eclipse Public License 2.0
@@ -98,6 +98,12 @@ CompareWithOtherResource.tooltip= Open the 'Compare With' Dialog
9898
CompareWithHistoryAction.label= &Local History...
9999
CompareWithHistoryAction.tooltip= Compare the Selected Resource with Local History
100100

101+
CompareWithClipboardAction.label= Clipboard
102+
CompareWithClipboardAction.tooltip= Compare the selection or entire contents in editor with contents in clipboard
103+
104+
ReplaceWithClipboardAction.label= Clipboard
105+
ReplaceWithClipboardAction.tooltip= Replace the selection or entire contents in editor with contents in clipboard
106+
101107
ReplaceWithMenu.label= Rep&lace With
102108

103109
ReplaceFromHistoryAction.label= &Local History...

team/bundles/org.eclipse.compare/plugin.xml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,14 @@
296296
enablesFor="1"
297297
id="replaceWithPreviousFromHistory">
298298
</action>
299+
<action
300+
label="%ReplaceWithClipboardAction.label"
301+
tooltip="%ReplaceWithClipboardAction.tooltip"
302+
class="org.eclipse.compare.internal.ClipboardReplace"
303+
menubarPath="replaceWithMenu/replaceWithGroup"
304+
enablesFor="1"
305+
id="replaceWithClipboard">
306+
</action>
299307
</objectContribution>
300308
<objectContribution
301309
objectClass="org.eclipse.core.resources.IFile"
@@ -309,6 +317,14 @@
309317
name="compareWithGroup">
310318
</separator>
311319
</menu>
320+
<action
321+
label="%CompareWithClipboardAction.label"
322+
tooltip="%CompareWithClipboardAction.tooltip"
323+
class="org.eclipse.compare.internal.ClipboardCompare"
324+
menubarPath="compareWithMenu/compareWithGroup"
325+
enablesFor="1"
326+
id="compareWithClipboard">
327+
</action>
312328
<action
313329
label="%CompareWithHistoryAction.label"
314330
tooltip="%CompareWithHistoryAction.tooltip"

0 commit comments

Comments
 (0)