diff --git a/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/tracermi/TerminalSession.java b/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/tracermi/TerminalSession.java index c9269758d8..eb522ed4b2 100644 --- a/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/tracermi/TerminalSession.java +++ b/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/tracermi/TerminalSession.java @@ -17,15 +17,39 @@ package ghidra.debug.api.tracermi; import java.io.IOException; +import ghidra.app.services.Terminal; + /** * A terminal with some back-end element attached to it */ public interface TerminalSession extends AutoCloseable { @Override - void close() throws IOException; + default void close() throws IOException { + terminate(); + terminal().close(); + } + + /** + * The handle to the terminal + * + * @return the handle + */ + Terminal terminal(); + + /** + * Ensure the session is visible + * + *
+ * The window should be displayed and brought to the front. + */ + default void show() { + terminal().toFront(); + } /** * Terminate the session without closing the terminal + * + * @throws IOException if an I/O issue occurs during termination */ void terminate() throws IOException; @@ -34,7 +58,9 @@ public interface TerminalSession extends AutoCloseable { * * @return true for terminated, false for active */ - boolean isTerminated(); + default boolean isTerminated() { + return terminal().isTerminated(); + } /** * Provide a human-readable description of the session @@ -42,4 +68,22 @@ public interface TerminalSession extends AutoCloseable { * @return the description */ String description(); + + /** + * Get the terminal contents as a string (no attributes) + * + * @return the content + */ + default String content() { + return terminal().getFullText(); + } + + /** + * Get the current title of the terminal + * + * @return the title + */ + default String title() { + return terminal().getSubTitle(); + } } diff --git a/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/tracermi/TraceRmiLaunchOffer.java b/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/tracermi/TraceRmiLaunchOffer.java index bd69e0310c..85c16bbeb2 100644 --- a/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/tracermi/TraceRmiLaunchOffer.java +++ b/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/tracermi/TraceRmiLaunchOffer.java @@ -71,6 +71,12 @@ public interface TraceRmiLaunchOffer { this.exception = exception; } + public void showTerminals() { + for (TerminalSession session : sessions.values()) { + session.show(); + } + } + @Override public void close() throws Exception { if (connection != null) { diff --git a/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/AbstractTraceRmiLaunchOffer.java b/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/AbstractTraceRmiLaunchOffer.java index 1857819ac1..d266593deb 100644 --- a/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/AbstractTraceRmiLaunchOffer.java +++ b/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/AbstractTraceRmiLaunchOffer.java @@ -67,12 +67,6 @@ public abstract class AbstractTraceRmiLaunchOffer implements TraceRmiLaunchOffer protected record PtyTerminalSession(Terminal terminal, Pty pty, PtySession session, Thread waiter) implements TerminalSession { - @Override - public void close() throws IOException { - terminate(); - terminal.close(); - } - @Override public void terminate() throws IOException { terminal.terminated(); @@ -81,11 +75,6 @@ public abstract class AbstractTraceRmiLaunchOffer implements TraceRmiLaunchOffer waiter.interrupt(); } - @Override - public boolean isTerminated() { - return terminal.isTerminated(); - } - @Override public String description() { return session.description(); @@ -94,23 +83,12 @@ public abstract class AbstractTraceRmiLaunchOffer implements TraceRmiLaunchOffer protected record NullPtyTerminalSession(Terminal terminal, Pty pty, String name) implements TerminalSession { - @Override - public void close() throws IOException { - terminate(); - terminal.close(); - } - @Override public void terminate() throws IOException { terminal.terminated(); pty.close(); } - @Override - public boolean isTerminated() { - return terminal.isTerminated(); - } - @Override public String description() { return name; @@ -700,6 +678,7 @@ public abstract class AbstractTraceRmiLaunchOffer implements TraceRmiLaunchOffer if (prompt) { switch (promptError(result)) { case KEEP: + result.showTerminals(); return result; case RETRY: try { diff --git a/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/LaunchFailureDialog.java b/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/LaunchFailureDialog.java index 84476059f3..bb36376626 100644 --- a/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/LaunchFailureDialog.java +++ b/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/LaunchFailureDialog.java @@ -15,7 +15,10 @@ */ package ghidra.app.plugin.core.debug.gui.tracermi.launcher; +import java.util.Arrays; +import java.util.List; import java.util.Map.Entry; +import java.util.stream.Collectors; import docking.widgets.OptionDialog; import ghidra.debug.api.tracermi.TerminalSession; @@ -26,7 +29,7 @@ import ghidra.util.HelpLocation; public class LaunchFailureDialog extends OptionDialog { private static final String MSGPAT_PART_TOP = """
-%s""".formatted( + session.title(), + note, + content); + } + protected static String htmlResources(LaunchResult result) { StringBuilder sb = new StringBuilder(); for (Entry
* This only affects the primary buffer. The alternate buffer has no scroll-back. + * + * @param rows the number of scroll-back rows */ void setMaxScrollBackRows(int rows); @@ -210,4 +217,9 @@ public interface Terminal extends AutoCloseable { * @return true for terminated, false for active */ boolean isTerminated(); + + /** + * Bring the terminal to the front of the UI + */ + void toFront(); } diff --git a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/app/plugin/core/terminal/TerminalProviderTest.java b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/app/plugin/core/terminal/TerminalProviderTest.java index 2206663601..952c61cb73 100644 --- a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/app/plugin/core/terminal/TerminalProviderTest.java +++ b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/app/plugin/core/terminal/TerminalProviderTest.java @@ -482,6 +482,23 @@ public class TerminalProviderTest extends AbstractGhidraHeadedDebuggerTest { } } + @Test + @SuppressWarnings("resource") + public void testGetFullText() throws Exception { + terminalService = addPlugin(tool, TerminalPlugin.class); + + try (DefaultTerminal term = (DefaultTerminal) terminalService + .createNullTerminal(Charset.forName("UTF-8"), buf -> { + })) { + term.setFixedSize(80, 25); + term.injectDisplayOutput(TEST_CONTENTS); + + assertEquals(""" + term Term + noterm""", term.getFullText().trim()); + } + } + protected String csi(char f, int... params) { return "\033[" + IntStream.of(params).mapToObj(Integer::toString).collect(Collectors.joining(";")) + f;