Teach the reader fast path about self-insert-notfirst

This teaches the reader fast-path to use self-insert-notfirst, allowing
it to handle spaces. This greatly increases the performance of paste by
reducing redraws.

Fixes #6603. Somewhat improves #6704
This commit is contained in:
ridiculousfish 2020-03-04 14:47:18 -08:00
parent 29c2bce704
commit f73e324618

View file

@ -2525,8 +2525,6 @@ static bool text_ends_in_comment(const wcstring &text) {
/// \return true if an event is a normal character that should be inserted into the buffer. /// \return true if an event is a normal character that should be inserted into the buffer.
static bool event_is_normal_char(const char_event_t &evt) { static bool event_is_normal_char(const char_event_t &evt) {
if (!evt.is_char()) return false; if (!evt.is_char()) return false;
// Non-normal insertion styles are treated as a non-normal character.
if (evt.input_style != char_event_t::style_normal) return false;
auto c = evt.get_char(); auto c = evt.get_char();
return !fish_reserved_codepoint(c) && c > 31 && c != 127; return !fish_reserved_codepoint(c) && c > 31 && c != 127;
} }
@ -2561,47 +2559,36 @@ struct readline_loop_state_t {
/// Read normal characters, inserting them into the command line. /// Read normal characters, inserting them into the command line.
/// \return the next unhandled event. /// \return the next unhandled event.
maybe_t<char_event_t> reader_data_t::read_normal_chars(readline_loop_state_t &rls) { maybe_t<char_event_t> reader_data_t::read_normal_chars(readline_loop_state_t &rls) {
maybe_t<char_event_t> event_needing_handling = inputter.readch(); maybe_t<char_event_t> event_needing_handling{};
wcstring accumulated_chars;
if (!event_is_normal_char(*event_needing_handling) || !can_read(STDIN_FILENO))
return event_needing_handling;
// This is a normal character input.
// We are going to handle it directly, accumulating more.
char_event_t evt = event_needing_handling.acquire();
size_t limit = std::min(rls.nchars - command_line.size(), READAHEAD_MAX); size_t limit = std::min(rls.nchars - command_line.size(), READAHEAD_MAX);
while (accumulated_chars.size() < limit) {
wchar_t arr[READAHEAD_MAX + 1] = {}; bool allow_commands = (accumulated_chars.empty());
arr[0] = evt.get_char(); auto evt = inputter.readch(allow_commands);
if (!event_is_normal_char(evt) || !can_read(STDIN_FILENO)) {
for (size_t i = 1; i < limit; ++i) { event_needing_handling = std::move(evt);
if (!can_read(0)) {
break; break;
} } else if (evt.input_style == char_event_t::style_notfirst && accumulated_chars.empty() &&
// Only allow commands on the first key; otherwise, we might have data we active_edit_line()->position() == 0) {
// need to insert on the commandline that the command might need to be able // The cursor is at the beginning and nothing is accumulated, so skip this character.
// to see. continue;
auto next_event = inputter.readch(false);
if (event_is_normal_char(next_event)) {
arr[i] = next_event.get_char();
} else { } else {
// We need to process this in the outer loop. accumulated_chars.push_back(evt.get_char());
assert(!event_needing_handling && "Should not have an unhandled event");
event_needing_handling = next_event;
break;
} }
} }
editable_line_t *el = active_edit_line(); if (!accumulated_chars.empty()) {
insert_string(el, arr); editable_line_t *el = active_edit_line();
insert_string(el, accumulated_chars);
// End paging upon inserting into the normal command line. // End paging upon inserting into the normal command line.
if (el == &command_line) { if (el == &command_line) {
clear_pager(); clear_pager();
}
// Since we handled a normal character, we don't have a last command.
rls.last_cmd.reset();
} }
// Since we handled a normal character, we don't have a last command.
rls.last_cmd.reset();
return event_needing_handling; return event_needing_handling;
} }