LibLine: Properly handle multiline suggestions

This commit is contained in:
AnotherTest 2020-04-14 22:18:56 +04:30 committed by Andreas Kling
parent d09bea5beb
commit 32276cba7a
Notes: sideshowbarker 2024-07-19 07:35:30 +09:00
2 changed files with 32 additions and 7 deletions

View file

@ -293,6 +293,7 @@ String Editor::get_line(const String& prompt)
m_suggestions = on_tab_complete_first_token(token);
else
m_suggestions = on_tab_complete_other_token(token);
m_prompt_lines_at_suggestion_initiation = num_lines();
}
// Adjust already incremented / decremented index when switching tab direction
@ -330,25 +331,43 @@ String Editor::get_line(const String& prompt)
if (m_times_tab_pressed > 1 && !m_suggestions.is_empty()) {
size_t longest_suggestion_length = 0;
for (auto& suggestion : m_suggestions)
for (auto& suggestion : m_suggestions) {
longest_suggestion_length = max(longest_suggestion_length, suggestion.length());
}
size_t num_printed = 0;
size_t lines_used { 1 };
size_t index { 0 };
putchar('\n');
vt_save_cursor();
vt_clear_lines(0, m_lines_used_for_last_suggestions);
vt_restore_cursor();
auto spans_entire_line { false };
auto max_line_count = (m_cached_prompt_length + longest_suggestion_length + m_num_columns - 1) / m_num_columns;
if (longest_suggestion_length >= m_num_columns - 2) {
spans_entire_line = true;
// we should make enough space for the biggest entry in
// the suggestion list to fit in the prompt line
auto start = max_line_count - m_prompt_lines_at_suggestion_initiation;
for (size_t i = start; i < max_line_count; ++i) {
putchar('\n');
}
lines_used += max_line_count;
longest_suggestion_length = 0;
}
vt_move_absolute(max_line_count + m_origin_x, 1);
for (auto& suggestion : m_suggestions) {
size_t next_column = num_printed + suggestion.length() + longest_suggestion_length + 2;
if (next_column > m_num_columns) {
++lines_used;
auto lines = (suggestion.length() + m_num_columns - 1) / m_num_columns;
lines_used += lines;
putchar('\n');
num_printed = 0;
}
// show just enough suggestions to fill up the screen
// without moving the prompt out of view
if (lines_used + num_lines() >= m_num_lines)
if (lines_used + m_prompt_lines_at_suggestion_initiation >= m_num_lines)
break;
if (index == current_suggestion_index) {
@ -356,7 +375,12 @@ String Editor::get_line(const String& prompt)
fflush(stdout);
}
num_printed += fprintf(stderr, "%-*s", static_cast<int>(longest_suggestion_length) + 2, suggestion.characters());
if (spans_entire_line) {
num_printed += m_num_columns;
fprintf(stderr, "%s", suggestion.characters());
} else {
num_printed += fprintf(stderr, "%-*s", static_cast<int>(longest_suggestion_length) + 2, suggestion.characters());
}
if (index == current_suggestion_index) {
vt_apply_style({});

View file

@ -151,12 +151,12 @@ private:
size_t num_lines() const
{
return (m_cached_buffer_size + m_num_columns + current_prompt_length()) / m_num_columns;
return (m_cached_buffer_size + m_num_columns + current_prompt_length() - 1) / m_num_columns;
}
size_t cursor_line() const
{
return (m_drawn_cursor + m_num_columns + current_prompt_length()) / m_num_columns;
return (m_drawn_cursor + m_num_columns + current_prompt_length() - 1) / m_num_columns;
}
size_t offset_in_line() const
@ -187,6 +187,7 @@ private:
size_t m_old_prompt_length { 0 };
size_t m_cached_buffer_size { 0 };
size_t m_lines_used_for_last_suggestions { 0 };
size_t m_prompt_lines_at_suggestion_initiation { 0 };
bool m_cached_prompt_valid { false };
// exact position before our prompt in the terminal