From 36eab4634f4cd4594e6d1409a66bc8f2d8fda04f Mon Sep 17 00:00:00 2001 From: Med Ismail Bennani Date: Fri, 5 Mar 2021 18:30:48 +0000 Subject: [PATCH] [lldb/Interpreter] Add `interpreter.repeat-previous-command` setting This patch introduces a new interpreter setting to prevent LLDB from re-executing the previous command when passing an empty command. This can be very useful when performing actions that requires a long time to complete. To preserve the original behaviour, the setting defaults to `true`. rdar://74983516 Differential Revision: https://reviews.llvm.org/D97999 Signed-off-by: Med Ismail Bennani --- lldb/include/lldb/Interpreter/CommandInterpreter.h | 2 ++ lldb/source/Interpreter/CommandInterpreter.cpp | 11 +++++++ lldb/source/Interpreter/InterpreterProperties.td | 4 +++ lldb/test/API/commands/settings/TestSettings.py | 36 ++++++++++++++++++++++ 4 files changed, 53 insertions(+) diff --git a/lldb/include/lldb/Interpreter/CommandInterpreter.h b/lldb/include/lldb/Interpreter/CommandInterpreter.h index 7f897bf..5b5f145 100644 --- a/lldb/include/lldb/Interpreter/CommandInterpreter.h +++ b/lldb/include/lldb/Interpreter/CommandInterpreter.h @@ -504,6 +504,8 @@ public: 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 index b0ff634..eeef14b 100644 --- a/lldb/source/Interpreter/CommandInterpreter.cpp +++ b/lldb/source/Interpreter/CommandInterpreter.cpp @@ -223,6 +223,12 @@ bool CommandInterpreter::GetSpaceReplPrompts() const { 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 @@ bool CommandInterpreter::HandleCommand(const char *command_line, } 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 index e5346d1..1148c1b 100644 --- a/lldb/source/Interpreter/InterpreterProperties.td +++ b/lldb/source/Interpreter/InterpreterProperties.td @@ -29,4 +29,8 @@ let Definition = "interpreter" in { 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 index c3cfdab..7eab23a 100644 --- a/lldb/test/API/commands/settings/TestSettings.py +++ b/lldb/test/API/commands/settings/TestSettings.py @@ -25,6 +25,42 @@ class SettingsCommandTestCase(TestBase): "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. -- 2.7.4