diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScript.java b/Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScript.java index 95f972327e..91a46d506b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScript.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScript.java @@ -94,8 +94,8 @@ import ghidra.util.task.TaskMonitor; * *
- * - *All scripts, when run, will be handed the current state in the form of class instance + * + *
All scripts, when run, will be handed the current state in the form of class instance * variable. These variables are: *
*
- * + * * * @param title the title of the dialog (in GUI mode) or the first part of the variable name * (in headless mode or when using .properties file) @@ -2475,7 +2495,7 @@ public abstract class GhidraScript extends FlatProgramAPI { * .properties value (if it exists), or throws an Exception if there is an invalid or * missing .properties value. * - * + * * * @param title the title of the dialog (in GUI mode) or the first part of the variable name * (in headless mode or when using .properties file) @@ -2549,7 +2569,7 @@ public abstract class GhidraScript extends FlatProgramAPI { * .properties byte pattern value (if it exists), or throws an Exception if there is * an invalid or missing .properties value. * - * + * * * @param title the title of the dialog (in GUI mode) or the first part of the variable * name (in headless mode or when using .properties file) @@ -2608,7 +2628,7 @@ public abstract class GhidraScript extends FlatProgramAPI { * then that value is returned. Otherwise, an Exception is thrown if there is an * invalid or missing .properties value. * - * + * * * @param title the title of the pop-up dialog (in GUI mode) or the variable name (in * headless mode) @@ -2694,7 +2714,7 @@ public abstract class GhidraScript extends FlatProgramAPI { * then that value is returned. Otherwise, an Exception is thrown if there is an invalid * or missing .properties value. * - * + * * @param title the title of the pop-up dialog (in GUI mode) or the variable name (in headless * mode or when using .properties file) * @throws IllegalArgumentException if in headless mode, there was a missing or invalid domain @@ -2831,7 +2851,7 @@ public abstract class GhidraScript extends FlatProgramAPI { * .properties value (if it exists), or throws an Exception if there is an invalid or * missing .properties value. * - * + * * * @param title the title of the dialog (in GUI mode) or the first part of the variable name * (in headless mode or when using .properties file) @@ -2874,7 +2894,7 @@ public abstract class GhidraScript extends FlatProgramAPI { * not null or an empty String, it is returned. In all other cases, an exception * is thrown. * - * + * * * @param title the title of the dialog (in GUI mode) or the first part of the variable name * (in headless mode or when using .properties file) @@ -2948,7 +2968,7 @@ public abstract class GhidraScript extends FlatProgramAPI { * .properties value (if it exists and is a valid choice), or throws an Exception if * there is an invalid or missing .properties value. * - * + * * @param title the title of the dialog (in GUI mode) or the first part of the variable name * (in headless mode or when using .properties file) * @param message the message to display next to the input field (in GUI mode) or the second @@ -3088,7 +3108,7 @@ public abstract class GhidraScript extends FlatProgramAPI { * * @throws CancelledException if the user hits the 'cancel' button * @throws IllegalArgumentException if in headless mode, there was a missing or invalid set of - * choices specified in the .properties file + * choices specified in the .properties file */ public- @@ -140,6 +140,7 @@ public abstract class GhidraScript extends FlatProgramAPI { // Stores any parameters in a .properties file sharing the same base name as this GhidraScript protected GhidraScriptProperties propertiesFileParams; protected List
currentProgram
: the active programpotentialPropertiesFileLocs = new ArrayList<>(); + private boolean reusePreviousChoices = true; private CodeUnitFormat cuFormat; // Stores any script-specific arguments @@ -181,7 +182,7 @@ public abstract class GhidraScript extends FlatProgramAPI { /** * Set the context for this script. - * + * * @param state state object * @param monitor the monitor to use during run * @param writer the target of script "print" statements @@ -193,9 +194,28 @@ public abstract class GhidraScript extends FlatProgramAPI { loadVariablesFromState(); } + /** + * Sets whether the user's previously selected values should be used when showing the various + * {@code ask} methods. This is true by default, meaning that previous choices will be shown + * instead of any provided default value. + * @param reuse true to reuse values; false to not reuse previous values + */ + public void setReusePreviousChoices(boolean reuse) { + this.reusePreviousChoices = reuse; + } + + /** + * Returns whether scripts will reuse previously selected values when showing the various + * {@code ask} methods. + * @return true to reuse values; false to not reuse previous values + */ + public boolean getReusePreviousChoices() { + return reusePreviousChoices; + } + /** * Execute/run script and {@link #doCleanup} afterwards. - * + * * @param runState state object * @param runMonitor the monitor to use during run * @param runWriter the target of script "print" statements @@ -490,7 +510,7 @@ public abstract class GhidraScript extends FlatProgramAPI { /** * Set the script {@link #currentAddress}, {@link #currentLocation}, and update state object. - * + * * @param address the new address */ public final void setCurrentLocation(Address address) { @@ -1707,7 +1727,7 @@ public abstract class GhidraScript extends FlatProgramAPI { * action from a selection in the table. * * This method is unavailable in headless mode. - * + * * @param title the title of the dialog * @param executor the TableChooserExecuter to be used to apply operations on table entries. * @return a new TableChooserDialog. @@ -1725,7 +1745,7 @@ public abstract class GhidraScript extends FlatProgramAPI { * action from a selection in the table. *
* This method is unavailable in headless mode. - * + * * @param title of the dialog * @param executor the TableChooserExecuter to be used to apply operations on table entries. * @param isModal indicates whether the dialog should be modal or not @@ -1954,7 +1974,7 @@ public abstract class GhidraScript extends FlatProgramAPI { Map
, Object> map = getScriptMap(key1, key2); T mappedValue = null; - if (clazz != null) { + if (clazz != null && reusePreviousChoices) { mappedValue = (T) map.get(clazz); } @@ -2402,7 +2422,7 @@ public abstract class GhidraScript extends FlatProgramAPI { * .properties value (if it exists), or throws an Exception if there is an invalid or * missing .properties value. * List askChoices(String title, String message, List choices) throws CancelledException { @@ -3160,8 +3180,8 @@ public abstract class GhidraScript extends FlatProgramAPI { * @return the user-selected value(s); null if no selection was made * * @throws CancelledException if the user hits the 'cancel' button - * @throws IllegalArgumentException if choices is empty; if in headless mode, - * there was a missing or invalid set of choices specified in the .properties file + * @throws IllegalArgumentException if choices is empty; if in headless mode, + * there was a missing or invalid set of choices specified in the .properties file */ public List askChoices(String title, String message, List choices, List choiceLabels) throws CancelledException { @@ -3232,7 +3252,7 @@ public abstract class GhidraScript extends FlatProgramAPI { * then that value is returned. Otherwise, an Exception is thrown if there is an * invalid or missing .properties value. * - * + * * * @param title the title of the dialog (in GUI mode) or the first part of the variable name * (in headless mode) diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/script/GhidraScriptAskMethodsTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/script/GhidraScriptAskMethodsTest.java index d6bd07420e..eada70135d 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/script/GhidraScriptAskMethodsTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/script/GhidraScriptAskMethodsTest.java @@ -123,7 +123,7 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT } /* - * Calling askProgram() would stacktrace if the user 1) didn't select a program in the + * Calling askProgram() would stacktrace if the user 1) didn't select a program in the * tree and then 2) pressed the OK button. */ @Test @@ -151,17 +151,17 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT runSwing(() -> dtd.close()); } - /* + /* * For scripts with properties files in a different location (could be the case with subscripts), - * tests that the .properties file is found in the default location and that the default value - * for the input field is provided by the .properties file in the alternate location. - * + * tests that the .properties file is found in the default location and that the default value + * for the input field is provided by the .properties file in the alternate location. + * * @throws Exception */ @Test public void testAlternateLocationPropertiesFile() throws Exception { - // Create a temporary .properties file and set the potentialPropertiesFileLocs to look + // Create a temporary .properties file and set the potentialPropertiesFileLocs to look // in that location String tempDirPath = AbstractGTest.getTestDirectoryPath(); File tempDir = new File(tempDirPath); @@ -481,7 +481,7 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT /* * Test that askInt method auto-populates dialog with value in .properties file. - * + * * Also test that subsequent calls to the dialog show the last-used value. */ @Test @@ -622,13 +622,40 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT createScript(); - final String defaultValue = "a default value"; + String defaultValue = "a default value"; String myString = ask_TextInput(() -> { return script.askString("Default Test", "Enter a string here:", defaultValue); }); assertEquals(defaultValue, myString); } + @Test + public void testAskStringDefaultValue_DoNotReusePreviousValues() throws Exception { + createScript(); + + String defaultValue = "a default value"; + String myString = ask_TextInput(() -> { + return script.askString("Default Test", "Enter a string here:", defaultValue); + }); + assertEquals(defaultValue, myString); + + script.setReusePreviousChoices(false); + + String secondDefaultValue = "a new default value"; + String secondString = ask_TextInput(() -> { + return script.askString("Default Test", "Enter a string here:", secondDefaultValue); + }); + assertEquals(secondDefaultValue, secondString); + + script.setReusePreviousChoices(true); + + String thirdDefaultValue = "a third default value"; + String thirdString = ask_TextInput(() -> { + return script.askString("Default Test", "Enter a string here:", thirdDefaultValue); + }); + assertEquals(secondString, thirdString); + } + @Test public void testAskChoice() throws Exception { createScript(); @@ -673,37 +700,37 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT assertEquals(choices.get(choiceIndex), chosen); } - // TODO test for askChoices() + // TODO test for askChoices() - /* - * No test for either of the two versions of 'askChoices()" because it does not use either the - * the last-selected value or a .properties file value to pre-populate the user choice in the - * GUI. + /* + * No test for either of the two versions of 'askChoices()" because it does not use either the + * the last-selected value or a .properties file value to pre-populate the user choice in the + * GUI. */ - /* + /* * No test for 'askYesNo()" because it does not use either the the last-selected value or - * a .properties file value to pre-populate the user choice in the GUI. + * a .properties file value to pre-populate the user choice in the GUI. */ - /* - * No test for 'askProjectFolder()" because it does not use either the the last-selected value - * or a .properties file value to pre-populate the user choice in the GUI. + /* + * No test for 'askProjectFolder()" because it does not use either the the last-selected value + * or a .properties file value to pre-populate the user choice in the GUI. */ - /* + /* * No test for 'askProgram()" because it does not use either the the last-selected value or - * a .properties file value to pre-populate the user choice in the GUI. + * a .properties file value to pre-populate the user choice in the GUI. */ - /* + /* * No test for 'askDomainFile()" because it does not use either the the last-selected value or - * a .properties file value to pre-populate the user choice in the GUI. + * a .properties file value to pre-populate the user choice in the GUI. */ //================================================================================================== // Private Methods -//================================================================================================== +//================================================================================================== private T ask_ComboInput(Callable c) { return ask_TextInput(null, c);