Skip to content

Commit 2f75f65

Browse files
authored
[lldb] Take a sledgehammer approach to resizing the statusline (#146578)
Terminal resizing continues to be a source of statusline bugs, so much so that some users have started disabling it altogether. Different operating systems and terminal emulators exhibit subtly different behaviors, making it nearly impossible to handle resizing reliably across the board. This patch sidesteps those issues by clearing the entire screen when the terminal is resized. This avoids having to account for the previous, potentially wrapped statusline, the underlying cause of many of the aforementioned bugs. The obvious downside is that this clears the on-screen history, but I believe that’s a reasonable trade-off. Note that this only happens when resizing the terminal; when launching LLDB, the statusline is drawn without clearing the screen. rdar://154778410
1 parent 795b17d commit 2f75f65

File tree

3 files changed

+31
-30
lines changed

3 files changed

+31
-30
lines changed

lldb/include/lldb/Core/Statusline.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,10 @@ class Statusline {
3636
/// Draw the statusline with the given text.
3737
void Draw(std::string msg);
3838

39-
/// Update terminal dimensions.
40-
void UpdateTerminalProperties();
41-
4239
enum ScrollWindowMode {
4340
EnableStatusline,
4441
DisableStatusline,
42+
ResizeStatusline,
4543
};
4644

4745
/// Set the scroll window for the given mode.

lldb/source/Core/Statusline.cpp

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#define ANSI_SAVE_CURSOR ESCAPE "7"
2525
#define ANSI_RESTORE_CURSOR ESCAPE "8"
2626
#define ANSI_CLEAR_BELOW ESCAPE "[J"
27+
#define ANSI_CLEAR_SCREEN ESCAPE "[2J"
2728
#define ANSI_SET_SCROLL_ROWS ESCAPE "[1;%ur"
2829
#define ANSI_TO_START_OF_ROW ESCAPE "[%u;1f"
2930
#define ANSI_REVERSE_VIDEO ESCAPE "[7m"
@@ -41,10 +42,12 @@ Statusline::Statusline(Debugger &debugger)
4142
Statusline::~Statusline() { Disable(); }
4243

4344
void Statusline::TerminalSizeChanged() {
44-
UpdateTerminalProperties();
45+
m_terminal_width = m_debugger.GetTerminalWidth();
46+
m_terminal_height = m_debugger.GetTerminalHeight();
4547

46-
// This definitely isn't signal safe, but the best we can do, until we
47-
// have proper signal-catching thread.
48+
UpdateScrollWindow(ResizeStatusline);
49+
50+
// Draw the old statusline.
4851
Redraw(/*update=*/false);
4952
}
5053

@@ -85,38 +88,40 @@ void Statusline::Draw(std::string str) {
8588
locked_stream << ANSI_RESTORE_CURSOR;
8689
}
8790

88-
void Statusline::UpdateTerminalProperties() {
89-
UpdateScrollWindow(DisableStatusline);
90-
m_terminal_width = m_debugger.GetTerminalWidth();
91-
m_terminal_height = m_debugger.GetTerminalHeight();
92-
UpdateScrollWindow(EnableStatusline);
93-
}
94-
9591
void Statusline::UpdateScrollWindow(ScrollWindowMode mode) {
9692
assert(m_terminal_width != 0 && m_terminal_height != 0);
9793

9894
lldb::LockableStreamFileSP stream_sp = m_debugger.GetOutputStreamSP();
9995
if (!stream_sp)
10096
return;
10197

102-
const unsigned scroll_height =
103-
(mode == DisableStatusline) ? m_terminal_height : m_terminal_height - 1;
104-
98+
const unsigned reduced_scroll_window = m_terminal_height - 1;
10599
LockedStreamFile locked_stream = stream_sp->Lock();
106100

107-
if (mode == EnableStatusline) {
101+
switch (mode) {
102+
case EnableStatusline:
108103
// Move everything on the screen up.
109104
locked_stream << '\n';
110105
locked_stream.Printf(ANSI_UP_ROWS, 1);
111-
}
112-
113-
locked_stream << ANSI_SAVE_CURSOR;
114-
locked_stream.Printf(ANSI_SET_SCROLL_ROWS, scroll_height);
115-
locked_stream << ANSI_RESTORE_CURSOR;
116-
117-
if (mode == DisableStatusline) {
106+
// Reduce the scroll window.
107+
locked_stream << ANSI_SAVE_CURSOR;
108+
locked_stream.Printf(ANSI_SET_SCROLL_ROWS, reduced_scroll_window);
109+
locked_stream << ANSI_RESTORE_CURSOR;
110+
break;
111+
case DisableStatusline:
112+
// Reset the scroll window.
113+
locked_stream << ANSI_SAVE_CURSOR;
114+
locked_stream.Printf(ANSI_SET_SCROLL_ROWS, 0);
115+
locked_stream << ANSI_RESTORE_CURSOR;
118116
// Clear the screen below to hide the old statusline.
119117
locked_stream << ANSI_CLEAR_BELOW;
118+
break;
119+
case ResizeStatusline:
120+
// Clear the screen and update the scroll window.
121+
// FIXME: Find a better solution (#146919).
122+
locked_stream << ANSI_CLEAR_SCREEN;
123+
locked_stream.Printf(ANSI_SET_SCROLL_ROWS, reduced_scroll_window);
124+
break;
120125
}
121126

122127
m_debugger.RefreshIOHandler();

lldb/test/API/functionalities/statusline/TestStatusline.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,7 @@ def test(self):
6767
self.expect('set set separator "| "')
6868

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

7472
def test_no_color(self):
7573
"""Basic test for the statusline with colors disabled."""
@@ -114,6 +112,6 @@ def test_resize(self):
114112
self.resize()
115113
self.expect("set set show-statusline true", ["no target"])
116114
self.resize(20, 60)
117-
# Check for the escape code to resize the scroll window, followed by
118-
# the prompt.
119-
self.child.expect(re.escape("\x1b[1;19r\x1b8(lldb)"))
115+
# Check for the escape code to resize the scroll window.
116+
self.child.expect(re.escape("\x1b[1;19r"))
117+
self.child.expect("(lldb)")

0 commit comments

Comments
 (0)