bool SetUseColor(bool use_color);
+ bool GetShowProgress() const;
+
bool GetUseAutosuggestion() const;
llvm::StringRef GetAutosuggestionAnsiPrefix() const;
uint64_t completed, uint64_t total,
llvm::Optional<lldb::user_id_t> debugger_id);
+ void PrintProgress(const Debugger::ProgressEventData &data);
+
bool StartEventHandlerThread();
void StopEventHandlerThread();
void HandleThreadEvent(const lldb::EventSP &event_sp);
+ void HandleProgressEvent(const lldb::EventSP &event_sp);
+
// Ensures two threads don't attempt to flush process output in parallel.
std::mutex m_output_flush_mutex;
void FlushProcessOutput(Process &process, bool flush_stdout,
IOHandlerStack m_io_handler_stack;
std::recursive_mutex m_io_handler_synchronous_mutex;
+ llvm::Optional<uint64_t> m_current_event_id;
+
llvm::StringMap<std::weak_ptr<llvm::raw_ostream>> m_log_streams;
std::shared_ptr<llvm::raw_ostream> m_log_callback_stream_sp;
ConstString m_instance_name;
return ret;
}
+bool Debugger::GetShowProgress() const {
+ const uint32_t idx = ePropertyShowProgress;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(
+ nullptr, idx, g_debugger_properties[idx].default_uint_value != 0);
+}
+
bool Debugger::GetUseAutosuggestion() const {
const uint32_t idx = ePropertyShowAutosuggestion;
return m_collection_sp->GetPropertyAtIndexAsBoolean(
CommandInterpreter::eBroadcastBitAsynchronousOutputData |
CommandInterpreter::eBroadcastBitAsynchronousErrorData);
+ if (!m_broadcaster.EventTypeHasListeners(Debugger::eBroadcastBitProgress)) {
+ listener_sp->StartListeningForEvents(&m_broadcaster,
+ Debugger::eBroadcastBitProgress);
+ }
+
// Let the thread that spawned us know that we have started up and that we
// are now listening to all required events so no events get missed
m_sync_broadcaster.BroadcastEvent(eBroadcastBitEventThreadIsListening);
}
}
}
+ } else if (broadcaster == &m_broadcaster) {
+ if (event_type & Debugger::eBroadcastBitProgress)
+ HandleProgressEvent(event_sp);
}
}
return {};
}
+void Debugger::HandleProgressEvent(const lldb::EventSP &event_sp) {
+ auto *data =
+ Debugger::ProgressEventData::GetEventDataFromEvent(event_sp.get());
+ if (!data)
+ return;
+
+ // Do some bookkeeping for the current event, regardless of whether we're
+ // going to show the progress.
+ const uint64_t id = data->GetID();
+ if (m_current_event_id) {
+ if (id != *m_current_event_id)
+ return;
+ if (data->GetCompleted())
+ m_current_event_id.reset();
+ } else {
+ m_current_event_id = id;
+ }
+
+ // Decide whether we actually are going to show the progress. This decision
+ // can change between iterations so check it inside the loop.
+ if (!GetShowProgress())
+ return;
+
+ // Determine whether the current output file is an interactive terminal with
+ // color support. We assume that if we support ANSI escape codes we support
+ // vt100 escape codes.
+ File &output = GetOutputFile();
+ if (!output.GetIsInteractive() || !output.GetIsTerminalWithColors())
+ return;
+
+ if (data->GetCompleted()) {
+ // Clear the current line.
+ output.Printf("\33[2K\r");
+ return;
+ }
+
+ // Print over previous line, if any.
+ output.Printf("\r");
+
+ // Print the progress message.
+ std::string message = data->GetMessage();
+ if (data->GetTotal() != UINT64_MAX) {
+ output.Printf("[%llu/%llu] %s...", data->GetCompleted(), data->GetTotal(),
+ message.c_str());
+ } else {
+ output.Printf("%s...", message.c_str());
+ }
+
+ // Clear until the end of the line.
+ output.Printf("\x1B[K");
+
+ // Flush the output.
+ output.Flush();
+}
+
bool Debugger::HasIOHandlerThread() { return m_io_handler_thread.IsJoinable(); }
bool Debugger::StartIOHandlerThread() {
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/Progress.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Utility/ArchSpec.h"
FileSystem::Instance().Exists(symbol_file_spec))
return symbol_file_spec;
+ Progress progress(llvm::formatv(
+ "Locating external symbol file for {0}",
+ module_spec.GetFileSpec().GetFilename().AsCString("<Unknown>")));
+
FileSpecList debug_file_search_paths = default_search_paths;
// Add module directory.