From e10ec75177ec1960f96428e89d75d05260e16b58 Mon Sep 17 00:00:00 2001 From: Sougandh S Date: Fri, 24 Jul 2026 09:13:59 +0530 Subject: [PATCH] Add Compare with Clipboard action to Console Adds a Compare with Clipboard action to the Eclipse Console view, allowing users to compare the selected console output with the contents of the system clipboard using Eclipse's compare editor. --- .../META-INF/MANIFEST.MF | 2 + .../eclipse/ui/console/TextConsolePage.java | 4 + .../console/CompareConsoleWithClipboard.java | 145 ++++++++++++++++++ .../ui/internal/console/ConsoleMessages.java | 11 +- .../console/ConsoleMessages.properties | 10 +- .../console/IConsoleHelpContextIds.java | 4 +- 6 files changed, 171 insertions(+), 5 deletions(-) create mode 100644 debug/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/CompareConsoleWithClipboard.java diff --git a/debug/org.eclipse.ui.console/META-INF/MANIFEST.MF b/debug/org.eclipse.ui.console/META-INF/MANIFEST.MF index 000b0c4d9b0..3420436d3d2 100644 --- a/debug/org.eclipse.ui.console/META-INF/MANIFEST.MF +++ b/debug/org.eclipse.ui.console/META-INF/MANIFEST.MF @@ -40,3 +40,5 @@ Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-21 Automatic-Module-Name: org.eclipse.ui.console Require-Capability: eclipse.swt;filter:="(image.format=svg)" +Import-Package: org.eclipse.compare;resolution:=optional, + org.eclipse.compare.structuremergeviewer;resolution:=optional diff --git a/debug/org.eclipse.ui.console/src/org/eclipse/ui/console/TextConsolePage.java b/debug/org.eclipse.ui.console/src/org/eclipse/ui/console/TextConsolePage.java index 8aef9959185..7c009a0deda 100644 --- a/debug/org.eclipse.ui.console/src/org/eclipse/ui/console/TextConsolePage.java +++ b/debug/org.eclipse.ui.console/src/org/eclipse/ui/console/TextConsolePage.java @@ -48,6 +48,7 @@ import org.eclipse.ui.actions.ActionFactory; import org.eclipse.ui.console.actions.ClearOutputAction; import org.eclipse.ui.console.actions.TextViewerAction; +import org.eclipse.ui.internal.console.CompareConsoleWithClipboard; import org.eclipse.ui.internal.console.ConsoleMessages; import org.eclipse.ui.internal.console.ConsoleResourceBundleMessages; import org.eclipse.ui.internal.console.FollowHyperlinkAction; @@ -366,6 +367,9 @@ protected void contextMenuAboutToShow(IMenuManager menuManager) { menuManager.add(fGlobalActions.get(ITextEditorActionConstants.FIND_NEXT)); menuManager.add(fGlobalActions.get(ITextEditorActionConstants.FIND_PREVIOUS)); menuManager.add(new FollowHyperlinkAction(fViewer.getHyperlink())); + if (CompareConsoleWithClipboard.isAvailable()) { + menuManager.add(new CompareConsoleWithClipboard(fViewer)); + } menuManager.add(fClearOutputAction); menuManager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); diff --git a/debug/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/CompareConsoleWithClipboard.java b/debug/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/CompareConsoleWithClipboard.java new file mode 100644 index 00000000000..5acb39a919a --- /dev/null +++ b/debug/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/CompareConsoleWithClipboard.java @@ -0,0 +1,145 @@ +/******************************************************************************* + * Copyright (c) 2026 IBM Corporation. + * + * 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.internal.console; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.lang.reflect.InvocationTargetException; +import java.nio.charset.StandardCharsets; + +import org.eclipse.compare.CompareConfiguration; +import org.eclipse.compare.CompareEditorInput; +import org.eclipse.compare.CompareUI; +import org.eclipse.compare.IEncodedStreamContentAccessor; +import org.eclipse.compare.ITypedElement; +import org.eclipse.compare.structuremergeviewer.DiffNode; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.dnd.TextTransfer; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.console.TextConsoleViewer; + +public class CompareConsoleWithClipboard extends Action { + + private final TextConsoleViewer console; + + public CompareConsoleWithClipboard(TextConsoleViewer consoleView) { + super(ConsoleMessages.CompareConsoleWithClipboard_0); + this.console = consoleView; + setToolTipText(ConsoleMessages.CompareConsoleWithClipboard_6); + PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IConsoleHelpContextIds.CONSOLE_COMPARE_ACTION); + } + + @Override + public void run() { + ISelection selection = console.getSelection(); + if (selection instanceof ITextSelection textSelection) { + String selectedText = textSelection.getText(); + if (selectedText.isEmpty()) { + selectedText = console.getDocument().get(); + } + compareWithClipboard(ConsoleMessages.CompareConsoleWithClipboard_1, selectedText); + } + } + + private static void compareWithClipboard(String leftLabel, String content) { + Object clipboardContents = getClipboard(); + if (!(clipboardContents instanceof String clipboardText)) { + MessageDialog.openInformation(Display.getDefault().getActiveShell(), ConsoleMessages.CompareConsoleWithClipboard_2, + ConsoleMessages.CompareConsoleWithClipboard_3); + return; + } + + class StringTypedElement implements ITypedElement, IEncodedStreamContentAccessor { + private final String name; + private final String text; + + StringTypedElement(String name, String text) { + this.name = name; + this.text = text; + } + + @Override + public String getName() { + return name; + } + + @Override + public Image getImage() { + return null; + } + + @Override + public String getType() { + return ITypedElement.TEXT_TYPE; + } + + @Override + public String getCharset() { + return StandardCharsets.UTF_8.name(); + } + + @Override + public InputStream getContents() { + return new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8)); + } + } + + CompareConfiguration configuration = new CompareConfiguration(); + configuration.setLeftLabel(leftLabel); + configuration.setRightLabel(ConsoleMessages.CompareConsoleWithClipboard_4); + configuration.setLeftEditable(false); + configuration.setRightEditable(false); + + CompareEditorInput input = new CompareEditorInput(configuration) { + @Override + protected Object prepareInput(IProgressMonitor monitor) + throws InvocationTargetException, InterruptedException { + return new DiffNode(new StringTypedElement(leftLabel, content), + new StringTypedElement(ConsoleMessages.CompareConsoleWithClipboard_4, clipboardText)); + } + }; + + input.setTitle(ConsoleMessages.CompareConsoleWithClipboard_5); + CompareUI.openCompareEditor(input); + } + + private static Object getClipboard() { + Clipboard clipboard = new Clipboard(Display.getDefault()); + try { + return clipboard.getContents(TextTransfer.getInstance()); + } finally { + clipboard.dispose(); + } + } + + public static boolean isAvailable() { + org.osgi.framework.Bundle bundle = Platform.getBundle("org.eclipse.compare"); //$NON-NLS-1$ + return bundle != null && (bundle.getState() & (org.osgi.framework.Bundle.RESOLVED + | org.osgi.framework.Bundle.STARTING | org.osgi.framework.Bundle.ACTIVE)) != 0; + } + + @Override + public boolean isEnabled() { + return console.getDocument().getLength() > 0; + } +} + diff --git a/debug/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/ConsoleMessages.java b/debug/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/ConsoleMessages.java index 47414b13a89..94e2c311c59 100644 --- a/debug/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/ConsoleMessages.java +++ b/debug/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/ConsoleMessages.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2014 IBM Corporation and others. + * Copyright (c) 2000, 2026 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -20,7 +20,6 @@ public class ConsoleMessages extends NLS { private static final String BUNDLE_NAME = "org.eclipse.ui.internal.console.ConsoleMessages";//$NON-NLS-1$ public static String AbstractConsole_0; - public static String ConsoleDropDownAction_0; public static String ConsoleDropDownAction_1; @@ -80,4 +79,12 @@ public class ConsoleMessages extends NLS { public static String PatternMatchListenerExtension_5; public static String UpdatingConsoleState; + + public static String CompareConsoleWithClipboard_0; + public static String CompareConsoleWithClipboard_1; + public static String CompareConsoleWithClipboard_2; + public static String CompareConsoleWithClipboard_3; + public static String CompareConsoleWithClipboard_4; + public static String CompareConsoleWithClipboard_5; + public static String CompareConsoleWithClipboard_6; } diff --git a/debug/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/ConsoleMessages.properties b/debug/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/ConsoleMessages.properties index af42f0c44d6..24e74e38c93 100644 --- a/debug/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/ConsoleMessages.properties +++ b/debug/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/ConsoleMessages.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2000, 2014 IBM Corporation and others. +# Copyright (c) 2000, 2026 IBM Corporation and others. # # This program and the accompanying materials # are made available under the terms of the Eclipse Public License 2.0 @@ -15,6 +15,14 @@ AbstractConsole_0=Exception occurred during console property change notification. +CompareConsoleWithClipboard_0=Compare with Clipboard +CompareConsoleWithClipboard_1=Console +CompareConsoleWithClipboard_2=Comparison Failed +CompareConsoleWithClipboard_3=Clipboard does not contain text +CompareConsoleWithClipboard_4=Clipboard +CompareConsoleWithClipboard_5=Compare with Clipboard +CompareConsoleWithClipboard_6=Compare console output with clipboard content + ConsoleDropDownAction_0=Select Console ConsoleDropDownAction_1=Display Selected Console diff --git a/debug/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/IConsoleHelpContextIds.java b/debug/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/IConsoleHelpContextIds.java index a820ed87805..d568f21b1d5 100644 --- a/debug/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/IConsoleHelpContextIds.java +++ b/debug/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/IConsoleHelpContextIds.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2020 IBM Corporation and others. + * Copyright (c) 2000, 2026 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -42,7 +42,7 @@ public interface IConsoleHelpContextIds { String CONSOLE_OPEN_CONSOLE_ACTION = PREFIX + "console_open_console_action_context"; //$NON-NLS-1$ String CONSOLE_DISPLAY_CONSOLE_ACTION = PREFIX + "console_display_console_action"; //$NON-NLS-1$ String CONSOLE_PIN_CONSOLE_ACITON = PREFIX + "console_pin_console_action"; //$NON-NLS-1$ - + String CONSOLE_COMPARE_ACTION = PREFIX + "console_compare_action_context"; //$NON-NLS-1$ // Views String CONSOLE_VIEW = PREFIX + "console_view_context"; //$NON-NLS-1$