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, 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 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); + } + } } }