https://github.com/walter-erquinigo updated 
https://github.com/llvm/llvm-project/pull/69238

>From 3d14b2938e0fd6073cdafcea4a54071f23158b42 Mon Sep 17 00:00:00 2001
From: walter erquinigo <wal...@modular.com>
Date: Mon, 16 Oct 2023 15:08:20 -0400
Subject: [PATCH] [lldb-vscode] Allow specifying a custom escape character for
 LLDB commands

We've been using the backtick as our escape character, however that leads to a 
weird experience on VS Code, because on most hosts, as soon as you type the 
backtick on VS Code, the IDE will introduce another backtick. As changing the 
default escape character might be out of question because other plugins might 
rely on it, we can instead introduce an option to change this variable upon 
lldb-vscode initialization.
FWIW, my users will be using : instead ot the backtick.
---
 .../tools/lldb-vscode/lldbvscode_testcase.py  | 12 +++++---
 .../test/tools/lldb-vscode/vscode.py          | 10 +++++--
 .../lldb-vscode/console/TestVSCode_console.py | 29 ++++++++++++++++---
 lldb/tools/lldb-vscode/Options.td             |  6 ++++
 lldb/tools/lldb-vscode/VSCode.cpp             |  8 +++--
 lldb/tools/lldb-vscode/VSCode.h               |  1 +
 lldb/tools/lldb-vscode/lldb-vscode.cpp        | 10 +++++++
 7 files changed, 63 insertions(+), 13 deletions(-)

diff --git 
a/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py 
b/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py
index 8cd4e8454c89099..594c37bb1999c58 100644
--- 
a/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py
+++ 
b/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py
@@ -8,7 +8,7 @@
 class VSCodeTestCaseBase(TestBase):
     NO_DEBUG_INFO_TESTCASE = True
 
