Skip to content
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
2 changes: 2 additions & 0 deletions lldb/include/lldb/Core/Debugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,8 @@ class Debugger : public std::enable_shared_from_this<Debugger>,

const char *GetIOHandlerHelpPrologue();

void RefreshIOHandler();

void ClearIOHandlers();

bool EnableLog(llvm::StringRef channel,
Expand Down
4 changes: 4 additions & 0 deletions lldb/include/lldb/Core/IOHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ class IOHandler {

virtual void TerminalSizeChanged() {}

virtual void Refresh() {}

virtual const char *GetPrompt() {
// Prompt support isn't mandatory
return nullptr;
Expand Down Expand Up @@ -404,6 +406,8 @@ class IOHandlerEditline : public IOHandler {

void PrintAsync(const char *s, size_t len, bool is_stdout) override;

void Refresh() override;

private:
#if LLDB_ENABLE_LIBEDIT
bool IsInputCompleteCallback(Editline *editline, StringList &lines);
Expand Down
4 changes: 1 addition & 3 deletions lldb/include/lldb/Core/Statusline.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,10 @@ class Statusline {
/// Draw the statusline with the given text.
void Draw(std::string msg);

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

enum ScrollWindowMode {
EnableStatusline,
DisableStatusline,
ResizeStatusline,
};

/// Set the scroll window for the given mode.
Expand Down
2 changes: 2 additions & 0 deletions lldb/include/lldb/Host/Editline.h
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,8 @@ class Editline {

size_t GetTerminalHeight() { return m_terminal_height; }

void Refresh();

private:
/// Sets the lowest line number for multi-line editing sessions. A value of
/// zero suppresses line number printing in the prompt.
Expand Down
7 changes: 7 additions & 0 deletions lldb/source/Core/Debugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1435,6 +1435,13 @@ bool Debugger::PopIOHandler(const IOHandlerSP &pop_reader_sp) {
return true;
}

void Debugger::RefreshIOHandler() {
std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());
IOHandlerSP reader_sp(m_io_handler_stack.Top());
if (reader_sp)
reader_sp->Refresh();
}

StreamUP Debugger::GetAsyncOutputStream() {
return std::make_unique<StreamAsynchronousIO>(*this,
StreamAsynchronousIO::STDOUT);
Expand Down
7 changes: 7 additions & 0 deletions lldb/source/Core/IOHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -666,3 +666,10 @@ void IOHandlerEditline::PrintAsync(const char *s, size_t len, bool is_stdout) {
#endif
}
}

void IOHandlerEditline::Refresh() {
#if LLDB_ENABLE_LIBEDIT
if (m_editline_up)
m_editline_up->Refresh();
#endif
}
48 changes: 27 additions & 21 deletions lldb/source/Core/Statusline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,9 @@
#define ANSI_SAVE_CURSOR ESCAPE "7"
#define ANSI_RESTORE_CURSOR ESCAPE "8"
#define ANSI_CLEAR_BELOW ESCAPE "[J"
#define ANSI_CURSOR_DOWN ESCAPE "[B"
#define ANSI_CLEAR_LINE ESCAPE "[2K"
#define ANSI_SET_SCROLL_ROWS ESCAPE "[0;%ur"
#define ANSI_TO_START_OF_ROW ESCAPE "[%u;0f"
#define ANSI_CLEAR_SCREEN ESCAPE "[2J"
#define ANSI_SET_SCROLL_ROWS ESCAPE "[1;%ur"
#define ANSI_TO_START_OF_ROW ESCAPE "[%u;1f"
#define ANSI_REVERSE_VIDEO ESCAPE "[7m"
#define ANSI_UP_ROWS ESCAPE "[%dA"

Expand All @@ -43,10 +42,12 @@ Statusline::Statusline(Debugger &debugger)
Statusline::~Statusline() { Disable(); }

void Statusline::TerminalSizeChanged() {
UpdateTerminalProperties();
m_terminal_width = m_debugger.GetTerminalWidth();
m_terminal_height = m_debugger.GetTerminalHeight();

UpdateScrollWindow(ResizeStatusline);

// This definitely isn't signal safe, but the best we can do, until we
// have proper signal-catching thread.
// Draw the old statusline.
Redraw(/*update=*/false);
}

Expand Down Expand Up @@ -87,38 +88,43 @@ void Statusline::Draw(std::string str) {
locked_stream << ANSI_RESTORE_CURSOR;
}

void Statusline::UpdateTerminalProperties() {
UpdateScrollWindow(DisableStatusline);
m_terminal_width = m_debugger.GetTerminalWidth();
m_terminal_height = m_debugger.GetTerminalHeight();
UpdateScrollWindow(EnableStatusline);
}

void Statusline::UpdateScrollWindow(ScrollWindowMode mode) {
assert(m_terminal_width != 0 && m_terminal_height != 0);

lldb::LockableStreamFileSP stream_sp = m_debugger.GetOutputStreamSP();
if (!stream_sp)
return;

const unsigned scroll_height =
(mode == DisableStatusline) ? m_terminal_height : m_terminal_height - 1;

const unsigned reduced_scroll_window = m_terminal_height - 1;
LockedStreamFile locked_stream = stream_sp->Lock();
locked_stream << ANSI_SAVE_CURSOR;
locked_stream.Printf(ANSI_SET_SCROLL_ROWS, scroll_height);
locked_stream << ANSI_RESTORE_CURSOR;

switch (mode) {
case EnableStatusline:
// Move everything on the screen up.
locked_stream.Printf(ANSI_UP_ROWS, 1);
locked_stream << '\n';
locked_stream.Printf(ANSI_UP_ROWS, 1);
// Reduce the scroll window.
locked_stream << ANSI_SAVE_CURSOR;
locked_stream.Printf(ANSI_SET_SCROLL_ROWS, reduced_scroll_window);
locked_stream << ANSI_RESTORE_CURSOR;
break;
case DisableStatusline:
// Reset the scroll window.
locked_stream << ANSI_SAVE_CURSOR;
locked_stream.Printf(ANSI_SET_SCROLL_ROWS, 0);
locked_stream << ANSI_RESTORE_CURSOR;
// Clear the screen below to hide the old statusline.
locked_stream << ANSI_CLEAR_BELOW;
break;
case ResizeStatusline:
// Clear the screen and update the scroll window.
// FIXME: Find a better solution (#146919).
locked_stream << ANSI_CLEAR_SCREEN;
locked_stream.Printf(ANSI_SET_SCROLL_ROWS, reduced_scroll_window);
break;
}

m_debugger.RefreshIOHandler();
}

void Statusline::Redraw(bool update) {
Expand Down
7 changes: 7 additions & 0 deletions lldb/source/Host/common/Editline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1709,6 +1709,13 @@ void Editline::PrintAsync(lldb::LockableStreamFileSP stream_sp, const char *s,
}
}

void Editline::Refresh() {
if (!m_editline || !m_output_stream_sp)
return;
LockedStreamFile locked_stream = m_output_stream_sp->Lock();
el_set(m_editline, EL_REFRESH);
}

bool Editline::CompleteCharacter(char ch, EditLineGetCharType &out) {
#if !LLDB_EDITLINE_USE_WCHAR
if (ch == (char)EOF)
Expand Down
23 changes: 17 additions & 6 deletions lldb/test/API/functionalities/statusline/TestStatusline.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ def do_setup(self):
self.expect("run", substrs=["stop reason"])
self.resize()

def resize(self):
def resize(self, height=None, width=None):
height = self.TERMINAL_HEIGHT if not height else height
width = self.TERMINAL_WIDTH if not width else width
# Change the terminal dimensions. When we launch the tests, we reset
# all the settings, leaving the terminal dimensions unset.
self.child.setwinsize(self.TERMINAL_HEIGHT, self.TERMINAL_WIDTH)
self.child.setwinsize(height, width)

def test(self):
"""Basic test for the statusline."""
Expand All @@ -44,7 +46,7 @@ def test(self):
self.expect(
"set set show-statusline true",
[
"\x1b[0;{}r".format(self.TERMINAL_HEIGHT - 1),
"\x1b[1;{}r".format(self.TERMINAL_HEIGHT - 1),
"a.out | main.c:2:11 | breakpoint 1.1 ",
],
)
Expand All @@ -65,9 +67,7 @@ def test(self):
self.expect('set set separator "| "')

# Hide the statusline and check or the control character.
self.expect(
"set set show-statusline false", ["\x1b[0;{}r".format(self.TERMINAL_HEIGHT)]
)
self.expect("set set show-statusline false", ["\x1b[1;0r"])

def test_no_color(self):
"""Basic test for the statusline with colors disabled."""
Expand Down Expand Up @@ -104,3 +104,14 @@ def test_no_target(self):
self.resize()

self.expect("set set show-statusline true", ["no target"])

@skipIfEditlineSupportMissing
def test_resize(self):
"""Test that move the cursor when resizing."""
self.launch(timeout=self.TIMEOUT)
self.resize()
self.expect("set set show-statusline true", ["no target"])
self.resize(20, 60)
# Check for the escape code to resize the scroll window.
self.child.expect(re.escape("\x1b[1;19r"))
self.child.expect("(lldb)")