-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[lldb] Use the terminal height for paging editline completions #119914
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
Changes from all commits
f6fdfaf
2745e5c
3fe7645
ae4e7a1
e46386b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -924,18 +924,26 @@ unsigned char Editline::BufferEndCommand(int ch) { | |
|
||
/// Prints completions and their descriptions to the given file. Only the | ||
/// completions in the interval [start, end) are printed. | ||
static void | ||
static size_t | ||
PrintCompletion(FILE *output_file, | ||
llvm::ArrayRef<CompletionResult::Completion> results, | ||
size_t max_completion_length, size_t max_length) { | ||
size_t max_completion_length, size_t max_length, | ||
std::optional<size_t> max_height = std::nullopt) { | ||
constexpr size_t ellipsis_length = 3; | ||
constexpr size_t padding_length = 8; | ||
constexpr size_t separator_length = 4; | ||
|
||
const size_t description_col = | ||
std::min(max_completion_length + padding_length, max_length); | ||
|
||
size_t lines_printed = 0; | ||
size_t results_printed = 0; | ||
for (const CompletionResult::Completion &c : results) { | ||
if (max_height && lines_printed >= *max_height) | ||
break; | ||
|
||
results_printed++; | ||
|
||
if (c.GetCompletion().empty()) | ||
continue; | ||
|
||
|
@@ -956,6 +964,7 @@ PrintCompletion(FILE *output_file, | |
fprintf(output_file, "%.*s...\n", | ||
static_cast<int>(max_length - padding_length - ellipsis_length), | ||
c.GetCompletion().c_str()); | ||
lines_printed++; | ||
continue; | ||
} | ||
|
||
|
@@ -964,6 +973,7 @@ PrintCompletion(FILE *output_file, | |
if (c.GetDescription().empty() || | ||
description_col + separator_length + ellipsis_length >= max_length) { | ||
fprintf(output_file, "\n"); | ||
lines_printed++; | ||
continue; | ||
} | ||
|
||
|
@@ -990,6 +1000,8 @@ PrintCompletion(FILE *output_file, | |
for (llvm::StringRef line : llvm::split(c.GetDescription(), '\n')) { | ||
if (line.empty()) | ||
break; | ||
if (max_height && lines_printed >= *max_height) | ||
break; | ||
if (!first) | ||
fprintf(output_file, "%*s", | ||
static_cast<int>(description_col + separator_length), ""); | ||
|
@@ -1000,14 +1012,17 @@ PrintCompletion(FILE *output_file, | |
if (position + description_length < max_length) { | ||
fprintf(output_file, "%.*s\n", static_cast<int>(description_length), | ||
line.data()); | ||
lines_printed++; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems like this could be a problem if we cross the page boundary in the middle of a multi-line description. The worst part is that given that the code above checks for strict equality, this situation might end up cause us to dump everything in a single go. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah good point. I considered the situation where we would potentially exceed the page size if the last entry was a multiline one (and deemed that acceptable) but I didn't account for it in the check. We can make that a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suppose its not the end of the world, though it that case, it might be better to bail out here (and skip printing the rest of the description) instead of pushing the first completion off the screen (and if it fit on one line, the user wouldn't even know that it was there). If this was c++20 I guess we could make this a coroutine which continues where it left off for the next page. Up to you, I guess... |
||
} else { | ||
fprintf(output_file, "%.*s...\n", | ||
static_cast<int>(max_length - position - ellipsis_length), | ||
line.data()); | ||
lines_printed++; | ||
continue; | ||
} | ||
} | ||
} | ||
return results_printed; | ||
} | ||
|
||
void Editline::DisplayCompletions( | ||
|
@@ -1016,7 +1031,11 @@ void Editline::DisplayCompletions( | |
|
||
fprintf(editline.m_output_file, | ||
"\n" ANSI_CLEAR_BELOW "Available completions:\n"); | ||
const size_t page_size = 40; | ||
|
||
/// Account for the current line, the line showing "Available completions" | ||
/// before and the line saying "More" after. | ||
const size_t page_size = editline.GetTerminalHeight() - 3; | ||
|
||
bool all = false; | ||
|
||
auto longest = | ||
|
@@ -1026,21 +1045,12 @@ void Editline::DisplayCompletions( | |
|
||
const size_t max_len = longest->GetCompletion().size(); | ||
|
||
if (results.size() < page_size) { | ||
PrintCompletion(editline.m_output_file, results, max_len, | ||
editline.GetTerminalWidth()); | ||
return; | ||
} | ||
|
||
size_t cur_pos = 0; | ||
while (cur_pos < results.size()) { | ||
size_t remaining = results.size() - cur_pos; | ||
size_t next_size = all ? remaining : std::min(page_size, remaining); | ||
|
||
PrintCompletion(editline.m_output_file, results.slice(cur_pos, next_size), | ||
max_len, editline.GetTerminalWidth()); | ||
|
||
cur_pos += next_size; | ||
cur_pos += | ||
PrintCompletion(editline.m_output_file, results.slice(cur_pos), max_len, | ||
editline.GetTerminalWidth(), | ||
all ? std::nullopt : std::optional<size_t>(page_size)); | ||
|
||
if (cur_pos >= results.size()) | ||
break; | ||
|
@@ -1525,6 +1535,13 @@ void Editline::ApplyTerminalSizeChange() { | |
m_terminal_width = INT_MAX; | ||
m_current_line_rows = 1; | ||
} | ||
|
||
int rows; | ||
if (el_get(m_editline, EL_GETTC, "li", &rows, nullptr) == 0) { | ||
m_terminal_height = rows; | ||
} else { | ||
m_terminal_height = INT_MAX; | ||
} | ||
} | ||
|
||
const char *Editline::GetPrompt() { return m_set_prompt.c_str(); } | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed the maximum value here because I didn't want to duplicate it for the terminal height. If this bothers folks I can do that in a separate commit. I don't think it makes sense to arbitrarily limit the upper bound in the age of ultra-wide monitors.