Skip to content

Commit e601025

Browse files
committed
[lldb] Correctly restore the cursor column after resizing the statusline
This PR ensures we correctly restore the cursor column after resizing the statusline. To ensure we have space for the statusline, we have to emit a newline to move up everything on screen. The newline causes the cursor to move to the start of the next line, which needs to be undone. Normally, we would use escape codes to save & restore the cursor position, but that doesn't work here, as the cursor position may have (purposely) changed. Instead, we move the cursor up one line using an escape code, but we weren't restoring the column. Interestingly, Editline was able to recover from this issue through the LineInfo struct which contains the buffer and the cursor location, which allows us to compute the column. This PR addresses the bug by having Editline "refresh" the cursor position. Fixes #134064
1 parent 7eec132 commit e601025

File tree

7 files changed

+40
-8
lines changed

7 files changed

+40
-8
lines changed

lldb/include/lldb/Core/Debugger.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,8 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
227227

228228
const char *GetIOHandlerHelpPrologue();
229229

230+
void RefreshIOHandler();
231+
230232
void ClearIOHandlers();
231233

232234
bool EnableLog(llvm::StringRef channel,

lldb/include/lldb/Core/IOHandler.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ class IOHandler {
9090

9191
virtual void TerminalSizeChanged() {}
9292

93+
virtual void Refresh() {}
94+
9395
virtual const char *GetPrompt() {
9496
// Prompt support isn't mandatory
9597
return nullptr;
@@ -404,6 +406,8 @@ class IOHandlerEditline : public IOHandler {
404406

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

409+
void Refresh() override;
410+
407411
private:
408412
#if LLDB_ENABLE_LIBEDIT
409413
bool IsInputCompleteCallback(Editline *editline, StringList &lines);

lldb/include/lldb/Host/Editline.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,8 @@ class Editline {
267267

268268
size_t GetTerminalHeight() { return m_terminal_height; }
269269

270+
void Refresh();
271+
270272
private:
271273
/// Sets the lowest line number for multi-line editing sessions. A value of
272274
/// zero suppresses line number printing in the prompt.

lldb/source/Core/Debugger.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1445,6 +1445,13 @@ bool Debugger::PopIOHandler(const IOHandlerSP &pop_reader_sp) {
14451445
return true;
14461446
}
14471447

1448+
void Debugger::RefreshIOHandler() {
1449+
std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());
1450+
IOHandlerSP reader_sp(m_io_handler_stack.Top());
1451+
if (reader_sp)
1452+
reader_sp->Refresh();
1453+
}
1454+
14481455
StreamUP Debugger::GetAsyncOutputStream() {
14491456
return std::make_unique<StreamAsynchronousIO>(*this,
14501457
StreamAsynchronousIO::STDOUT);

lldb/source/Core/IOHandler.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,3 +663,10 @@ void IOHandlerEditline::PrintAsync(const char *s, size_t len, bool is_stdout) {
663663
#endif
664664
}
665665
}
666+
667+
void IOHandlerEditline::Refresh() {
668+
#if LLDB_ENABLE_LIBEDIT
669+
if (m_editline_up)
670+
m_editline_up->Refresh();
671+
#endif
672+
}

lldb/source/Core/Statusline.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -103,20 +103,23 @@ void Statusline::UpdateScrollWindow(ScrollWindowMode mode) {
103103
(mode == DisableStatusline) ? m_terminal_height : m_terminal_height - 1;
104104

105105
LockedStreamFile locked_stream = stream_sp->Lock();
106+
107+
if (mode == EnableStatusline) {
108+
// Move everything on the screen up.
109+
locked_stream << '\n';
110+
locked_stream.Printf(ANSI_UP_ROWS, 1);
111+
}
112+
106113
locked_stream << ANSI_SAVE_CURSOR;
107114
locked_stream.Printf(ANSI_SET_SCROLL_ROWS, scroll_height);
108115
locked_stream << ANSI_RESTORE_CURSOR;
109-
switch (mode) {
110-
case EnableStatusline:
111-
// Move everything on the screen up.
112-
locked_stream.Printf(ANSI_UP_ROWS, 1);
113-
locked_stream << '\n';
114-
break;
115-
case DisableStatusline:
116+
117+
if (mode == DisableStatusline) {
116118
// Clear the screen below to hide the old statusline.
117119
locked_stream << ANSI_CLEAR_BELOW;
118-
break;
119120
}
121+
122+
m_debugger.RefreshIOHandler();
120123
}
121124

122125
void Statusline::Redraw(bool update) {

lldb/source/Host/common/Editline.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1709,6 +1709,13 @@ void Editline::PrintAsync(lldb::LockableStreamFileSP stream_sp, const char *s,
17091709
}
17101710
}
17111711

1712+
void Editline::Refresh() {
1713+
if (!m_editline || !m_output_stream_sp)
1714+
return;
1715+
LockedStreamFile locked_stream = m_output_stream_sp->Lock();
1716+
MoveCursor(CursorLocation::EditingPrompt, CursorLocation::EditingCursor);
1717+
}
1718+
17121719
bool Editline::CompleteCharacter(char ch, EditLineGetCharType &out) {
17131720
#if !LLDB_EDITLINE_USE_WCHAR
17141721
if (ch == (char)EOF)

0 commit comments

Comments
 (0)