mirror of
https://github.com/RGBCube/serenity
synced 2025-07-23 20:57:41 +00:00
LibLine: Make the comments follow the project style
This commit is contained in:
parent
3c3edf5831
commit
909ac2a558
6 changed files with 81 additions and 83 deletions
|
@ -294,7 +294,7 @@ String Editor::get_line(const String& prompt)
|
||||||
auto reverse_tab = false;
|
auto reverse_tab = false;
|
||||||
auto ctrl_held = false;
|
auto ctrl_held = false;
|
||||||
|
|
||||||
// discard starting bytes until they make sense as utf-8
|
// Discard starting bytes until they make sense as utf-8.
|
||||||
size_t valid_bytes = 0;
|
size_t valid_bytes = 0;
|
||||||
while (nread) {
|
while (nread) {
|
||||||
Utf8View { StringView { m_incomplete_data.data(), (size_t)nread } }.validate(valid_bytes);
|
Utf8View { StringView { m_incomplete_data.data(), (size_t)nread } }.validate(valid_bytes);
|
||||||
|
@ -395,8 +395,8 @@ String Editor::get_line(const String& prompt)
|
||||||
case 'C': // right
|
case 'C': // right
|
||||||
if (m_cursor < m_buffer.size()) {
|
if (m_cursor < m_buffer.size()) {
|
||||||
if (ctrl_held) {
|
if (ctrl_held) {
|
||||||
// temporarily put a space at the end of our buffer
|
// Temporarily put a space at the end of our buffer,
|
||||||
// this greatly simplifies the logic below
|
// doing this greatly simplifies the logic below.
|
||||||
m_buffer.append(' ');
|
m_buffer.append(' ');
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (m_cursor >= m_buffer.size())
|
if (m_cursor >= m_buffer.size())
|
||||||
|
@ -476,25 +476,25 @@ String Editor::get_line(const String& prompt)
|
||||||
if (!on_tab_complete)
|
if (!on_tab_complete)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// reverse tab can count as regular tab here
|
// Reverse tab can count as regular tab here.
|
||||||
m_times_tab_pressed++;
|
m_times_tab_pressed++;
|
||||||
|
|
||||||
int token_start = m_cursor;
|
int token_start = m_cursor;
|
||||||
|
|
||||||
// ask for completions only on the first tab
|
// Ask for completions only on the first tab
|
||||||
// and scan for the largest common prefix to display
|
// and scan for the largest common prefix to display,
|
||||||
// further tabs simply show the cached completions
|
// further tabs simply show the cached completions.
|
||||||
if (m_times_tab_pressed == 1) {
|
if (m_times_tab_pressed == 1) {
|
||||||
m_suggestion_manager.set_suggestions(on_tab_complete(*this));
|
m_suggestion_manager.set_suggestions(on_tab_complete(*this));
|
||||||
m_prompt_lines_at_suggestion_initiation = num_lines();
|
m_prompt_lines_at_suggestion_initiation = num_lines();
|
||||||
if (m_suggestion_manager.count() == 0) {
|
if (m_suggestion_manager.count() == 0) {
|
||||||
// there are no suggestions, beep~
|
// There are no suggestions, beep.
|
||||||
putchar('\a');
|
putchar('\a');
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust already incremented / decremented index when switching tab direction
|
// Adjust already incremented / decremented index when switching tab direction.
|
||||||
if (reverse_tab && m_tab_direction != TabDirection::Backward) {
|
if (reverse_tab && m_tab_direction != TabDirection::Backward) {
|
||||||
m_suggestion_manager.previous();
|
m_suggestion_manager.previous();
|
||||||
m_suggestion_manager.previous();
|
m_suggestion_manager.previous();
|
||||||
|
@ -523,7 +523,7 @@ String Editor::get_line(const String& prompt)
|
||||||
insert(view);
|
insert(view);
|
||||||
|
|
||||||
if (completion_result.style_to_apply.has_value()) {
|
if (completion_result.style_to_apply.has_value()) {
|
||||||
// Apply the style of the last suggestion
|
// Apply the style of the last suggestion.
|
||||||
readjust_anchored_styles(m_suggestion_manager.current_suggestion().start_index, ModificationKind::ForcedOverlapRemoval);
|
readjust_anchored_styles(m_suggestion_manager.current_suggestion().start_index, ModificationKind::ForcedOverlapRemoval);
|
||||||
stylize({ m_suggestion_manager.current_suggestion().start_index, m_cursor, Span::Mode::CodepointOriented }, completion_result.style_to_apply.value());
|
stylize({ m_suggestion_manager.current_suggestion().start_index, m_cursor, Span::Mode::CodepointOriented }, completion_result.style_to_apply.value());
|
||||||
}
|
}
|
||||||
|
@ -560,9 +560,9 @@ String Editor::get_line(const String& prompt)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_suggestion_manager.count() < 2) {
|
if (m_suggestion_manager.count() < 2) {
|
||||||
// we have none, or just one suggestion
|
// We have none, or just one suggestion,
|
||||||
// we should just commit that and continue
|
// we should just commit that and continue
|
||||||
// after it, as if it were auto-completed
|
// after it, as if it were auto-completed.
|
||||||
suggest(0, 0, Span::CodepointOriented);
|
suggest(0, 0, Span::CodepointOriented);
|
||||||
m_times_tab_pressed = 0;
|
m_times_tab_pressed = 0;
|
||||||
m_suggestion_manager.reset();
|
m_suggestion_manager.reset();
|
||||||
|
@ -572,11 +572,11 @@ String Editor::get_line(const String& prompt)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_times_tab_pressed) {
|
if (m_times_tab_pressed) {
|
||||||
// Apply the style of the last suggestion
|
// Apply the style of the last suggestion.
|
||||||
readjust_anchored_styles(m_suggestion_manager.current_suggestion().start_index, ModificationKind::ForcedOverlapRemoval);
|
readjust_anchored_styles(m_suggestion_manager.current_suggestion().start_index, ModificationKind::ForcedOverlapRemoval);
|
||||||
stylize({ m_suggestion_manager.current_suggestion().start_index, m_cursor, Span::Mode::CodepointOriented }, m_suggestion_manager.current_suggestion().style);
|
stylize({ m_suggestion_manager.current_suggestion().start_index, m_cursor, Span::Mode::CodepointOriented }, m_suggestion_manager.current_suggestion().style);
|
||||||
// we probably have some suggestions drawn
|
// We probably have some suggestions drawn,
|
||||||
// let's clean them up
|
// let's clean them up.
|
||||||
if (m_suggestion_display->cleanup()) {
|
if (m_suggestion_display->cleanup()) {
|
||||||
reposition_cursor();
|
reposition_cursor();
|
||||||
m_refresh_needed = true;
|
m_refresh_needed = true;
|
||||||
|
@ -599,7 +599,7 @@ String Editor::get_line(const String& prompt)
|
||||||
remove_at_index(m_cursor - 1);
|
remove_at_index(m_cursor - 1);
|
||||||
--m_cursor;
|
--m_cursor;
|
||||||
m_inline_search_cursor = m_cursor;
|
m_inline_search_cursor = m_cursor;
|
||||||
// we will have to redraw :(
|
// We will have to redraw :(
|
||||||
m_refresh_needed = true;
|
m_refresh_needed = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -661,15 +661,15 @@ String Editor::get_line(const String& prompt)
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
// whenever the search editor gets a ^R, cycle between history entries
|
// Whenever the search editor gets a ^R, cycle between history entries.
|
||||||
m_search_editor->register_character_input_callback(0x12, [this](Editor& search_editor) {
|
m_search_editor->register_character_input_callback(0x12, [this](Editor& search_editor) {
|
||||||
++m_search_offset;
|
++m_search_offset;
|
||||||
search_editor.m_refresh_needed = true;
|
search_editor.m_refresh_needed = true;
|
||||||
return false; // Do not process this key event
|
return false; // Do not process this key event
|
||||||
});
|
});
|
||||||
|
|
||||||
// whenever the search editor gets a backspace, cycle back between history entries
|
// Whenever the search editor gets a backspace, cycle back between history entries
|
||||||
// unless we're at the zeroth entry, in which case, allow the deletion
|
// unless we're at the zeroth entry, in which case, allow the deletion.
|
||||||
m_search_editor->register_character_input_callback(m_termios.c_cc[VERASE], [this](Editor& search_editor) {
|
m_search_editor->register_character_input_callback(m_termios.c_cc[VERASE], [this](Editor& search_editor) {
|
||||||
if (m_search_offset > 0) {
|
if (m_search_offset > 0) {
|
||||||
--m_search_offset;
|
--m_search_offset;
|
||||||
|
@ -682,7 +682,7 @@ String Editor::get_line(const String& prompt)
|
||||||
// ^L - This is a source of issues, as the search editor refreshes first,
|
// ^L - This is a source of issues, as the search editor refreshes first,
|
||||||
// and we end up with the wrong order of prompts, so we will first refresh
|
// and we end up with the wrong order of prompts, so we will first refresh
|
||||||
// ourselves, then refresh the search editor, and then tell him not to process
|
// ourselves, then refresh the search editor, and then tell him not to process
|
||||||
// this event
|
// this event.
|
||||||
m_search_editor->register_character_input_callback(0x0c, [this](auto& search_editor) {
|
m_search_editor->register_character_input_callback(0x0c, [this](auto& search_editor) {
|
||||||
printf("\033[3J\033[H\033[2J"); // Clear screen.
|
printf("\033[3J\033[H\033[2J"); // Clear screen.
|
||||||
|
|
||||||
|
@ -716,7 +716,7 @@ String Editor::get_line(const String& prompt)
|
||||||
m_is_searching = false;
|
m_is_searching = false;
|
||||||
m_search_offset = 0;
|
m_search_offset = 0;
|
||||||
|
|
||||||
// manually cleanup the search line
|
// Manually cleanup the search line.
|
||||||
reposition_cursor();
|
reposition_cursor();
|
||||||
auto search_string_codepoint_length = Utf8View { search_string }.length_in_codepoints();
|
auto search_string_codepoint_length = Utf8View { search_string }.length_in_codepoints();
|
||||||
VT::clear_lines(0, (search_string_codepoint_length + actual_rendered_string_length(search_prompt) + m_num_columns - 1) / m_num_columns);
|
VT::clear_lines(0, (search_string_codepoint_length + actual_rendered_string_length(search_prompt) + m_num_columns - 1) / m_num_columns);
|
||||||
|
@ -724,14 +724,13 @@ String Editor::get_line(const String& prompt)
|
||||||
reposition_cursor();
|
reposition_cursor();
|
||||||
|
|
||||||
if (!m_reset_buffer_on_search_end || search_string_codepoint_length == 0) {
|
if (!m_reset_buffer_on_search_end || search_string_codepoint_length == 0) {
|
||||||
// if the entry was empty, or we purposely quit without a newline,
|
// If the entry was empty, or we purposely quit without a newline,
|
||||||
// do not return anything
|
// do not return anything; instead, just end the search.
|
||||||
// instead, just end the search
|
|
||||||
end_search();
|
end_search();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return the string
|
// Return the string,
|
||||||
finish();
|
finish();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -741,7 +740,7 @@ String Editor::get_line(const String& prompt)
|
||||||
if (codepoint == m_termios.c_cc[VEOF]) {
|
if (codepoint == m_termios.c_cc[VEOF]) {
|
||||||
if (m_buffer.is_empty()) {
|
if (m_buffer.is_empty()) {
|
||||||
printf("<EOF>\n");
|
printf("<EOF>\n");
|
||||||
if (!m_always_refresh) // this is a little off, but it'll do for now
|
if (!m_always_refresh) // This is a little off, but it'll do for now
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
@ -774,7 +773,7 @@ bool Editor::search(const StringView& phrase, bool allow_empty, bool from_beginn
|
||||||
|
|
||||||
int last_matching_offset = -1;
|
int last_matching_offset = -1;
|
||||||
|
|
||||||
// do not search for empty strings
|
// Do not search for empty strings.
|
||||||
if (allow_empty || phrase.length() > 0) {
|
if (allow_empty || phrase.length() > 0) {
|
||||||
size_t search_offset = m_search_offset;
|
size_t search_offset = m_search_offset;
|
||||||
for (size_t i = m_history_cursor; i > 0; --i) {
|
for (size_t i = m_history_cursor; i > 0; --i) {
|
||||||
|
@ -798,25 +797,25 @@ bool Editor::search(const StringView& phrase, bool allow_empty, bool from_beginn
|
||||||
if (last_matching_offset >= 0) {
|
if (last_matching_offset >= 0) {
|
||||||
insert(m_history[last_matching_offset]);
|
insert(m_history[last_matching_offset]);
|
||||||
}
|
}
|
||||||
// always needed
|
// Always needed, as we have cleared the buffer above.
|
||||||
m_refresh_needed = true;
|
m_refresh_needed = true;
|
||||||
return last_matching_offset >= 0;
|
return last_matching_offset >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::recalculate_origin()
|
void Editor::recalculate_origin()
|
||||||
{
|
{
|
||||||
// changing the columns can affect our origin if
|
// Changing the columns can affect our origin if
|
||||||
// the new size is smaller than our prompt, which would
|
// the new size is smaller than our prompt, which would
|
||||||
// cause said prompt to take up more space, so we should
|
// cause said prompt to take up more space, so we should
|
||||||
// compensate for that
|
// compensate for that.
|
||||||
if (m_cached_prompt_length >= m_num_columns) {
|
if (m_cached_prompt_length >= m_num_columns) {
|
||||||
auto added_lines = (m_cached_prompt_length + 1) / m_num_columns - 1;
|
auto added_lines = (m_cached_prompt_length + 1) / m_num_columns - 1;
|
||||||
m_origin_x += added_lines;
|
m_origin_x += added_lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
// we also need to recalculate our cursor position
|
// We also need to recalculate our cursor position,
|
||||||
// but that will be calculated and applied at the next
|
// but that will be calculated and applied at the next
|
||||||
// refresh cycle
|
// refresh cycle.
|
||||||
}
|
}
|
||||||
void Editor::cleanup()
|
void Editor::cleanup()
|
||||||
{
|
{
|
||||||
|
@ -830,8 +829,8 @@ void Editor::cleanup()
|
||||||
void Editor::refresh_display()
|
void Editor::refresh_display()
|
||||||
{
|
{
|
||||||
auto has_cleaned_up = false;
|
auto has_cleaned_up = false;
|
||||||
// someone changed the window size, figure it out
|
// Someone changed the window size, figure it out
|
||||||
// and react to it, we might need to redraw
|
// and react to it, we might need to redraw.
|
||||||
if (m_was_resized) {
|
if (m_was_resized) {
|
||||||
auto previous_num_columns = m_num_columns;
|
auto previous_num_columns = m_num_columns;
|
||||||
|
|
||||||
|
@ -846,7 +845,7 @@ void Editor::refresh_display()
|
||||||
m_suggestion_display->set_vt_size(m_num_lines, m_num_columns);
|
m_suggestion_display->set_vt_size(m_num_lines, m_num_columns);
|
||||||
|
|
||||||
if (previous_num_columns != m_num_columns) {
|
if (previous_num_columns != m_num_columns) {
|
||||||
// we need to cleanup and redo everything
|
// We need to cleanup and redo everything.
|
||||||
m_cached_prompt_valid = false;
|
m_cached_prompt_valid = false;
|
||||||
m_refresh_needed = true;
|
m_refresh_needed = true;
|
||||||
swap(previous_num_columns, m_num_columns);
|
swap(previous_num_columns, m_num_columns);
|
||||||
|
@ -856,9 +855,9 @@ void Editor::refresh_display()
|
||||||
has_cleaned_up = true;
|
has_cleaned_up = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// do not call hook on pure cursor movement
|
// Do not call hook on pure cursor movement.
|
||||||
if (m_cached_prompt_valid && !m_refresh_needed && m_pending_chars.size() == 0) {
|
if (m_cached_prompt_valid && !m_refresh_needed && m_pending_chars.size() == 0) {
|
||||||
// probably just moving around
|
// Probably just moving around.
|
||||||
reposition_cursor();
|
reposition_cursor();
|
||||||
m_cached_buffer_size = m_buffer.size();
|
m_cached_buffer_size = m_buffer.size();
|
||||||
return;
|
return;
|
||||||
|
@ -869,8 +868,8 @@ void Editor::refresh_display()
|
||||||
|
|
||||||
if (m_cached_prompt_valid) {
|
if (m_cached_prompt_valid) {
|
||||||
if (!m_refresh_needed && m_cursor == m_buffer.size()) {
|
if (!m_refresh_needed && m_cursor == m_buffer.size()) {
|
||||||
// just write the characters out and continue
|
// Just write the characters out and continue,
|
||||||
// no need to refresh the entire line
|
// no need to refresh the entire line.
|
||||||
char null = 0;
|
char null = 0;
|
||||||
m_pending_chars.append(&null, 1);
|
m_pending_chars.append(&null, 1);
|
||||||
fputs((char*)m_pending_chars.data(), stdout);
|
fputs((char*)m_pending_chars.data(), stdout);
|
||||||
|
@ -882,7 +881,7 @@ void Editor::refresh_display()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ouch, reflow entire line
|
// Ouch, reflow entire line.
|
||||||
// FIXME: handle multiline stuff
|
// FIXME: handle multiline stuff
|
||||||
if (!has_cleaned_up) {
|
if (!has_cleaned_up) {
|
||||||
cleanup();
|
cleanup();
|
||||||
|
@ -910,10 +909,10 @@ void Editor::refresh_display()
|
||||||
for (auto& applicable_style : anchored_ends)
|
for (auto& applicable_style : anchored_ends)
|
||||||
style.unify_with(applicable_style.value);
|
style.unify_with(applicable_style.value);
|
||||||
|
|
||||||
// Disable any style that should be turned off
|
// Disable any style that should be turned off.
|
||||||
VT::apply_style(style, false);
|
VT::apply_style(style, false);
|
||||||
|
|
||||||
// go back to defaults
|
// Reapply styles for overlapping spans that include this one.
|
||||||
style = find_applicable_style(i);
|
style = find_applicable_style(i);
|
||||||
VT::apply_style(style, true);
|
VT::apply_style(style, true);
|
||||||
}
|
}
|
||||||
|
@ -926,7 +925,7 @@ void Editor::refresh_display()
|
||||||
for (auto& applicable_style : anchored_starts)
|
for (auto& applicable_style : anchored_starts)
|
||||||
style.unify_with(applicable_style.value);
|
style.unify_with(applicable_style.value);
|
||||||
|
|
||||||
// set new options
|
// Set new styles.
|
||||||
VT::apply_style(style, true);
|
VT::apply_style(style, true);
|
||||||
}
|
}
|
||||||
builder.clear();
|
builder.clear();
|
||||||
|
@ -998,7 +997,7 @@ void VT::move_relative(int x, int y)
|
||||||
|
|
||||||
Style Editor::find_applicable_style(size_t offset) const
|
Style Editor::find_applicable_style(size_t offset) const
|
||||||
{
|
{
|
||||||
// walk through our styles and merge all that fit in the offset
|
// Walk through our styles and merge all that fit in the offset.
|
||||||
Style style;
|
Style style;
|
||||||
auto unify = [&](auto& entry) {
|
auto unify = [&](auto& entry) {
|
||||||
if (entry.key >= offset)
|
if (entry.key >= offset)
|
||||||
|
@ -1055,14 +1054,14 @@ String Style::Hyperlink::to_vt_escape(bool starting) const
|
||||||
|
|
||||||
void Style::unify_with(const Style& other, bool prefer_other)
|
void Style::unify_with(const Style& other, bool prefer_other)
|
||||||
{
|
{
|
||||||
// unify colors
|
// Unify colors.
|
||||||
if (prefer_other || m_background.is_default())
|
if (prefer_other || m_background.is_default())
|
||||||
m_background = other.background();
|
m_background = other.background();
|
||||||
|
|
||||||
if (prefer_other || m_foreground.is_default())
|
if (prefer_other || m_foreground.is_default())
|
||||||
m_foreground = other.foreground();
|
m_foreground = other.foreground();
|
||||||
|
|
||||||
// unify graphic renditions
|
// Unify graphic renditions.
|
||||||
if (other.bold())
|
if (other.bold())
|
||||||
set(Bold);
|
set(Bold);
|
||||||
|
|
||||||
|
@ -1072,7 +1071,7 @@ void Style::unify_with(const Style& other, bool prefer_other)
|
||||||
if (other.underline())
|
if (other.underline())
|
||||||
set(Underline);
|
set(Underline);
|
||||||
|
|
||||||
// unify links
|
// Unify links.
|
||||||
if (prefer_other || m_hyperlink.is_empty())
|
if (prefer_other || m_hyperlink.is_empty())
|
||||||
m_hyperlink = other.hyperlink();
|
m_hyperlink = other.hyperlink();
|
||||||
}
|
}
|
||||||
|
@ -1137,10 +1136,10 @@ void VT::apply_style(const Style& style, bool is_starting)
|
||||||
|
|
||||||
void VT::clear_lines(size_t count_above, size_t count_below)
|
void VT::clear_lines(size_t count_above, size_t count_below)
|
||||||
{
|
{
|
||||||
// go down count_below lines
|
// Go down count_below lines.
|
||||||
if (count_below > 0)
|
if (count_below > 0)
|
||||||
printf("\033[%dB", (int)count_below);
|
printf("\033[%dB", (int)count_below);
|
||||||
// then clear lines going upwards
|
// Then clear lines going upwards.
|
||||||
for (size_t i = count_below + count_above; i > 0; --i)
|
for (size_t i = count_below + count_above; i > 0; --i)
|
||||||
fputs(i == 1 ? "\033[2K" : "\033[2K\033[A", stdout);
|
fputs(i == 1 ? "\033[2K" : "\033[2K\033[A", stdout);
|
||||||
}
|
}
|
||||||
|
@ -1180,13 +1179,12 @@ size_t Editor::actual_rendered_string_length(const StringView& string) const
|
||||||
auto c = *it;
|
auto c = *it;
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case Free:
|
case Free:
|
||||||
if (c == '\x1b') {
|
if (c == '\x1b') { // escape
|
||||||
// escape
|
|
||||||
state = Escape;
|
state = Escape;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (c == '\r' || c == '\n') {
|
if (c == '\r' || c == '\n') { // return or carriage return
|
||||||
// reset length to 0, since we either overwrite, or are on a newline
|
// Reset length to 0, since we either overwrite, or are on a newline.
|
||||||
length = 0;
|
length = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1235,8 +1233,8 @@ Vector<size_t, 2> Editor::vt_dsr()
|
||||||
char buf[16];
|
char buf[16];
|
||||||
u32 length { 0 };
|
u32 length { 0 };
|
||||||
|
|
||||||
// read whatever junk there is before talking to the terminal
|
// Read whatever junk there is before talking to the terminal
|
||||||
// and insert them later when we're reading user input
|
// and insert them later when we're reading user input.
|
||||||
bool more_junk_to_read { false };
|
bool more_junk_to_read { false };
|
||||||
timeval timeout { 0, 0 };
|
timeval timeout { 0, 0 };
|
||||||
fd_set readfds;
|
fd_set readfds;
|
||||||
|
@ -1311,7 +1309,7 @@ bool Editor::should_break_token(Vector<u32, 1024>& buffer, size_t index)
|
||||||
|
|
||||||
void Editor::remove_at_index(size_t index)
|
void Editor::remove_at_index(size_t index)
|
||||||
{
|
{
|
||||||
// see if we have any anchored styles, and reposition them if needed
|
// See if we have any anchored styles, and reposition them if needed.
|
||||||
readjust_anchored_styles(index, ModificationKind::Removal);
|
readjust_anchored_styles(index, ModificationKind::Removal);
|
||||||
m_buffer.remove(index);
|
m_buffer.remove(index);
|
||||||
}
|
}
|
||||||
|
@ -1331,21 +1329,21 @@ void Editor::readjust_anchored_styles(size_t hint_index, ModificationKind modifi
|
||||||
for (auto& end_entry : start_entry.value) {
|
for (auto& end_entry : start_entry.value) {
|
||||||
if (forced_removal) {
|
if (forced_removal) {
|
||||||
if (start_entry.key <= hint_index && end_entry.key > hint_index) {
|
if (start_entry.key <= hint_index && end_entry.key > hint_index) {
|
||||||
// remove any overlapping regions
|
// Remove any overlapping regions.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (start_entry.key >= hint_index) {
|
if (start_entry.key >= hint_index) {
|
||||||
if (start_entry.key == hint_index && end_entry.key == hint_index + 1 && modification == ModificationKind::Removal) {
|
if (start_entry.key == hint_index && end_entry.key == hint_index + 1 && modification == ModificationKind::Removal) {
|
||||||
// remove the anchor, as all its text was wiped
|
// Remove the anchor, as all its text was wiped.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// shift everything
|
// Shift everything.
|
||||||
anchors_to_relocate.append({ { start_entry.key, end_entry.key, Span::Mode::CodepointOriented }, { start_entry.key + index_shift, end_entry.key + index_shift, Span::Mode::CodepointOriented }, end_entry.value });
|
anchors_to_relocate.append({ { start_entry.key, end_entry.key, Span::Mode::CodepointOriented }, { start_entry.key + index_shift, end_entry.key + index_shift, Span::Mode::CodepointOriented }, end_entry.value });
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (end_entry.key > hint_index) {
|
if (end_entry.key > hint_index) {
|
||||||
// shift just the end
|
// Shift just the end.
|
||||||
anchors_to_relocate.append({ { start_entry.key, end_entry.key, Span::Mode::CodepointOriented }, { start_entry.key, end_entry.key + index_shift, Span::Mode::CodepointOriented }, end_entry.value });
|
anchors_to_relocate.append({ { start_entry.key, end_entry.key, Span::Mode::CodepointOriented }, { start_entry.key, end_entry.key + index_shift, Span::Mode::CodepointOriented }, end_entry.value });
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1355,7 +1353,7 @@ void Editor::readjust_anchored_styles(size_t hint_index, ModificationKind modifi
|
||||||
|
|
||||||
m_anchored_spans_ending.clear();
|
m_anchored_spans_ending.clear();
|
||||||
m_anchored_spans_starting.clear();
|
m_anchored_spans_starting.clear();
|
||||||
// pass over the relocations and update the stale entries
|
// Pass over the relocations and update the stale entries.
|
||||||
for (auto& relocation : anchors_to_relocate) {
|
for (auto& relocation : anchors_to_relocate) {
|
||||||
stylize(relocation.new_span, relocation.style);
|
stylize(relocation.new_span, relocation.style);
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,8 +109,8 @@ public:
|
||||||
Function<void()> on_interrupt_handled;
|
Function<void()> on_interrupt_handled;
|
||||||
Function<void(Editor&)> on_display_refresh;
|
Function<void(Editor&)> on_display_refresh;
|
||||||
|
|
||||||
// FIXME: we will have to kindly ask our instantiators to set our signal handlers
|
// FIXME: we will have to kindly ask our instantiators to set our signal handlers,
|
||||||
// since we can not do this cleanly ourselves (signal() limitation: cannot give member functions)
|
// since we can not do this cleanly ourselves. (signal() limitation: cannot give member functions)
|
||||||
void interrupted()
|
void interrupted()
|
||||||
{
|
{
|
||||||
if (m_is_editing)
|
if (m_is_editing)
|
||||||
|
@ -124,7 +124,7 @@ public:
|
||||||
String line() const { return line(m_buffer.size()); }
|
String line() const { return line(m_buffer.size()); }
|
||||||
String line(size_t up_to_index) const;
|
String line(size_t up_to_index) const;
|
||||||
|
|
||||||
// only makes sense inside a char_input callback or on_* callback
|
// Only makes sense inside a character_input callback or on_* callback.
|
||||||
void set_prompt(const String& prompt)
|
void set_prompt(const String& prompt)
|
||||||
{
|
{
|
||||||
if (m_cached_prompt_valid)
|
if (m_cached_prompt_valid)
|
||||||
|
@ -291,7 +291,7 @@ private:
|
||||||
size_t m_prompt_lines_at_suggestion_initiation { 0 };
|
size_t m_prompt_lines_at_suggestion_initiation { 0 };
|
||||||
bool m_cached_prompt_valid { false };
|
bool m_cached_prompt_valid { false };
|
||||||
|
|
||||||
// exact position before our prompt in the terminal
|
// Exact position before our prompt in the terminal.
|
||||||
size_t m_origin_x { 0 };
|
size_t m_origin_x { 0 };
|
||||||
size_t m_origin_y { 0 };
|
size_t m_origin_y { 0 };
|
||||||
|
|
||||||
|
@ -311,7 +311,7 @@ private:
|
||||||
|
|
||||||
HashMap<char, NonnullOwnPtr<KeyCallback>> m_key_callbacks;
|
HashMap<char, NonnullOwnPtr<KeyCallback>> m_key_callbacks;
|
||||||
|
|
||||||
// TODO: handle signals internally
|
// TODO: handle signals internally.
|
||||||
struct termios m_termios, m_default_termios;
|
struct termios m_termios, m_default_termios;
|
||||||
bool m_was_interrupted { false };
|
bool m_was_interrupted { false };
|
||||||
bool m_was_resized { false };
|
bool m_was_resized { false };
|
||||||
|
|
|
@ -124,7 +124,7 @@ public:
|
||||||
static constexpr ItalicTag Italic {};
|
static constexpr ItalicTag Italic {};
|
||||||
static constexpr AnchoredTag Anchored {};
|
static constexpr AnchoredTag Anchored {};
|
||||||
|
|
||||||
// prepare for the horror of templates
|
// Prepare for the horror of templates.
|
||||||
template<typename T, typename... Rest>
|
template<typename T, typename... Rest>
|
||||||
Style(const T& style_arg, Rest... rest)
|
Style(const T& style_arg, Rest... rest)
|
||||||
: Style(rest...)
|
: Style(rest...)
|
||||||
|
|
|
@ -148,15 +148,15 @@ SuggestionManager::CompletionAttemptResult SuggestionManager::attempt_completion
|
||||||
set_current_suggestion_initiation_index(initiation_start_index);
|
set_current_suggestion_initiation_index(initiation_start_index);
|
||||||
|
|
||||||
if (mode == CompletePrefix) {
|
if (mode == CompletePrefix) {
|
||||||
// only auto-complete *if possible*
|
// Only auto-complete *if possible*.
|
||||||
if (can_complete) {
|
if (can_complete) {
|
||||||
result.insert.append(suggestion.text_view.substring_view(m_next_suggestion_invariant_offset, m_largest_common_suggestion_prefix_length - m_next_suggestion_invariant_offset));
|
result.insert.append(suggestion.text_view.substring_view(m_next_suggestion_invariant_offset, m_largest_common_suggestion_prefix_length - m_next_suggestion_invariant_offset));
|
||||||
m_last_shown_suggestion_display_length = m_largest_common_suggestion_prefix_length;
|
m_last_shown_suggestion_display_length = m_largest_common_suggestion_prefix_length;
|
||||||
// do not increment the suggestion index, as the first tab should only be a *peek*
|
// Do not increment the suggestion index, as the first tab should only be a *peek*.
|
||||||
if (m_suggestions.size() == 1) {
|
if (m_suggestions.size() == 1) {
|
||||||
// if there's one suggestion, commit and forget
|
// If there's one suggestion, commit and forget.
|
||||||
result.new_completion_mode = DontComplete;
|
result.new_completion_mode = DontComplete;
|
||||||
// add in the trivia of the last selected suggestion
|
// Add in the trivia of the last selected suggestion.
|
||||||
result.insert.append(suggestion.trivia_view);
|
result.insert.append(suggestion.trivia_view);
|
||||||
m_last_shown_suggestion_display_length = 0;
|
m_last_shown_suggestion_display_length = 0;
|
||||||
result.style_to_apply = suggestion.style;
|
result.style_to_apply = suggestion.style;
|
||||||
|
@ -171,7 +171,7 @@ SuggestionManager::CompletionAttemptResult SuggestionManager::attempt_completion
|
||||||
m_last_shown_suggestion = String::empty();
|
m_last_shown_suggestion = String::empty();
|
||||||
} else {
|
} else {
|
||||||
result.insert.append(suggestion.text_view.substring_view(m_next_suggestion_invariant_offset, suggestion.text_view.length() - m_next_suggestion_invariant_offset));
|
result.insert.append(suggestion.text_view.substring_view(m_next_suggestion_invariant_offset, suggestion.text_view.length() - m_next_suggestion_invariant_offset));
|
||||||
// add in the trivia of the last selected suggestion
|
// Add in the trivia of the last selected suggestion.
|
||||||
result.insert.append(suggestion.trivia_view);
|
result.insert.append(suggestion.trivia_view);
|
||||||
m_last_shown_suggestion_display_length += suggestion.trivia_view.length();
|
m_last_shown_suggestion_display_length += suggestion.trivia_view.length();
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
namespace Line {
|
namespace Line {
|
||||||
|
|
||||||
// FIXME: These objects are pretty heavy since they store two copies of text
|
// FIXME: These objects are pretty heavy since they store two copies of text
|
||||||
// somehow get rid of one
|
// somehow get rid of one.
|
||||||
struct CompletionSuggestion {
|
struct CompletionSuggestion {
|
||||||
private:
|
private:
|
||||||
struct ForSearchTag {
|
struct ForSearchTag {
|
||||||
|
@ -44,7 +44,7 @@ private:
|
||||||
public:
|
public:
|
||||||
static constexpr ForSearchTag ForSearch {};
|
static constexpr ForSearchTag ForSearch {};
|
||||||
|
|
||||||
// intentionally not explicit (allows suggesting bare strings)
|
// Intentionally not explicit. (To allow suggesting bare strings)
|
||||||
CompletionSuggestion(const String& completion)
|
CompletionSuggestion(const String& completion)
|
||||||
: CompletionSuggestion(completion, "", {})
|
: CompletionSuggestion(completion, "", {})
|
||||||
{
|
{
|
||||||
|
|
|
@ -55,8 +55,8 @@ void XtermSuggestionDisplay::display(const SuggestionManager& manager)
|
||||||
auto max_line_count = (m_prompt_length + longest_suggestion_length + m_num_columns - 1) / m_num_columns;
|
auto max_line_count = (m_prompt_length + longest_suggestion_length + m_num_columns - 1) / m_num_columns;
|
||||||
if (longest_suggestion_length >= m_num_columns - 2) {
|
if (longest_suggestion_length >= m_num_columns - 2) {
|
||||||
spans_entire_line = true;
|
spans_entire_line = true;
|
||||||
// we should make enough space for the biggest entry in
|
// We should make enough space for the biggest entry in
|
||||||
// the suggestion list to fit in the prompt line
|
// the suggestion list to fit in the prompt line.
|
||||||
auto start = max_line_count - m_prompt_lines_at_suggestion_initiation;
|
auto start = max_line_count - m_prompt_lines_at_suggestion_initiation;
|
||||||
for (size_t i = start; i < max_line_count; ++i) {
|
for (size_t i = start; i < max_line_count; ++i) {
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
|
@ -70,7 +70,7 @@ void XtermSuggestionDisplay::display(const SuggestionManager& manager)
|
||||||
if (m_pages.is_empty()) {
|
if (m_pages.is_empty()) {
|
||||||
size_t num_printed = 0;
|
size_t num_printed = 0;
|
||||||
size_t lines_used = 1;
|
size_t lines_used = 1;
|
||||||
// cache the pages
|
// Cache the pages.
|
||||||
manager.set_start_index(0);
|
manager.set_start_index(0);
|
||||||
size_t page_start = 0;
|
size_t page_start = 0;
|
||||||
manager.for_each_suggestion([&](auto& suggestion, auto index) {
|
manager.for_each_suggestion([&](auto& suggestion, auto index) {
|
||||||
|
@ -95,7 +95,7 @@ void XtermSuggestionDisplay::display(const SuggestionManager& manager)
|
||||||
|
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
});
|
});
|
||||||
// last page
|
// Append the last page.
|
||||||
m_pages.append({ page_start, manager.count() });
|
m_pages.append({ page_start, manager.count() });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,12 +113,12 @@ void XtermSuggestionDisplay::display(const SuggestionManager& manager)
|
||||||
num_printed = 0;
|
num_printed = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// show just enough suggestions to fill up the screen
|
// Show just enough suggestions to fill up the screen
|
||||||
// without moving the prompt out of view
|
// without moving the prompt out of view.
|
||||||
if (lines_used + m_prompt_lines_at_suggestion_initiation >= m_num_lines)
|
if (lines_used + m_prompt_lines_at_suggestion_initiation >= m_num_lines)
|
||||||
return IterationDecision::Break;
|
return IterationDecision::Break;
|
||||||
|
|
||||||
// only apply colour to the selection if something is *actually* added to the buffer
|
// Only apply colour to the selection if something is *actually* added to the buffer.
|
||||||
if (manager.is_current_suggestion_complete() && index == manager.next_index()) {
|
if (manager.is_current_suggestion_complete() && index == manager.next_index()) {
|
||||||
VT::apply_style({ Style::Foreground(Style::XtermColor::Blue) });
|
VT::apply_style({ Style::Foreground(Style::XtermColor::Blue) });
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
@ -141,7 +141,7 @@ void XtermSuggestionDisplay::display(const SuggestionManager& manager)
|
||||||
|
|
||||||
m_lines_used_for_last_suggestions = lines_used;
|
m_lines_used_for_last_suggestions = lines_used;
|
||||||
|
|
||||||
// if we filled the screen, move back the origin
|
// If we filled the screen, move back the origin.
|
||||||
if (m_origin_x + lines_used >= m_num_lines) {
|
if (m_origin_x + lines_used >= m_num_lines) {
|
||||||
m_origin_x = m_num_lines - lines_used;
|
m_origin_x = m_num_lines - lines_used;
|
||||||
}
|
}
|
||||||
|
@ -152,7 +152,7 @@ void XtermSuggestionDisplay::display(const SuggestionManager& manager)
|
||||||
auto string = String::format("%c page %d of %d %c", left_arrow, page_index + 1, m_pages.size(), right_arrow);
|
auto string = String::format("%c page %d of %d %c", left_arrow, page_index + 1, m_pages.size(), right_arrow);
|
||||||
|
|
||||||
if (string.length() > m_num_columns - 1) {
|
if (string.length() > m_num_columns - 1) {
|
||||||
// this would overflow into the next line, so just don't print an indicator
|
// This would overflow into the next line, so just don't print an indicator.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue