mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
GT-2901: Python interpreter keybinding improvements.
This commit is contained in:
parent
d0ee2aa26b
commit
b2c65d147d
4 changed files with 89 additions and 37 deletions
|
@ -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<CodeCompletion> 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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -55,13 +55,34 @@
|
|||
</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H2><A name="Clear_Interpreter"></A>Clear <IMG border="0" src="images/erase16.png"></H2>
|
||||
<BLOCKQUOTE>
|
||||
<P>
|
||||
This command clears the interpreter's display. Its effect is purely visual.
|
||||
It does not affect the state of the interpreter in any way.
|
||||
</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H2><A name="Interrupt_Interpreter"></A>Interrupt <IMG border="0" src="images/dialog-cancel.png"></H2>
|
||||
<BLOCKQUOTE>
|
||||
<P>
|
||||
This command issues a keyboard interrupt to the interpreter, which can be used to interrupt
|
||||
long running commands or loops.
|
||||
</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H2><A name="Reset_Interpreter"></A>Reset <IMG border="0" src="images/reload3.png"></H2>
|
||||
<BLOCKQUOTE>
|
||||
<P>
|
||||
This command resets the interpreter, which clears the display and resets all state.
|
||||
</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H2>Keybindings</H2>
|
||||
<BLOCKQUOTE>
|
||||
<P>
|
||||
The Ghidra <I>Python Interpreter</I> supports the following keybindings:
|
||||
The Ghidra <I>Python Interpreter</I> supports the following hard-coded keybindings:
|
||||
<UL>
|
||||
<LI><B>CTRL+D:</B> Clear the console and reset the interpreter</LI>
|
||||
<LI><B>CTRL+I:</B> Interrupt the interpreter</LI>
|
||||
<LI><B>(up):</B> Move backward in command stack</LI>
|
||||
<LI><B>(down):</B> Move forward in command stack</LI>
|
||||
<LI><B>TAB:</B> Show code completion window</LI>
|
||||
|
@ -142,14 +163,6 @@
|
|||
</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H2><A name="Clear_Interpreter"></A>Clear <IMG border="0" src="images/erase16.png"></H2>
|
||||
<BLOCKQUOTE>
|
||||
<P>
|
||||
This command clears the interpreter's display. Its effect is purely visual.
|
||||
It does not affect the state of the interpreter in any way.
|
||||
</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<P align="left" class="providedbyplugin">Provided by: <I>PythonPlugin</I></P>
|
||||
|
||||
<P class="relatedtopic">Related Topics:</P>
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue