Skip to content

Commit 692713d

Browse files
committed
[lldb] Support OSC escape codes for native progress
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 #160369
1 parent 3e7e60a commit 692713d

File tree

4 files changed

+55
-14
lines changed

4 files changed

+55
-14
lines changed

lldb/include/lldb/Core/Debugger.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,7 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
682682
lldb::LockableStreamFileSP GetErrorStreamSP() { return m_error_stream_sp; }
683683
/// @}
684684

685+
bool IsInteractiveColorTTY();
685686
bool StatuslineSupported();
686687

687688
void PushIOHandler(const lldb::IOHandlerSP &reader_sp,

lldb/include/lldb/Utility/AnsiTerminal.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,15 @@
7272

7373
#define ANSI_ESC_START_LEN 2
7474

75+
// OSC (Operating System Commands)
76+
#define OSC_ESCAPE_START "\033"
77+
#define OSC_ESCAPE_END "\x07"
78+
79+
#define OSC_PROGRESS_REMOVE OSC_ESCAPE_START "]9;4;0;0" OSC_ESCAPE_END
80+
#define OSC_PROGRESS_SHOW OSC_ESCAPE_START "]9;4;1;%u" OSC_ESCAPE_END
81+
#define OSC_PROGRESS_ERROR OSC_ESCAPE_START "]9;4;2;%u" OSC_ESCAPE_END
82+
#define OSC_PROGRESS_INDETERMINATE OSC_ESCAPE_START "]9;4;3;%u" OSC_ESCAPE_END
83+
7584
#include "llvm/ADT/ArrayRef.h"
7685
#include "llvm/ADT/STLExtras.h"
7786
#include "llvm/ADT/StringRef.h"

lldb/source/Core/CoreProperties.td

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,10 +162,12 @@ let Definition = "debugger" in {
162162
Global,
163163
DefaultTrue,
164164
Desc<"Whether to use Ansi color codes or not.">;
165-
def ShowProgress: Property<"show-progress", "Boolean">,
166-
Global,
167-
DefaultTrue,
168-
Desc<"Whether to show progress or not if the debugger's output is an interactive color-enabled terminal.">;
165+
def ShowProgress
166+
: Property<"show-progress", "Boolean">,
167+
Global,
168+
DefaultFalse,
169+
Desc<"Whether to show progress using Operating System Command (OSC) "
170+
"Sequences in supporting terminal emulators.">;
169171
def ShowProgressAnsiPrefix: Property<"show-progress-ansi-prefix", "String">,
170172
Global,
171173
DefaultStringValue<"${ansi.faint}">,

lldb/source/Core/Debugger.cpp

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2066,19 +2066,23 @@ void Debugger::CancelForwardEvents(const ListenerSP &listener_sp) {
20662066
m_forward_listener_sp.reset();
20672067
}
20682068

2069+
bool Debugger::IsInteractiveColorTTY() {
2070+
if (lldb::LockableStreamFileSP stream_sp = GetOutputStreamSP()) {
2071+
File &file = stream_sp->GetUnlockedFile();
2072+
return file.GetIsInteractive() && file.GetIsRealTerminal() &&
2073+
file.GetIsTerminalWithColors();
2074+
}
2075+
return false;
2076+
}
2077+
20692078
bool Debugger::StatuslineSupported() {
20702079
// We have trouble with the contol codes on Windows, see
20712080
// https://github.com/llvm/llvm-project/issues/134846.
20722081
#ifndef _WIN32
2073-
if (GetShowStatusline()) {
2074-
if (lldb::LockableStreamFileSP stream_sp = GetOutputStreamSP()) {
2075-
File &file = stream_sp->GetUnlockedFile();
2076-
return file.GetIsInteractive() && file.GetIsRealTerminal() &&
2077-
file.GetIsTerminalWithColors();
2078-
}
2079-
}
2080-
#endif
2082+
return GetShowStatusline() && IsInteractiveColorTTY();
2083+
#else
20812084
return false;
2085+
#endif
20822086
}
20832087

20842088
static bool RequiresFollowChildWorkaround(const Process &process) {
@@ -2271,10 +2275,11 @@ void Debugger::HandleProgressEvent(const lldb::EventSP &event_sp) {
22712275
ProgressReport progress_report{data->GetID(), data->GetCompleted(),
22722276
data->GetTotal(), data->GetMessage()};
22732277

2274-
// Do some bookkeeping regardless of whether we're going to display
2275-
// progress reports.
22762278
{
22772279
std::lock_guard<std::mutex> guard(m_progress_reports_mutex);
2280+
2281+
// Do some bookkeeping regardless of whether we're going to display
2282+
// progress reports.
22782283
auto it = llvm::find_if(m_progress_reports, [&](const auto &report) {
22792284
return report.id == progress_report.id;
22802285
});
@@ -2287,6 +2292,30 @@ void Debugger::HandleProgressEvent(const lldb::EventSP &event_sp) {
22872292
} else {
22882293
m_progress_reports.push_back(progress_report);
22892294
}
2295+
2296+
// Show progress using Operating System Command (OSC) sequences.
2297+
if (GetShowProgress() && IsInteractiveColorTTY()) {
2298+
if (lldb::LockableStreamFileSP stream_sp = GetOutputStreamSP()) {
2299+
2300+
// Clear progress if this was the last progress event.
2301+
if (m_progress_reports.empty()) {
2302+
stream_sp->Lock() << OSC_PROGRESS_REMOVE;
2303+
return;
2304+
}
2305+
2306+
const ProgressReport &report = m_progress_reports.back();
2307+
2308+
// Show indeterminate progress.
2309+
if (report.total == UINT64_MAX) {
2310+
stream_sp->Lock() << OSC_PROGRESS_INDETERMINATE;
2311+
return;
2312+
}
2313+
2314+
// Compute and show the progress value (0-100).
2315+
const unsigned value = (report.completed / report.total) * 100;
2316+
stream_sp->Lock().Printf(OSC_PROGRESS_SHOW, value);
2317+
}
2318+
}
22902319
}
22912320
}
22922321

0 commit comments

Comments
 (0)