-    def create_debug_adaptor(self, lldbVSCodeEnv=None):
+    def create_debug_adaptor(self, lldbVSCodeEnv=None, commandEscapeChar="`"):
         """Create the Visual Studio Code debug adaptor"""
         self.assertTrue(
             is_exe(self.lldbVSCodeExec), "lldb-vscode must exist and be 
executable"
@@ -16,14 +16,15 @@ def create_debug_adaptor(self, lldbVSCodeEnv=None):
         log_file_path = self.getBuildArtifact("vscode.txt")
         self.vscode = vscode.DebugAdaptor(
             executable=self.lldbVSCodeExec,
+            args=["--command-escape-character", commandEscapeChar],
             init_commands=self.setUpCommands(),
             log_file=log_file_path,
             env=lldbVSCodeEnv,
         )
 
-    def build_and_create_debug_adaptor(self, lldbVSCodeEnv=None):
+    def build_and_create_debug_adaptor(self, lldbVSCodeEnv=None, 
commandEscapeChar="`"):
         self.build()
-        self.create_debug_adaptor(lldbVSCodeEnv)
+        self.create_debug_adaptor(lldbVSCodeEnv, commandEscapeChar)
 
     def set_source_breakpoints(self, source_path, lines, data=None):
         """Sets source breakpoints and returns an array of strings containing
@@ -425,11 +426,14 @@ def build_and_launch(
         lldbVSCodeEnv=None,
         enableAutoVariableSummaries=False,
         enableSyntheticChildDebugging=False,
+        commandEscapeChar="`",
     ):
         """Build the default Makefile target, create the VSCode debug adaptor,
         and launch the process.
         """
-        self.build_and_create_debug_adaptor(lldbVSCodeEnv)
+        self.build_and_create_debug_adaptor(
+            lldbVSCodeEnv, commandEscapeChar=commandEscapeChar
+        )
         self.assertTrue(os.path.exists(program), "executable must exist")
 
         return self.launch(
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py 
b/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py
index 5ee0800b27a5699..01ba63a7cdec820 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py
@@ -1015,7 +1015,13 @@ def terminate(self):
 
 class DebugAdaptor(DebugCommunication):
     def __init__(
-        self, executable=None, port=None, init_commands=[], log_file=None, 
env=None
+        self,
+        executable=None,
+        args=[],
+        port=None,
+        init_commands=[],
+        log_file=None,
+        env=None,
     ):
         self.process = None
         if executable is not None:
@@ -1026,7 +1032,7 @@ def __init__(
             if log_file:
                 adaptor_env["LLDBVSCODE_LOG"] = log_file
             self.process = subprocess.Popen(
-                [executable],
+                [executable, *args],
                 stdin=subprocess.PIPE,
                 stdout=subprocess.PIPE,
                 stderr=subprocess.PIPE,
diff --git a/lldb/test/API/tools/lldb-vscode/console/TestVSCode_console.py 
b/lldb/test/API/tools/lldb-vscode/console/TestVSCode_console.py
index d28e98b37c589dd..c56839cd9fcadcc 100644
--- a/lldb/test/API/tools/lldb-vscode/console/TestVSCode_console.py
+++ b/lldb/test/API/tools/lldb-vscode/console/TestVSCode_console.py
@@ -2,16 +2,20 @@
 Test lldb-vscode setBreakpoints request
 """
 
+import lldbvscode_testcase
 import vscode
+from lldbsuite.test import lldbutil
 from lldbsuite.test.decorators import *
 from lldbsuite.test.lldbtest import *
-from lldbsuite.test import lldbutil
-import lldbvscode_testcase
 
 
 class TestVSCode_console(lldbvscode_testcase.VSCodeTestCaseBase):
-    def check_lldb_command(self, lldb_command, contains_string, assert_msg):
-        response = self.vscode.request_evaluate("`%s" % (lldb_command), 
context="repl")
+    def check_lldb_command(
+        self, lldb_command, contains_string, assert_msg, 
command_escape_char="`"
+    ):
+        response = self.vscode.request_evaluate(
+            f"{command_escape_char}{lldb_command}", context="repl"
+        )
         output = response["body"]["result"]
         self.assertIn(
             contains_string,
@@ -66,3 +70,20 @@ def test_scopes_variables_setVariable_evaluate(self):
         # currently selected frame.
 
         self.check_lldb_command("frame select", "frame #1", "frame 1 is 
selected")
+
+    @skipIfWindows
+    @skipIfRemote
+    def test_custom_escape_char(self):
+        program = self.getBuildArtifact("a.out")
+        self.build_and_launch(program, commandEscapeChar=":")
+        source = "main.cpp"
+        breakpoint1_line = line_number(source, "// breakpoint 1")
+        breakpoint_ids = self.set_source_breakpoints(source, 
[breakpoint1_line])
+        self.continue_to_breakpoints(breakpoint_ids)
+
+        self.check_lldb_command(
+            "help",
+            "For more information on any command",
+            "Help can be invoked",
+            command_escape_char=":",
+        )
diff --git a/lldb/tools/lldb-vscode/Options.td 
b/lldb/tools/lldb-vscode/Options.td
index a6ba0a318f388a1..7e885abeb615326 100644
--- a/lldb/tools/lldb-vscode/Options.td
+++ b/lldb/tools/lldb-vscode/Options.td
@@ -43,3 +43,9 @@ def debugger_pid: S<"debugger-pid">,
 def repl_mode: S<"repl-mode">,
   MetaVarName<"<mode>">,
   HelpText<"The mode for handling repl evaluation requests, supported modes: 
variable, command, auto.">;
+
+def command_escape_character: S<"command-escape-character">,
+  MetaVarName<"<character>">,
+  HelpText<"The escape prefix character to use for executing regular LLDB "
+           "commands in the Debug Console, instead of printing variables. "
+           "Defaults to a back-tick (`).">;
diff --git a/lldb/tools/lldb-vscode/VSCode.cpp 
b/lldb/tools/lldb-vscode/VSCode.cpp
index 1384604c48371b7..7ce5932f8691e80 100644
--- a/lldb/tools/lldb-vscode/VSCode.cpp
+++ b/lldb/tools/lldb-vscode/VSCode.cpp
@@ -384,8 +384,8 @@ llvm::json::Value VSCode::CreateTopLevelScopes() {
 
 ExpressionContext VSCode::DetectExpressionContext(lldb::SBFrame &frame,
                                                   std::string &text) {
-  // Include ` as an escape hatch.
-  if (!text.empty() && text[0] == '`') {
+  // Include the escape hatch prefix.
+  if (!text.empty() && text[0] == g_vsc.command_escape_character) {
     text = text.substr(1);
     return ExpressionContext::Command;
   }
@@ -418,7 +418,9 @@ ExpressionContext 
VSCode::DetectExpressionContext(lldb::SBFrame &frame,
         if (!auto_repl_mode_collision_warning) {
           llvm::errs() << "Variable expression '" << text
                        << "' is hiding an lldb command, prefix an expression "
-                          "with ` to ensure it runs as a lldb command.\n";
+                          "with "
+                       << g_vsc.command_escape_character
+                       << " to ensure it runs as a lldb command.\n";
           auto_repl_mode_collision_warning = true;
         }
         return ExpressionContext::Variable;
diff --git a/lldb/tools/lldb-vscode/VSCode.h b/lldb/tools/lldb-vscode/VSCode.h
index 59bb11c71e67203..1802eeb821fd30d 100644
--- a/lldb/tools/lldb-vscode/VSCode.h
+++ b/lldb/tools/lldb-vscode/VSCode.h
@@ -188,6 +188,7 @@ struct VSCode {
   ReplModeRequestHandler repl_mode_request_handler;
   ReplMode repl_mode;
   bool auto_repl_mode_collision_warning;
+  char command_escape_character = '`';
 
   VSCode();
   ~VSCode();
diff --git a/lldb/tools/lldb-vscode/lldb-vscode.cpp 
b/lldb/tools/lldb-vscode/lldb-vscode.cpp
index 3904d430c49b4cd..06c7724fb66d25a 100644
--- a/lldb/tools/lldb-vscode/lldb-vscode.cpp
+++ b/lldb/tools/lldb-vscode/lldb-vscode.cpp
@@ -3806,6 +3806,16 @@ int main(int argc, char *argv[]) {
     g_vsc.output.descriptor = StreamDescriptor::from_file(new_stdout_fd, 
false);
   }
 
+  if (llvm::opt::Arg *arg =
+          input_args.getLastArg(OPT_command_escape_character)) {
+    if (const char *escape_char = arg->getValue()) {
+      g_vsc.command_escape_character = *escape_char;
+    } else {
+      llvm::errs() << "Missing command escape character.\n";
+      return EXIT_FAILURE;
+    }
+  }
+
   bool CleanExit = true;
   if (auto Err = g_vsc.Loop()) {
     if (g_vsc.log)

_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to