[lldb] Support OSC escape codes for native progress#162162
[lldb] Support OSC escape codes for native progress#162162JDevlieghere merged 3 commits intollvm:mainfrom
Conversation
This PR adds support for emitting the ConEmu OSC 9;4 sequences to show a GUI native progress bar. There's a limited number of terminal emulators that support this, so for now this requires explicit opt-in through a setting. I'm reusing the existing `show-progress` setting, which became a NOOP with the introduction of the statusline. The option now defaults to off. Implements llvm#160369
|
@llvm/pr-subscribers-lldb Author: Jonas Devlieghere (JDevlieghere) ChangesThis PR adds support for emitting the OSC There's a limited number of terminal emulators that support this, so for now this requires explicit opt-in through a setting. I'm reusing the existing Implements #160369 Full diff: https://github.com/llvm/llvm-project/pull/162162.diff 4 Files Affected:
diff --git a/lldb/include/lldb/Core/Debugger.h b/lldb/include/lldb/Core/Debugger.h
index 06136ed40471d..78f1fa6757f9d 100644
--- a/lldb/include/lldb/Core/Debugger.h
+++ b/lldb/include/lldb/Core/Debugger.h
@@ -682,6 +682,7 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
lldb::LockableStreamFileSP GetErrorStreamSP() { return m_error_stream_sp; }
/// @}
+ bool IsInteractiveColorTTY();
bool StatuslineSupported();
void PushIOHandler(const lldb::IOHandlerSP &reader_sp,
diff --git a/lldb/include/lldb/Utility/AnsiTerminal.h b/lldb/include/lldb/Utility/AnsiTerminal.h
index 7db184ad67225..350c1fb145300 100644
--- a/lldb/include/lldb/Utility/AnsiTerminal.h
+++ b/lldb/include/lldb/Utility/AnsiTerminal.h
@@ -72,6 +72,15 @@
#define ANSI_ESC_START_LEN 2
+// OSC (Operating System Commands)
+#define OSC_ESCAPE_START "\033"
+#define OSC_ESCAPE_END "\x07"
+
+#define OSC_PROGRESS_REMOVE OSC_ESCAPE_START "]9;4;0;0" OSC_ESCAPE_END
+#define OSC_PROGRESS_SHOW OSC_ESCAPE_START "]9;4;1;%u" OSC_ESCAPE_END
+#define OSC_PROGRESS_ERROR OSC_ESCAPE_START "]9;4;2;%u" OSC_ESCAPE_END
+#define OSC_PROGRESS_INDETERMINATE OSC_ESCAPE_START "]9;4;3;%u" OSC_ESCAPE_END
+
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
diff --git a/lldb/source/Core/CoreProperties.td b/lldb/source/Core/CoreProperties.td
index fda34a8ad2630..1be911c291703 100644
--- a/lldb/source/Core/CoreProperties.td
+++ b/lldb/source/Core/CoreProperties.td
@@ -162,10 +162,12 @@ let Definition = "debugger" in {
Global,
DefaultTrue,
Desc<"Whether to use Ansi color codes or not.">;
- def ShowProgress: Property<"show-progress", "Boolean">,
- Global,
- DefaultTrue,
- Desc<"Whether to show progress or not if the debugger's output is an interactive color-enabled terminal.">;
+ def ShowProgress
+ : Property<"show-progress", "Boolean">,
+ Global,
+ DefaultFalse,
+ Desc<"Whether to show progress using Operating System Command (OSC) "
+ "Sequences in supporting terminal emulators.">;
def ShowProgressAnsiPrefix: Property<"show-progress-ansi-prefix", "String">,
Global,
DefaultStringValue<"${ansi.faint}">,
diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp
index 568cd9d3d03b6..13fd3a705128e 100644
--- a/lldb/source/Core/Debugger.cpp
+++ b/lldb/source/Core/Debugger.cpp
@@ -2066,19 +2066,23 @@ void Debugger::CancelForwardEvents(const ListenerSP &listener_sp) {
m_forward_listener_sp.reset();
}
+bool Debugger::IsInteractiveColorTTY() {
+ if (lldb::LockableStreamFileSP stream_sp = GetOutputStreamSP()) {
+ File &file = stream_sp->GetUnlockedFile();
+ return file.GetIsInteractive() && file.GetIsRealTerminal() &&
+ file.GetIsTerminalWithColors();
+ }
+ return false;
+}
+
bool Debugger::StatuslineSupported() {
// We have trouble with the contol codes on Windows, see
// https://github.com/llvm/llvm-project/issues/134846.
#ifndef _WIN32
- if (GetShowStatusline()) {
- if (lldb::LockableStreamFileSP stream_sp = GetOutputStreamSP()) {
- File &file = stream_sp->GetUnlockedFile();
- return file.GetIsInteractive() && file.GetIsRealTerminal() &&
- file.GetIsTerminalWithColors();
- }
- }
-#endif
+ return GetShowStatusline() && IsInteractiveColorTTY();
+#else
return false;
+#endif
}
static bool RequiresFollowChildWorkaround(const Process &process) {
@@ -2271,10 +2275,11 @@ void Debugger::HandleProgressEvent(const lldb::EventSP &event_sp) {
ProgressReport progress_report{data->GetID(), data->GetCompleted(),
data->GetTotal(), data->GetMessage()};
- // Do some bookkeeping regardless of whether we're going to display
- // progress reports.
{
std::lock_guard<std::mutex> guard(m_progress_reports_mutex);
+
+ // Do some bookkeeping regardless of whether we're going to display
+ // progress reports.
auto it = llvm::find_if(m_progress_reports, [&](const auto &report) {
return report.id == progress_report.id;
});
@@ -2287,6 +2292,30 @@ void Debugger::HandleProgressEvent(const lldb::EventSP &event_sp) {
} else {
m_progress_reports.push_back(progress_report);
}
+
+ // Show progress using Operating System Command (OSC) sequences.
+ if (GetShowProgress() && IsInteractiveColorTTY()) {
+ if (lldb::LockableStreamFileSP stream_sp = GetOutputStreamSP()) {
+
+ // Clear progress if this was the last progress event.
+ if (m_progress_reports.empty()) {
+ stream_sp->Lock() << OSC_PROGRESS_REMOVE;
+ return;
+ }
+
+ const ProgressReport &report = m_progress_reports.back();
+
+ // Show indeterminate progress.
+ if (report.total == UINT64_MAX) {
+ stream_sp->Lock() << OSC_PROGRESS_INDETERMINATE;
+ return;
+ }
+
+ // Compute and show the progress value (0-100).
+ const unsigned value = (report.completed / report.total) * 100;
+ stream_sp->Lock().Printf(OSC_PROGRESS_SHOW, value);
+ }
+ }
}
}
|
DavidSpickett
left a comment
There was a problem hiding this comment.
Needs a release note.
| DefaultFalse, | ||
| Desc<"Whether to show progress using Operating System Command (OSC) " | ||
| "Sequences in supporting terminal emulators.">; | ||
| def ShowProgressAnsiPrefix: Property<"show-progress-ansi-prefix", "String">, |
There was a problem hiding this comment.
We should/should have release noted that this and the next setting now do nothing.
There was a problem hiding this comment.
You're right. I've retroactively included in the new release note.
This PR adds support for emitting the OSC `9;4` sequences to show a GUI native progress bar. There's a limited number of terminal emulators that support this, so for now this requires explicit opt-in through a setting. I'm reusing the existing `show-progress` setting, which became a NOOP with the introduction of the statusline. The option now defaults to off. Implements llvm#160369
In llvm#162162, I added support for OSC 9;4 graphical progress. I put it behind the `show-progress` setting because I didn't have a reliable way to detect whether the escape code was supported by the terminal. Since then, more tools have added support for it, most notably Claude Code and Homebrew. While I still don't have a good way to detect this, there are a handful of known terminals that are easy enough to identify. This PR toggles the default of `show-progress` to on again and puts showing the progress behind a check for those known terminals (Windows Terminal, ConEmu & Ghostty). This means that if you're running in one of those, you'll get the visual progress by default unless you set `show-progress` to off. The downside is that if you're on an unrecognized terminal, you can't force it on any longer by setting `show-progress` to on. I think that's a fair trade-off as the setting wasn't really advertised and I doubt many people are using that. As a workaround, they can set `OSC_PROGRESS` to spoof an OSC-supporting terminal.
…5541) In #162162, I added support for OSC 9;4 graphical progress. I put it behind the `show-progress` setting because I didn't have a reliable way to detect whether the escape code was supported by the terminal. Since then, more tools have added support for it, most notably Claude Code and Homebrew. While I still don't have a good way to detect this, there are a handful of known terminals that are easy enough to identify. This PR toggles the default of `show-progress` to on again and puts showing the progress behind a check for those known terminals (Windows Terminal, ConEmu & Ghostty). This means that if you're running in one of those, you'll get the visual progress by default unless you set `show-progress` to off. The downside is that if you're on an unrecognized terminal, you can't force it on any longer by setting `show-progress` to on. I think that's a fair trade-off as the setting wasn't really advertised and I doubt many people are using that. As a workaround, they can set `OSC_PROGRESS` to spoof an OSC-supporting terminal.
This PR adds support for emitting the OSC
9;4sequences to show a GUI native progress bar.There's a limited number of terminal emulators that support this, so for now this requires explicit opt-in through a setting. I'm reusing the existing
show-progresssetting, which became a NOOP with the introduction of the statusline. The option now defaults to off.Implements #160369