Skip to content

[lldb] Correctly restore the cursor column after resizing the statusline #145823

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

Closed
wants to merge 1 commit into from
Closed
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 @@ -133,6 +133,8 @@ class Debugger : public std::enable_shared_from_this<Debugger>,

void SetAsyncExecution(bool async);

CursorPosition GetIOHandlerCursorPosition();

lldb::FileSP GetInputFileSP() { return m_input_file_sp; }
File &GetInputFile() { return *m_input_file_sp; }

Expand Down
7 changes: 7 additions & 0 deletions lldb/include/lldb/Core/IOHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define LLDB_CORE_IOHANDLER_H

#include "lldb/Host/Config.h"
#include "lldb/Host/Terminal.h"
#include "lldb/Utility/CompletionRequest.h"
#include "lldb/Utility/Flags.h"
#include "lldb/Utility/Predicate.h"
Expand Down Expand Up @@ -113,6 +114,10 @@ class IOHandler {

virtual const char *GetHelpPrologue() { return nullptr; }

virtual CursorPosition GetCursorPosition() const {
return {std::nullopt, std::nullopt};
}

int GetInputFD();

int GetOutputFD();
Expand Down Expand Up @@ -404,6 +409,8 @@ class IOHandlerEditline : public IOHandler {

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

virtual CursorPosition GetCursorPosition() const override;

private:
#if LLDB_ENABLE_LIBEDIT
bool IsInputCompleteCallback(Editline *editline, StringList &lines);
Expand Down
3 changes: 3 additions & 0 deletions lldb/include/lldb/Host/Editline.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <vector>

#include "lldb/Host/StreamFile.h"
#include "lldb/Host/Terminal.h"
#include "lldb/lldb-private.h"

#if !defined(_WIN32) && !defined(__ANDROID__)
Expand Down Expand Up @@ -267,6 +268,8 @@ class Editline {

size_t GetTerminalHeight() { return m_terminal_height; }

CursorPosition GetCursorPosition();

private:
/// Sets the lowest line number for multi-line editing sessions. A value of
/// zero suppresses line number printing in the prompt.
Expand Down
5 changes: 5 additions & 0 deletions lldb/include/lldb/Host/Terminal.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,11 @@ class TerminalState {
lldb::pid_t m_process_group = -1; ///< Cached process group information.
};

struct CursorPosition {
std::optional<unsigned> cols;
std::optional<unsigned> rows;
};

} // namespace lldb_private

#endif // LLDB_HOST_TERMINAL_H
8 changes: 8 additions & 0 deletions lldb/source/Core/Debugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1240,6 +1240,14 @@ void Debugger::DispatchInputEndOfFile() {
reader_sp->GotEOF();
}

CursorPosition Debugger::GetIOHandlerCursorPosition() {
std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());
IOHandlerSP reader_sp(m_io_handler_stack.Top());
if (reader_sp)
return reader_sp->GetCursorPosition();
return {std::nullopt, std::nullopt};
}

void Debugger::ClearIOHandlers() {
// The bottom input reader should be the main debugger input reader. We do
// not want to close that one here.
Expand Down
8 changes: 8 additions & 0 deletions lldb/source/Core/IOHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,14 @@ void IOHandlerEditline::GotEOF() {
#endif
}

CursorPosition IOHandlerEditline::GetCursorPosition() const {
#if LLDB_ENABLE_LIBEDIT
if (m_editline_up)
return m_editline_up->GetCursorPosition();
#endif
return {std::nullopt, std::nullopt};
}

void IOHandlerEditline::PrintAsync(const char *s, size_t len, bool is_stdout) {
#if LLDB_ENABLE_LIBEDIT
if (m_editline_up) {
Expand Down
33 changes: 25 additions & 8 deletions lldb/source/Core/Statusline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#define ANSI_TO_START_OF_ROW ESCAPE "[%u;1f"
#define ANSI_REVERSE_VIDEO ESCAPE "[7m"
#define ANSI_UP_ROWS ESCAPE "[%dA"
#define ANSI_SET_COLUMN_N ESCAPE "[%uG"

using namespace lldb;
using namespace lldb_private;
Expand Down Expand Up @@ -103,19 +104,35 @@ void Statusline::UpdateScrollWindow(ScrollWindowMode mode) {
(mode == DisableStatusline) ? m_terminal_height : m_terminal_height - 1;

LockedStreamFile locked_stream = stream_sp->Lock();

if (mode == EnableStatusline) {
// Get the cursor position before we potentially change the cursor position.
CursorPosition cursor_position = m_debugger.GetIOHandlerCursorPosition();

// Move everything on the screen up to make space for the statusline. This
// is going to move the cursor to the start of the next line which we need
// to undo.
locked_stream << '\n';

// First move the cursor back up. We can't use ANSI_SAVE/RESTORE_CURSOR
// here, because the old and new position differ if everything on the screen
// moved up.
locked_stream.Printf(ANSI_UP_ROWS, 1);

// Finally move the cursor back to the correct column, if the IOHandler was
// able to tell us where that was.
if (cursor_position.cols)
locked_stream.Printf(ANSI_SET_COLUMN_N, *cursor_position.cols);
}

// Adjust the scroll window.
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';
break;
case DisableStatusline:

if (mode == DisableStatusline) {
// Clear the screen below to hide the old statusline.
locked_stream << ANSI_CLEAR_BELOW;
break;
}
}

Expand Down
14 changes: 14 additions & 0 deletions lldb/source/Host/common/Editline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,20 @@ int Editline::GetLineIndexForLocation(CursorLocation location, int cursor_row) {
return line;
}

CursorPosition Editline::GetCursorPosition() {
if (!m_editline)
return {};

const LineInfoW *info = el_wline(m_editline);
if (!info)
return {};

const size_t editline_cursor_col =
(int)((info->cursor - info->buffer) + GetPromptWidth()) + 1;

return {editline_cursor_col, std::nullopt};
}

void Editline::MoveCursor(CursorLocation from, CursorLocation to) {
const LineInfoW *info = el_wline(m_editline);
int editline_cursor_position =
Expand Down
Loading