Skip to content

Commit b3f124c

Browse files
SougandhSvogella
authored andcommitted
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 2e1acee commit b3f124c

File tree

4 files changed

+303
-1
lines changed

4 files changed

+303
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
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+
private String compareFailed = "Comparision Failed"; //$NON-NLS-1$
50+
51+
@Override
52+
protected void run(ISelection selection) {
53+
IFile[] files = Utilities.getFiles(selection);
54+
Shell parentShell = CompareUIPlugin.getShell();
55+
for (IFile file : files) {
56+
try {
57+
processComparison(file, parentShell);
58+
} catch (Exception e) {
59+
MessageDialog.openError(parentShell, compareFailed, e.getMessage());
60+
}
61+
}
62+
}
63+
@Override
64+
protected boolean isEnabled(ISelection selection) {
65+
return Utilities.getFiles(selection).length == 1 && getClipboard() != null;
66+
}
67+
68+
/**
69+
* Process comparison with selection or entire editor contents with contents in
70+
* clipboard
71+
*
72+
* @param file Editor file
73+
* @param parentShell The shell containing this window's controls
74+
* @throws IOException, CoreException
75+
*/
76+
private void processComparison(IFile file, Shell parentShell) throws IOException, CoreException {
77+
String cb = getClipboard().toString();
78+
String fileName = file.getName();
79+
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
80+
IEditorPart editor = page.getActiveEditor();
81+
IEditorInput input = editor.getEditorInput();
82+
if (input instanceof IFileEditorInput fileEditorInp) {
83+
IFile file2 = fileEditorInp.getFile();
84+
String fileName2 = file2.getName();
85+
if (!file.getName().equals(fileName2)) {
86+
String fileContents = new String(file.getContents().readAllBytes(), file.getCharset());
87+
showComparison(fileContents, fileName, cb, parentShell);
88+
return;
89+
}
90+
}
91+
final String selectionContents;
92+
if (editor instanceof ITextEditor txtEditor) {
93+
ISelection selection = txtEditor.getSelectionProvider().getSelection();
94+
if (selection instanceof ITextSelection textSelection) {
95+
selectionContents = textSelection.getText();
96+
if (selectionContents.isEmpty()) {
97+
String fileContents = new String(file.getContents().readAllBytes(), file.getCharset());
98+
showComparison(fileContents, fileName, cb, parentShell);
99+
} else {
100+
showComparison(selectionContents, fileName, cb, parentShell);
101+
}
102+
return;
103+
}
104+
}
105+
if (editor instanceof CompareEditor existingCompare) { // if selection is from compare editor itself
106+
ISelection selection = existingCompare.getSite().getSelectionProvider().getSelection();
107+
if (selection instanceof ITextSelection textSelection) {
108+
String selectedText = textSelection.getText();
109+
String fileContents = new String(file.getContents().readAllBytes(), file.getCharset());
110+
showComparison(fileContents, fileName, selectedText, parentShell);
111+
}
112+
}
113+
}
114+
115+
/**
116+
* Shows comparison result
117+
*
118+
* @param source Either selection from current editor or entire
119+
* editor if no selection
120+
* @param fileName Editor file name
121+
* @param clipboardContents Contents in clipboard
122+
* @param parentShell The shell containing this window's controls
123+
*/
124+
private void showComparison(String source, String fileName, String clipboardContents, Shell parentShell) {
125+
class ClipboardTypedElement implements ITypedElement, IStreamContentAccessor {
126+
private final String name;
127+
private final String content;
128+
129+
public ClipboardTypedElement(String name, String content) {
130+
this.name = name;
131+
this.content = content;
132+
}
133+
134+
@Override
135+
public String getName() {
136+
return name;
137+
}
138+
139+
@Override
140+
public Image getImage() {
141+
return null;
142+
}
143+
144+
@Override
145+
public String getType() {
146+
return null;
147+
}
148+
149+
@Override
150+
public InputStream getContents() throws CoreException {
151+
return new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
152+
}
153+
154+
}
155+
if (source == null) {
156+
MessageDialog.openInformation(parentShell, compareFailed, "Failed to process selected file"); //$NON-NLS-1$
157+
return;
158+
}
159+
CompareConfiguration config = new CompareConfiguration();
160+
config.setLeftLabel(fileName);
161+
config.setRightLabel(clipboard);
162+
config.setLeftEditable(true);
163+
config.setRightEditable(true);
164+
CompareEditorInput compareInput = new CompareEditorInput(config) {
165+
@Override
166+
protected Object prepareInput(IProgressMonitor monitor)
167+
throws InvocationTargetException, InterruptedException {
168+
return new DiffNode(new ClipboardTypedElement(fileName, source),
169+
new ClipboardTypedElement(clipboard, clipboardContents));
170+
171+
}
172+
};
173+
CompareUI.openCompareEditor(compareInput);
174+
}
175+
176+
/**
177+
* Returns Clipboard Object or null if there is nothing in clipboard
178+
*
179+
* @returns Clipboard Object or null
180+
*/
181+
private Object getClipboard() {
182+
Clipboard clip = new Clipboard(Display.getDefault());
183+
return clip.getContents(TextTransfer.getInstance());
184+
}
185+
186+
}
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

+7-1
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

+16
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)