Skip to content

Commit 3f67652

Browse files
authored
Merge pull request swiftlang#9752 from swiftlang/cherrypick-swift/release/6.1-3dfc1d9b0bc4-8f151f0f559c
[🍒 swift/release/6.1] [lldb] Unify window resizing logic in command line driver
2 parents 7c8a4a0 + 0482d96 commit 3f67652

File tree

11 files changed

+147
-37
lines changed

11 files changed

+147
-37
lines changed

lldb/include/lldb/API/SBDebugger.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,10 @@ class LLDB_API SBDebugger {
382382

383383
void SetTerminalWidth(uint32_t term_width);
384384

385+
uint32_t GetTerminalHeight() const;
386+
387+
void SetTerminalHeight(uint32_t term_height);
388+
385389
lldb::user_id_t GetID();
386390

387391
const char *GetPrompt() const;

lldb/include/lldb/Core/Debugger.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,10 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
284284

285285
bool SetTerminalWidth(uint64_t term_width);
286286

287+
uint64_t GetTerminalHeight() const;
288+
289+
bool SetTerminalHeight(uint64_t term_height);
290+
287291
llvm::StringRef GetPrompt() const;
288292

289293
llvm::StringRef GetPromptAnsiPrefix() const;

lldb/include/lldb/Host/Editline.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,8 @@ class Editline {
240240

241241
size_t GetTerminalWidth() { return m_terminal_width; }
242242

243+
size_t GetTerminalHeight() { return m_terminal_height; }
244+
243245
private:
244246
/// Sets the lowest line number for multi-line editing sessions. A value of
245247
/// zero suppresses line number printing in the prompt.
@@ -373,6 +375,7 @@ class Editline {
373375
std::vector<EditLineStringType> m_input_lines;
374376
EditorStatus m_editor_status;
375377
int m_terminal_width = 0;
378+
int m_terminal_height = 0;
376379
int m_base_line_number = 0;
377380
unsigned m_current_line_index = 0;
378381
int m_current_line_rows = -1;

lldb/source/API/SBDebugger.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1407,6 +1407,19 @@ void SBDebugger::SetTerminalWidth(uint32_t term_width) {
14071407
m_opaque_sp->SetTerminalWidth(term_width);
14081408
}
14091409

1410+
uint32_t SBDebugger::GetTerminalHeight() const {
1411+
LLDB_INSTRUMENT_VA(this);
1412+
1413+
return (m_opaque_sp ? m_opaque_sp->GetTerminalWidth() : 0);
1414+
}
1415+
1416+
void SBDebugger::SetTerminalHeight(uint32_t term_height) {
1417+
LLDB_INSTRUMENT_VA(this, term_height);
1418+
1419+
if (m_opaque_sp)
1420+
m_opaque_sp->SetTerminalHeight(term_height);
1421+
}
1422+
14101423
const char *SBDebugger::GetPrompt() const {
14111424
LLDB_INSTRUMENT_VA(this);
14121425

lldb/source/Core/CoreProperties.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,10 @@ let Definition = "debugger" in {
181181
Global,
182182
DefaultUnsignedValue<80>,
183183
Desc<"The maximum number of columns to use for displaying text.">;
184+
def TerminalHeight: Property<"term-height", "UInt64">,
185+
Global,
186+
DefaultUnsignedValue<24>,
187+
Desc<"The number of rows used for displaying text.">;
184188
def ThreadFormat: Property<"thread-format", "FormatEntity">,
185189
Global,
186190
DefaultStringValue<"thread #${thread.index}: tid = ${thread.id%tid}{, ${frame.pc}}{ ${module.file.basename}{`${function.name-with-args}{${frame.no-debug}${function.pc-offset}}}}{ at ${ansi.fg.cyan}${line.file.basename}${ansi.normal}:${ansi.fg.yellow}${line.number}${ansi.normal}{:${ansi.fg.yellow}${line.column}${ansi.normal}}}{, name = ${ansi.fg.green}'${thread.name}'${ansi.normal}}{, queue = ${ansi.fg.green}'${thread.queue}'${ansi.normal}}{, activity = ${ansi.fg.green}'${thread.info.activity.name}'${ansi.normal}}{, ${thread.info.trace_messages} messages}{, stop reason = ${ansi.fg.red}${thread.stop-reason}${ansi.normal}}{\\\\nReturn value: ${thread.return-value}}{\\\\nCompleted expression: ${thread.completed-expression}}\\\\n">,

lldb/source/Core/Debugger.cpp

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -371,11 +371,29 @@ uint64_t Debugger::GetTerminalWidth() const {
371371
}
372372

373373
bool Debugger::SetTerminalWidth(uint64_t term_width) {
374+
const uint32_t idx = ePropertyTerminalWidth;
375+
const bool success = SetPropertyAtIndex(idx, term_width);
376+
374377
if (auto handler_sp = m_io_handler_stack.Top())
375378
handler_sp->TerminalSizeChanged();
376379

377-
const uint32_t idx = ePropertyTerminalWidth;
378-
return SetPropertyAtIndex(idx, term_width);
380+
return success;
381+
}
382+
383+
uint64_t Debugger::GetTerminalHeight() const {
384+
const uint32_t idx = ePropertyTerminalHeight;
385+
return GetPropertyAtIndexAs<uint64_t>(
386+
idx, g_debugger_properties[idx].default_uint_value);
387+
}
388+
389+
bool Debugger::SetTerminalHeight(uint64_t term_height) {
390+
const uint32_t idx = ePropertyTerminalHeight;
391+
const bool success = SetPropertyAtIndex(idx, term_height);
392+
393+
if (auto handler_sp = m_io_handler_stack.Top())
394+
handler_sp->TerminalSizeChanged();
395+
396+
return success;
379397
}
380398

381399
bool Debugger::GetUseExternalEditor() const {
@@ -919,7 +937,11 @@ Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
919937
m_collection_sp->GetPropertyAtIndexAsOptionValueUInt64(
920938
ePropertyTerminalWidth);
921939
term_width->SetMinimumValue(10);
922-
term_width->SetMaximumValue(1024);
940+
941+
OptionValueUInt64 *term_height =
942+
m_collection_sp->GetPropertyAtIndexAsOptionValueUInt64(
943+
ePropertyTerminalHeight);
944+
term_height->SetMinimumValue(10);
923945

924946
// Turn off use-color if this is a dumb terminal.
925947
const char *term = getenv("TERM");

lldb/source/Host/common/Editline.cpp

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -924,18 +924,26 @@ unsigned char Editline::BufferEndCommand(int ch) {
924924

925925
/// Prints completions and their descriptions to the given file. Only the
926926
/// completions in the interval [start, end) are printed.
927-
static void
927+
static size_t
928928
PrintCompletion(FILE *output_file,
929929
llvm::ArrayRef<CompletionResult::Completion> results,
930-
size_t max_completion_length, size_t max_length) {
930+
size_t max_completion_length, size_t max_length,
931+
std::optional<size_t> max_height = std::nullopt) {
931932
constexpr size_t ellipsis_length = 3;
932933
constexpr size_t padding_length = 8;
933934
constexpr size_t separator_length = 4;
934935

935936
const size_t description_col =
936937
std::min(max_completion_length + padding_length, max_length);
937938

939+
size_t lines_printed = 0;
940+
size_t results_printed = 0;
938941
for (const CompletionResult::Completion &c : results) {
942+
if (max_height && lines_printed >= *max_height)
943+
break;
944+
945+
results_printed++;
946+
939947
if (c.GetCompletion().empty())
940948
continue;
941949

@@ -956,6 +964,7 @@ PrintCompletion(FILE *output_file,
956964
fprintf(output_file, "%.*s...\n",
957965
static_cast<int>(max_length - padding_length - ellipsis_length),
958966
c.GetCompletion().c_str());
967+
lines_printed++;
959968
continue;
960969
}
961970

@@ -964,6 +973,7 @@ PrintCompletion(FILE *output_file,
964973
if (c.GetDescription().empty() ||
965974
description_col + separator_length + ellipsis_length >= max_length) {
966975
fprintf(output_file, "\n");
976+
lines_printed++;
967977
continue;
968978
}
969979

@@ -990,6 +1000,8 @@ PrintCompletion(FILE *output_file,
9901000
for (llvm::StringRef line : llvm::split(c.GetDescription(), '\n')) {
9911001
if (line.empty())
9921002
break;
1003+
if (max_height && lines_printed >= *max_height)
1004+
break;
9931005
if (!first)
9941006
fprintf(output_file, "%*s",
9951007
static_cast<int>(description_col + separator_length), "");
@@ -1000,14 +1012,17 @@ PrintCompletion(FILE *output_file,
10001012
if (position + description_length < max_length) {
10011013
fprintf(output_file, "%.*s\n", static_cast<int>(description_length),
10021014
line.data());
1015+
lines_printed++;
10031016
} else {
10041017
fprintf(output_file, "%.*s...\n",
10051018
static_cast<int>(max_length - position - ellipsis_length),
10061019
line.data());
1020+
lines_printed++;
10071021
continue;
10081022
}
10091023
}
10101024
}
1025+
return results_printed;
10111026
}
10121027

10131028
void Editline::DisplayCompletions(
@@ -1016,7 +1031,11 @@ void Editline::DisplayCompletions(
10161031

10171032
fprintf(editline.m_output_file,
10181033
"\n" ANSI_CLEAR_BELOW "Available completions:\n");
1019-
const size_t page_size = 40;
1034+
1035+
/// Account for the current line, the line showing "Available completions"
1036+
/// before and the line saying "More" after.
1037+
const size_t page_size = editline.GetTerminalHeight() - 3;
1038+
10201039
bool all = false;
10211040

10221041
auto longest =
@@ -1026,21 +1045,12 @@ void Editline::DisplayCompletions(
10261045

10271046
const size_t max_len = longest->GetCompletion().size();
10281047

1029-
if (results.size() < page_size) {
1030-
PrintCompletion(editline.m_output_file, results, max_len,
1031-
editline.GetTerminalWidth());
1032-
return;
1033-
}
1034-
10351048
size_t cur_pos = 0;
10361049
while (cur_pos < results.size()) {
1037-
size_t remaining = results.size() - cur_pos;
1038-
size_t next_size = all ? remaining : std::min(page_size, remaining);
1039-
1040-
PrintCompletion(editline.m_output_file, results.slice(cur_pos, next_size),
1041-
max_len, editline.GetTerminalWidth());
1042-
1043-
cur_pos += next_size;
1050+
cur_pos +=
1051+
PrintCompletion(editline.m_output_file, results.slice(cur_pos), max_len,
1052+
editline.GetTerminalWidth(),
1053+
all ? std::nullopt : std::optional<size_t>(page_size));
10441054

10451055
if (cur_pos >= results.size())
10461056
break;
@@ -1525,6 +1535,13 @@ void Editline::ApplyTerminalSizeChange() {
15251535
m_terminal_width = INT_MAX;
15261536
m_current_line_rows = 1;
15271537
}
1538+
1539+
int rows;
1540+
if (el_get(m_editline, EL_GETTC, "li", &rows, nullptr) == 0) {
1541+
m_terminal_height = rows;
1542+
} else {
1543+
m_terminal_height = INT_MAX;
1544+
}
15281545
}
15291546

15301547
const char *Editline::GetPrompt() { return m_set_prompt.c_str(); }

lldb/test/API/functionalities/completion/TestCompletion.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -335,13 +335,22 @@ def test_settings_replace_target_ru(self):
335335
)
336336

337337
def test_settings_show_term(self):
338-
self.complete_from_to("settings show term-", "settings show term-width")
338+
self.complete_from_to("settings show term-w", "settings show term-width")
339339

340340
def test_settings_list_term(self):
341-
self.complete_from_to("settings list term-", "settings list term-width")
341+
self.complete_from_to("settings list term-w", "settings list term-width")
342+
343+
def test_settings_show_term(self):
344+
self.complete_from_to("settings show term-h", "settings show term-height")
345+
346+
def test_settings_list_term(self):
347+
self.complete_from_to("settings list term-h", "settings list term-height")
348+
349+
def test_settings_remove_term(self):
350+
self.complete_from_to("settings remove term-w", "settings remove term-width")
342351

343352
def test_settings_remove_term(self):
344-
self.complete_from_to("settings remove term-", "settings remove term-width")
353+
self.complete_from_to("settings remove term-h", "settings remove term-height")
345354

346355
def test_settings_s(self):
347356
"""Test that 'settings s' completes to ['set', 'show']."""

lldb/test/API/terminal/TestEditlineCompletions.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,37 @@ def test_multiline_description(self):
6262
" kdp-remote is an abbreviation for 'process conn..."
6363
)
6464
self.child.expect(" kill -- Terminate the current target process.")
65+
66+
@skipIfAsan
67+
@skipIfEditlineSupportMissing
68+
def test_completion_pagination(self):
69+
"""Test that we use the terminal height for pagination."""
70+
self.launch(dimensions=(10, 30))
71+
self.child.send("_regexp-\t")
72+
self.child.expect("Available completions:")
73+
self.child.expect(" _regexp-attach")
74+
self.child.expect(" _regexp-break")
75+
self.child.expect(" _regexp-bt")
76+
self.child.expect(" _regexp-display")
77+
self.child.expect(" _regexp-down")
78+
self.child.expect(" _regexp-env")
79+
self.child.expect(" _regexp-jump")
80+
self.child.expect("More")
81+
82+
@skipIfAsan
83+
@skipIfEditlineSupportMissing
84+
def test_completion_multiline_pagination(self):
85+
"""Test that we use the terminal height for pagination and account for multi-line descriptions."""
86+
self.launch(dimensions=(6, 72))
87+
self.child.send("k\t")
88+
self.child.expect("Available completions:")
89+
self.child.expect(
90+
" kdp-remote -- Connect to a process via remote KDP server."
91+
)
92+
self.child.expect(
93+
" If no UDP port is specified, port 41139 is assu..."
94+
)
95+
self.child.expect(
96+
" kdp-remote is an abbreviation for 'process conn..."
97+
)
98+
self.child.expect("More")

lldb/tools/driver/Driver.cpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -454,12 +454,8 @@ int Driver::MainLoop() {
454454
m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor);
455455
m_debugger.SetShowInlineDiagnostics(true);
456456

457-
struct winsize window_size;
458-
if ((isatty(STDIN_FILENO) != 0) &&
459-
::ioctl(STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) {
460-
if (window_size.ws_col > 0)
461-
m_debugger.SetTerminalWidth(window_size.ws_col);
462-
}
457+
// Set the terminal dimensions.
458+
UpdateWindowSize();
463459

464460
SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
465461

@@ -635,20 +631,24 @@ int Driver::MainLoop() {
635631
return sb_interpreter.GetQuitStatus();
636632
}
637633

638-
void Driver::ResizeWindow(unsigned short col) {
639-
GetDebugger().SetTerminalWidth(col);
640-
}
641-
642-
void sigwinch_handler(int signo) {
634+
void Driver::UpdateWindowSize() {
643635
struct winsize window_size;
644636
if ((isatty(STDIN_FILENO) != 0) &&
645637
::ioctl(STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) {
646-
if ((window_size.ws_col > 0) && g_driver != nullptr) {
647-
g_driver->ResizeWindow(window_size.ws_col);
648-
}
638+
if (window_size.ws_col > 0)
639+
m_debugger.SetTerminalWidth(window_size.ws_col);
640+
#ifndef _WIN32
641+
if (window_size.ws_row > 0)
642+
m_debugger.SetTerminalHeight(window_size.ws_row);
643+
#endif
649644
}
650645
}
651646

647+
void sigwinch_handler(int signo) {
648+
if (g_driver != nullptr)
649+
g_driver->UpdateWindowSize();
650+
}
651+
652652
void sigint_handler(int signo) {
653653
#ifdef _WIN32 // Restore handler as it is not persistent on Windows
654654
signal(SIGINT, sigint_handler);

lldb/tools/driver/Driver.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ class Driver : public lldb::SBBroadcaster {
9292

9393
lldb::SBDebugger &GetDebugger() { return m_debugger; }
9494

95-
void ResizeWindow(unsigned short col);
95+
void UpdateWindowSize();
9696

9797
private:
9898
lldb::SBDebugger m_debugger;

0 commit comments

Comments
 (0)