[lldb] Add debugger.external-editor setting
authorJonas Devlieghere <jonas@devlieghere.com>
Mon, 1 May 2023 21:08:43 +0000 (14:08 -0700)
committerJonas Devlieghere <jonas@devlieghere.com>
Mon, 1 May 2023 21:11:11 +0000 (14:11 -0700)
Add a new setting (debugger.external-editor) to specify an external
editor. The setting takes precedence over the existing
LLDB_EXTERNAL_EDITOR environment variable.

Differential revision: https://reviews.llvm.org/D149565

lldb/include/lldb/Core/Debugger.h
lldb/include/lldb/Host/Host.h
lldb/source/Core/CoreProperties.td
lldb/source/Core/Debugger.cpp
lldb/source/Host/common/Host.cpp
lldb/source/Host/macosx/objcxx/Host.mm
lldb/source/Interpreter/CommandInterpreter.cpp
lldb/source/Target/Thread.cpp
lldb/test/Shell/Settings/TestExternalEditor.test [new file with mode: 0644]

index 1d9d691bc2b06113e2755ef9b7fbb62c5f370d45..12c1c046fbcefdfb4ee3a0fd3c280c7d8bc0b8d1 100644 (file)
@@ -293,9 +293,12 @@ public:
   void SetPrompt(const char *) = delete;
 
   bool GetUseExternalEditor() const;
-
   bool SetUseExternalEditor(bool use_external_editor_p);
 
+  llvm::StringRef GetExternalEditor() const;
+
+  bool SetExternalEditor(llvm::StringRef editor);
+
   bool GetUseColor() const;
 
   bool SetUseColor(bool use_color);
index 3fdf59dfb232448b7213223f3d712f5a5394123a..30549cd789149790dfdd82e959da909e353d27a0 100644 (file)
@@ -236,7 +236,8 @@ public:
                                 bool run_in_shell = true,
                                 bool hide_stderr = false);
 
