diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/InterpreterConnection.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/InterpreterConnection.java index aa11d0e5ce..236d039d62 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/InterpreterConnection.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/InterpreterConnection.java @@ -21,7 +21,16 @@ import javax.swing.ImageIcon; import ghidra.app.plugin.core.console.CodeCompletion; +/** + * A connection between an implementation of an interpreter and its generic GUI components. + */ public interface InterpreterConnection { + + /** + * Gets the title of the interpreter. + * + * @return The title of the interpreter + */ public String getTitle(); /** @@ -31,15 +40,11 @@ public interface InterpreterConnection { */ public ImageIcon getIcon(); + /** + * Gets a {@link List} of {@link CodeCompletion code completions} for the given command. + * + * @param cmd The command to get code completions for + * @return A {@link List} of {@link CodeCompletion code completions} for the given command + */ public List getCompletions(String cmd); - - /** - * Interrupts what the interpreter is currently doing. - */ - public void interrupt(); - - /** - * Resets the interpreter. Each interpreter can define what "reset" for them means. - */ - public void reset(); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/InterpreterPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/InterpreterPanel.java index 95bf73121d..d148b6cf9a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/InterpreterPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/InterpreterPanel.java @@ -277,20 +277,6 @@ public class InterpreterPanel extends JPanel implements OptionsChangeListener { completionWindow.setVisible(false); e.consume(); break; - case KeyEvent.VK_D: - if (e.isControlDown()) { - // Ctrl+D - reset interpreter - e.consume(); - interpreter.reset(); - } - break; - case KeyEvent.VK_I: - if (e.isControlDown()) { - // Ctrl+I - interrupt interpreter - e.consume(); - interpreter.interrupt(); - } - break; default: // Check for the completion window trigger on input that contains text diff --git a/Ghidra/Features/Python/src/main/help/help/topics/Python/interpreter.html b/Ghidra/Features/Python/src/main/help/help/topics/Python/interpreter.html index e6d942c69a..a351b93db0 100644 --- a/Ghidra/Features/Python/src/main/help/help/topics/Python/interpreter.html +++ b/Ghidra/Features/Python/src/main/help/help/topics/Python/interpreter.html @@ -55,13 +55,34 @@

+

Clear

+
+

+ This command clears the interpreter's display. Its effect is purely visual. + It does not affect the state of the interpreter in any way. +

+
+ +

Interrupt

+
+

+ This command issues a keyboard interrupt to the interpreter, which can be used to interrupt + long running commands or loops. +

+
+ +

Reset

+
+

+ This command resets the interpreter, which clears the display and resets all state. +

+
+

Keybindings

- The Ghidra Python Interpreter supports the following keybindings: + The Ghidra Python Interpreter supports the following hard-coded keybindings:

-

Clear

-
-

- This command clears the interpreter's display. Its effect is purely visual. - It does not affect the state of the interpreter in any way. -

-
-

Provided by: PythonPlugin

Related Topics:

diff --git a/Ghidra/Features/Python/src/main/java/ghidra/python/PythonPlugin.java b/Ghidra/Features/Python/src/main/java/ghidra/python/PythonPlugin.java index a1f5fd692b..f2c24b4e05 100644 --- a/Ghidra/Features/Python/src/main/java/ghidra/python/PythonPlugin.java +++ b/Ghidra/Features/Python/src/main/java/ghidra/python/PythonPlugin.java @@ -15,6 +15,7 @@ */ package ghidra.python; +import java.awt.event.KeyEvent; import java.io.*; import java.util.List; @@ -22,6 +23,9 @@ import javax.swing.ImageIcon; import org.python.core.PySystemState; +import docking.ActionContext; +import docking.DockingUtils; +import docking.action.*; import generic.jar.ResourceFile; import ghidra.app.CorePluginPackage; import ghidra.app.plugin.PluginCategoryNames; @@ -34,6 +38,7 @@ import ghidra.framework.options.ToolOptions; import ghidra.framework.plugintool.PluginInfo; import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.util.PluginStatus; +import ghidra.util.HelpLocation; import ghidra.util.task.*; import resources.ResourceManager; @@ -120,6 +125,45 @@ public class PythonPlugin extends ProgramPlugin getTool().getService(InterpreterPanelService.class).createInterpreterPanel(this, false); welcome(); console.addFirstActivationCallback(() -> resetInterpreter()); + createActions(); + } + + /** + * Creates various actions for the plugin. + */ + private void createActions() { + + // Interrupt Interpreter + DockingAction interruptAction = new DockingAction("Interrupt Interpreter", getName()) { + @Override + public void actionPerformed(ActionContext context) { + interrupt(); + } + }; + interruptAction.setDescription("Interrupt Interpreter"); + interruptAction.setToolBarData( + new ToolBarData(ResourceManager.loadImage("images/dialog-cancel.png"), null)); + interruptAction.setEnabled(true); + interruptAction.setKeyBindingData( + new KeyBindingData(KeyEvent.VK_I, DockingUtils.CONTROL_KEY_MODIFIER_MASK)); + interruptAction.setHelpLocation(new HelpLocation(getTitle(), "Interrupt_Interpreter")); + console.addAction(interruptAction); + + // Reset Interpreter + DockingAction resetAction = new DockingAction("Reset Interpreter", getName()) { + @Override + public void actionPerformed(ActionContext context) { + reset(); + } + }; + resetAction.setDescription("Reset Interpreter"); + resetAction.setToolBarData( + new ToolBarData(ResourceManager.loadImage("images/reload3.png"), null)); + resetAction.setEnabled(true); + resetAction.setKeyBindingData( + new KeyBindingData(KeyEvent.VK_D, DockingUtils.CONTROL_KEY_MODIFIER_MASK)); + resetAction.setHelpLocation(new HelpLocation(getTitle(), "Reset_Interpreter")); + console.addAction(resetAction); } /** @@ -253,7 +297,9 @@ public class PythonPlugin extends ProgramPlugin super.dispose(); } - @Override + /** + * Interrupts what the interpreter is currently doing. + */ public void interrupt() { if (interpreter == null) { return; @@ -262,7 +308,9 @@ public class PythonPlugin extends ProgramPlugin console.setPrompt(interpreter.getPrimaryPrompt()); } - @Override + /** + * Resets the interpreter's state. + */ public void reset() { // Do an interrupt in case there is a loop or something running