Skip to content

[lldb] Implement a statusline in LLDB #121860

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Mar 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion lldb/include/lldb/Core/Debugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/IOHandler.h"
#include "lldb/Core/SourceManager.h"
#include "lldb/Core/Statusline.h"
#include "lldb/Core/UserSettingsController.h"
#include "lldb/Host/HostThread.h"
#include "lldb/Host/StreamFile.h"
Expand Down Expand Up @@ -303,6 +304,10 @@ class Debugger : public std::enable_shared_from_this<Debugger>,

bool SetShowProgress(bool show_progress);

bool GetShowStatusline() const;

const FormatEntity::Entry *GetStatuslineFormat() const;

llvm::StringRef GetShowProgressAnsiPrefix() const;

llvm::StringRef GetShowProgressAnsiSuffix() const;
Expand Down Expand Up @@ -412,6 +417,9 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
/// Decrement the "interrupt requested" counter.
void CancelInterruptRequest();

/// Redraw the statusline if enabled.
void RedrawStatusline(bool update = true);

/// This is the correct way to query the state of Interruption.
/// If you are on the RunCommandInterpreter thread, it will check the
/// command interpreter state, and if it is on another thread it will
Expand Down Expand Up @@ -599,11 +607,20 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
return m_source_file_cache;
}

struct ProgressReport {
uint64_t id;
uint64_t completed;
uint64_t total;
std::string message;
};
std::optional<ProgressReport> GetCurrentProgressReport() const;

protected:
friend class CommandInterpreter;
friend class REPL;
friend class Progress;
friend class ProgressManager;
friend class Statusline;

/// Report progress events.
///
Expand Down Expand Up @@ -656,6 +673,8 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
lldb::LockableStreamFileSP GetErrorStreamSP() { return m_error_stream_sp; }
/// @}

bool StatuslineSupported();

void PushIOHandler(const lldb::IOHandlerSP &reader_sp,
bool cancel_top_handler = true);

Expand Down Expand Up @@ -732,7 +751,7 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
IOHandlerStack m_io_handler_stack;
std::recursive_mutex m_io_handler_synchronous_mutex;

std::optional<uint64_t> m_current_event_id;
std::optional<Statusline> m_statusline;

llvm::StringMap<std::weak_ptr<LogHandler>> m_stream_handlers;
std::shared_ptr<CallbackLogHandler> m_callback_handler_sp;
Expand All @@ -749,6 +768,12 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
lldb::TargetSP m_dummy_target_sp;
Diagnostics::CallbackID m_diagnostics_callback_id;

/// Bookkeeping for command line progress events.
/// @{
llvm::SmallVector<ProgressReport, 4> m_progress_reports;
mutable std::mutex m_progress_reports_mutex;
/// @}