-  static llvm::Error OpenFileInExternalEditor(const FileSpec &file_spec,
+  static llvm::Error OpenFileInExternalEditor(llvm::StringRef editor,
+                                              const FileSpec &file_spec,
                                               uint32_t line_no);
 
   /// Check if we're running in an interactive graphical session.
index 62729923f366b7a5778cca0ebae076232fde7782..ccee2a64fcbae82a575ca11ede7f8f3e9b1fa1b2 100644 (file)
@@ -135,6 +135,10 @@ let Definition = "debugger" in {
     Global,
     DefaultFalse,
     Desc<"Whether to use an external editor or not.">;
+  def ExternalEditor: Property<"external-editor", "String">,
+    Global,
+    DefaultStringValue<"">,
+    Desc<"External editor to use when use-external-editor is enabled.">;
   def UseColor: Property<"use-color", "Boolean">,
     Global,
     DefaultTrue,
index 581b29e6bc1efdc0dda22cfdbaf15b51381ffdad..ee51dd75a9ff73712bfd2e47f0138b0906162f1f 100644 (file)
@@ -372,6 +372,16 @@ bool Debugger::SetUseExternalEditor(bool b) {
   return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
 }
 
+llvm::StringRef Debugger::GetExternalEditor() const {
+  const uint32_t idx = ePropertyExternalEditor;
+  return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
+}
+
+bool Debugger::SetExternalEditor(llvm::StringRef editor) {
+  const uint32_t idx = ePropertyExternalEditor;
+  return m_collection_sp->SetPropertyAtIndexAsString(nullptr, idx, editor);
+}
+
 bool Debugger::GetUseColor() const {
   const uint32_t idx = ePropertyUseColor;
   return m_collection_sp->GetPropertyAtIndexAsBoolean(
index c8ebb6f84c0048f57f81f8a422fa2fc1b71632d6..49eac0b0fa7b0c6b9dbf08844e33bfb2838909ce 100644 (file)
@@ -546,7 +546,8 @@ void Host::Kill(lldb::pid_t pid, int signo) { ::kill(pid, signo); }
 #endif
 
 #if !defined(__APPLE__)
-llvm::Error Host::OpenFileInExternalEditor(const FileSpec &file_spec,
+llvm::Error Host::OpenFileInExternalEditor(llvm::StringRef editor,
+                                           const FileSpec &file_spec,
                                            uint32_t line_no) {
   return llvm::errorCodeToError(
       std::error_code(ENOTSUP, std::system_category()));
index 848fa0d79f4da5b2753dfc1f91439075d97f4d69..5a151b9ecc8ffff6ed3b8dbcbb36a59d88353528 100644 (file)
@@ -325,7 +325,8 @@ LaunchInNewTerminalWithAppleScript(const char *exe_path,
 
 #endif // TARGET_OS_OSX
 
-llvm::Error Host::OpenFileInExternalEditor(const FileSpec &file_spec,
+llvm::Error Host::OpenFileInExternalEditor(llvm::StringRef editor,
+                                           const FileSpec &file_spec,
                                            uint32_t line_no) {
 #if !TARGET_OS_OSX
   return llvm::errorCodeToError(
@@ -391,41 +392,36 @@ llvm::Error Host::OpenFileInExternalEditor(const FileSpec &file_spec,
   auto on_exit = llvm::make_scope_exit(
       [&]() { AEDisposeDesc(&(file_and_line_desc.descContent)); });
 
-  static std::optional<FSRef> g_app_fsref;
-  static std::string g_app_error;
-  static std::once_flag g_once_flag;
-  std::call_once(g_once_flag, [&]() {
-    if (const char *external_editor = ::getenv("LLDB_EXTERNAL_EDITOR")) {
-      LLDB_LOG(log, "Looking for external editor: {0}", external_editor);
-
-      FSRef app_fsref;
-      CFCString editor_name(external_editor, kCFStringEncodingUTF8);
-      long app_error = ::LSFindApplicationForInfo(
-          /*inCreator=*/kLSUnknownCreator, /*inBundleID=*/NULL,
-          /*inName=*/editor_name.get(), /*outAppRef=*/&app_fsref,
-          /*outAppURL=*/NULL);
-      if (app_error == noErr) {
-        g_app_fsref = app_fsref;
-      } else {
-        g_app_error =
-            llvm::formatv("could not find external editor \"{0}\": "
-                          "LSFindApplicationForInfo returned error {1}",
-                          external_editor, app_error)
-                .str();
-      }
-    }
-  });
+  if (editor.empty()) {
+    if (const char *lldb_external_editor = ::getenv("LLDB_EXTERNAL_EDITOR"))
+      editor = lldb_external_editor;
+  }
 
-  if (!g_app_error.empty())
-    return llvm::createStringError(llvm::inconvertibleErrorCode(), g_app_error);
+  std::optional<FSRef> app_fsref;
+  if (!editor.empty()) {
+    LLDB_LOG(log, "Looking for external editor: {0}", editor);
+
+    app_fsref.emplace();
+    CFCString editor_name(editor.data(), kCFStringEncodingUTF8);
+    long app_error = ::LSFindApplicationForInfo(
+        /*inCreator=*/kLSUnknownCreator, /*inBundleID=*/NULL,
+        /*inName=*/editor_name.get(), /*outAppRef=*/&(*app_fsref),
+        /*outAppURL=*/NULL);
+    if (app_error != noErr)
+      return llvm::createStringError(
+          llvm::inconvertibleErrorCode(),
+          llvm::formatv("could not find external editor \"{0}\": "
+                        "LSFindApplicationForInfo returned error {1}",
+                        editor, app_error));
+  }
 
   // Build app launch parameters.
   LSApplicationParameters app_params;
   ::memset(&app_params, 0, sizeof(app_params));
   app_params.flags =
       kLSLaunchDefaults | kLSLaunchDontAddToRecents | kLSLaunchDontSwitch;
-  if (g_app_fsref)
-    app_params.application = &(g_app_fsref.value());
+  if (app_fsref)
+    app_params.application = &(*app_fsref);
 
   ProcessSerialNumber psn;
   std::array<CFURLRef, 1> file_array = {file_URL.get()};
index f89cff49f0aeb2217e58bf682523e2222e4c9cbd..ba6188430344cfbab47e8d3c2ac6fc596ca92528 100644 (file)
@@ -3272,7 +3272,8 @@ bool CommandInterpreter::SaveTranscript(
     const FileSpec file_spec;
     error = file->GetFileSpec(const_cast<FileSpec &>(file_spec));
     if (error.Success()) {
-      if (llvm::Error e = Host::OpenFileInExternalEditor(file_spec, 1))
+      if (llvm::Error e = Host::OpenFileInExternalEditor(
+              m_debugger.GetExternalEditor(), file_spec, 1))
         result.AppendError(llvm::toString(std::move(e)));
     }
   }
index fa4c2c6a3557c35610dd4c77793dd38bf5639cc4..c71e65398f103c5084fb3278ae455e2347e5e95f 100644 (file)
@@ -303,10 +303,12 @@ bool Thread::SetSelectedFrameByIndexNoisily(uint32_t frame_idx,
       bool already_shown = false;
       SymbolContext frame_sc(
           frame_sp->GetSymbolContext(eSymbolContextLineEntry));
-      if (GetProcess()->GetTarget().GetDebugger().GetUseExternalEditor() &&
-          frame_sc.line_entry.file && frame_sc.line_entry.line != 0) {
+      const Debugger &debugger = GetProcess()->GetTarget().GetDebugger();
+      if (debugger.GetUseExternalEditor() && frame_sc.line_entry.file &&
+          frame_sc.line_entry.line != 0) {
         if (llvm::Error e = Host::OpenFileInExternalEditor(
-                frame_sc.line_entry.file, frame_sc.line_entry.line)) {
+                debugger.GetExternalEditor(), frame_sc.line_entry.file,
+                frame_sc.line_entry.line)) {
           LLDB_LOG_ERROR(GetLog(LLDBLog::Host), std::move(e),
                          "OpenFileInExternalEditor failed: {0}");
         } else {
@@ -1731,6 +1733,7 @@ size_t Thread::GetStatus(Stream &strm, uint32_t start_frame,
             frame_sp->GetSymbolContext(eSymbolContextLineEntry));
         if (frame_sc.line_entry.line != 0 && frame_sc.line_entry.file) {
           if (llvm::Error e = Host::OpenFileInExternalEditor(
+                  target->GetDebugger().GetExternalEditor(),
                   frame_sc.line_entry.file, frame_sc.line_entry.line)) {
             LLDB_LOG_ERROR(GetLog(LLDBLog::Host), std::move(e),
                            "OpenFileInExternalEditor failed: {0}");
diff --git a/lldb/test/Shell/Settings/TestExternalEditor.test b/lldb/test/Shell/Settings/TestExternalEditor.test
new file mode 100644 (file)
index 0000000..de0195a
--- /dev/null
@@ -0,0 +1,4 @@
+REQUIRES: system-darwin
+RUN: %lldb -o 'settings set use-external-editor true' -o 'setting set external-editor foo' -o 'session save' -b 2>&1 | FileCheck %s
+RUN: LLDB_EXTERNAL_EDITOR="foo" %lldb -o 'settings set use-external-editor true' -o 'session save' -b 2>&1 | FileCheck %s
+CHECK: error: could not find external editor "foo": LSFindApplicationForInfo returned error