diff --git a/lldb/include/lldb/Interpreter/CommandInterpreter.h b/lldb/include/lldb/Interpreter/CommandInterpreter.h --- a/lldb/include/lldb/Interpreter/CommandInterpreter.h +++ b/lldb/include/lldb/Interpreter/CommandInterpreter.h @@ -504,6 +504,8 @@ bool GetEchoCommentCommands() const; void SetEchoCommentCommands(bool enable); + bool GetRepeatPreviousCommand() const; + const CommandObject::CommandMap &GetUserCommands() const { return m_user_dict; } diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp --- a/lldb/source/Interpreter/CommandInterpreter.cpp +++ b/lldb/source/Interpreter/CommandInterpreter.cpp @@ -223,6 +223,12 @@ nullptr, idx, g_interpreter_properties[idx].default_uint_value != 0); } +bool CommandInterpreter::GetRepeatPreviousCommand() const { + const uint32_t idx = ePropertyRepeatPreviousCommand; + return m_collection_sp->GetPropertyAtIndexAsBoolean( + nullptr, idx, g_interpreter_properties[idx].default_uint_value != 0); +} + void CommandInterpreter::Initialize() { LLDB_SCOPED_TIMER(); @@ -1695,6 +1701,11 @@ } if (empty_command) { + if (!GetRepeatPreviousCommand()) { + result.SetStatus(eReturnStatusSuccessFinishNoResult); + return true; + } + if (m_command_history.IsEmpty()) { result.AppendError("empty command"); result.SetStatus(eReturnStatusFailed); diff --git a/lldb/source/Interpreter/InterpreterProperties.td b/lldb/source/Interpreter/InterpreterProperties.td --- a/lldb/source/Interpreter/InterpreterProperties.td +++ b/lldb/source/Interpreter/InterpreterProperties.td @@ -29,4 +29,8 @@ Global, DefaultTrue, Desc<"If true, commands will be echoed even if they are pure comment lines.">; + def RepeatPreviousCommand: Property<"repeat-previous-command", "Boolean">, + Global, + DefaultTrue, + Desc<"If true, LLDB will repeat the previous command if no command was passed to the interpreter. If false, LLDB won't repeat the previous command but only return a new prompt.">; } diff --git a/lldb/test/API/commands/settings/TestSettings.py b/lldb/test/API/commands/settings/TestSettings.py --- a/lldb/test/API/commands/settings/TestSettings.py +++ b/lldb/test/API/commands/settings/TestSettings.py @@ -25,6 +25,42 @@ "environment variables", "executable's environment"]) + def test_set_interpreter_repeat_prev_command(self): + """Test the `interpreter.repeat-previous-command` setting.""" + self.build() + + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + setting = "interpreter.repeat-previous-command" + + def cleanup(setting): + self.runCmd( + "settings clear %s" % + setting, check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup(setting)) + + # First, check for the setting default value. + self.expect("setting show %s" % setting, + substrs=["interpreter.repeat-previous-command (boolean) = true"]) + + # Then, invert the setting, and check that was set correctly + self.runCmd("setting set %s false" % setting) + self.expect("setting show %s" % setting, + substrs=["interpreter.repeat-previous-command (boolean) = false"]) + + + ci = self.dbg.GetCommandInterpreter() + self.assertTrue(ci.IsValid(), "Invalid command interpreter.") + # Now, test the functionnality + res = lldb.SBCommandReturnObject() + ci.HandleCommand('breakpoint set -n main', res) + self.assertTrue(res.Succeeded(), "Command failed.") + ci.HandleCommand('', res) + self.assertTrue(res.Succeeded(), "Empty command failed.") + self.assertEqual(self.dbg.GetSelectedTarget().GetNumBreakpoints(), 1) + def test_append_target_env_vars(self): """Test that 'append target.run-args' works.""" # Append the env-vars.