std::mutex m_destroy_callback_mutex;
lldb::callback_token_t m_destroy_callback_next_token = 0;
struct DestroyCallbackInfo {
Expand Down
4 changes: 3 additions & 1 deletion lldb/include/lldb/Core/FormatEntity.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,9 @@ struct Entry {
LineEntryColumn,
LineEntryStartAddress,
LineEntryEndAddress,
CurrentPCArrow
CurrentPCArrow,
ProgressCount,
ProgressMessage,
};

struct Definition {
Expand Down
2 changes: 2 additions & 0 deletions lldb/include/lldb/Core/IOHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,8 @@ class IOHandlerEditline : public IOHandler {
std::optional<std::string> SuggestionCallback(llvm::StringRef line);

void AutoCompleteCallback(CompletionRequest &request);

void RedrawCallback();
#endif

protected:
Expand Down
67 changes: 67 additions & 0 deletions lldb/include/lldb/Core/Statusline.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//===-- Statusline.h -----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLDB_CORE_STATUSLINE_H
#define LLDB_CORE_STATUSLINE_H

#include "lldb/lldb-forward.h"
#include "llvm/ADT/StringRef.h"
#include <csignal>
#include <cstdint>
#include <string>

namespace lldb_private {
class Statusline {
public:
Statusline(Debugger &debugger);
~Statusline();

/// Reduce the scroll window and draw the statusline.
void Enable();

/// Hide the statusline and extend the scroll window.
void Disable();

/// Redraw the statusline. If update is false, this will redraw the last
/// string.
void Redraw(bool update = true);

/// Inform the statusline that the terminal dimensions have changed.
void TerminalSizeChanged();

protected:
/// Pad and trim the given string to fit to the given width.
static std::string TrimAndPad(std::string str, size_t width);

private:
/// Draw the statusline with the given text.
void Draw(std::string msg);

/// Update terminal dimensions.
void UpdateTerminalProperties();

enum ScrollWindowMode {
ScrollWindowExtend,
ScrollWindowShrink,
};

/// Set the scroll window for the given mode.
void UpdateScrollWindow(ScrollWindowMode mode);

/// Clear the statusline (without redrawing the background).
void Reset();

Debugger &m_debugger;
std::string m_last_str;

volatile std::sig_atomic_t m_terminal_size_has_changed = 1;
uint64_t m_terminal_width = 0;
uint64_t m_terminal_height = 0;
};
} // namespace lldb_private
#endif // LLDB_CORE_STATUSLINE_H
8 changes: 8 additions & 0 deletions lldb/include/lldb/Host/Editline.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ using SuggestionCallbackType =

using CompleteCallbackType = llvm::unique_function<void(CompletionRequest &)>;

using RedrawCallbackType = llvm::unique_function<void()>;

/// Status used to decide when and how to start editing another line in
/// multi-line sessions.
enum class EditorStatus {
Expand Down Expand Up @@ -194,6 +196,11 @@ class Editline {
m_suggestion_callback = std::move(callback);
}

/// Register a callback for redrawing the statusline.
void SetRedrawCallback(RedrawCallbackType callback) {
m_redraw_callback = std::move(callback);
}

/// Register a callback for the tab key
void SetAutoCompleteCallback(CompleteCallbackType callback) {
m_completion_callback = std::move(callback);
Expand Down Expand Up @@ -409,6 +416,7 @@ class Editline {

CompleteCallbackType m_completion_callback;
SuggestionCallbackType m_suggestion_callback;
RedrawCallbackType m_redraw_callback;

bool m_color;
std::string m_prompt_ansi_prefix;
Expand Down
3 changes: 3 additions & 0 deletions lldb/packages/Python/lldbsuite/test/lldbtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -770,7 +770,10 @@ def setUpCommands(cls):
'settings set symbols.clang-modules-cache-path "{}"'.format(
configuration.lldb_module_cache_dir
),
# Disable colors by default.
"settings set use-color false",
# Disable the statusline by default.
"settings set show-statusline false",
]

# Set any user-overridden settings.
Expand Down
1 change: 1 addition & 0 deletions lldb/source/Core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ add_lldb_library(lldbCore
Opcode.cpp
PluginManager.cpp
Progress.cpp
Statusline.cpp
RichManglingContext.cpp
SearchFilter.cpp
Section.cpp
Expand Down
8 changes: 8 additions & 0 deletions lldb/source/Core/CoreProperties.td
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,14 @@ let Definition = "debugger" in {
Global,
DefaultStringValue<"${ansi.normal}">,
Desc<"When displaying progress in a color-enabled terminal, use the ANSI terminal code specified in this format immediately after the progress message.">;
def ShowStatusline: Property<"show-statusline", "Boolean">,
Global,
DefaultTrue,
Desc<"Whether to show a statusline at the bottom of the terminal.">;
def StatuslineFormat: Property<"statusline-format", "FormatEntity">,
Global,
DefaultStringValue<"${ansi.bg.blue}${ansi.fg.black}{${target.file.basename}}{ | ${line.file.basename}:${line.number}:${line.column}}{ | ${thread.stop-reason}}{ | {${progress.count} }${progress.message}}">,
Desc<"The default statusline format string.">;
def UseSourceCache: Property<"use-source-cache", "Boolean">,
Global,
DefaultTrue,
Expand Down
Loading