mirror of
https://github.com/nushell/reedline.git
synced 2024-10-27 01:45:51 +03:00
Avoid consuming CPU when waiting for input. (#651)
When reading input, start by calling `event::read`, which efficiently blocks until input arrives, rather than polling for input every 100 milliseconds. This preserves the existing `POLL_WAIT` polling behavior by moving the poll after the first `read` call returns. Fixes #521.
This commit is contained in:
parent
973dbb5f5f
commit
2b6790c14b
127
src/engine.rs
127
src/engine.rs
@ -725,77 +725,74 @@ impl Reedline {
|
||||
}
|
||||
}
|
||||
|
||||
if event::poll(Duration::from_millis(100))? {
|
||||
let mut latest_resize = None;
|
||||
let mut latest_resize = None;
|
||||
loop {
|
||||
match event::read()? {
|
||||
Event::Resize(x, y) => {
|
||||
latest_resize = Some((x, y));
|
||||
}
|
||||
enter @ Event::Key(KeyEvent {
|
||||
code: KeyCode::Enter,
|
||||
modifiers: KeyModifiers::NONE,
|
||||
..
|
||||
}) => {
|
||||
let enter = ReedlineRawEvent::convert_from(enter);
|
||||
if let Some(enter) = enter {
|
||||
crossterm_events.push(enter);
|
||||
// Break early to check if the input is complete and
|
||||
// can be send to the hosting application. If
|
||||
// multiple complete entries are submitted, events
|
||||
// are still in the crossterm queue for us to
|
||||
// process.
|
||||
paste_enter_state = crossterm_events.len() > EVENTS_THRESHOLD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
x => {
|
||||
let raw_event = ReedlineRawEvent::convert_from(x);
|
||||
if let Some(evt) = raw_event {
|
||||
crossterm_events.push(evt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// There could be multiple events queued up!
|
||||
// pasting text, resizes, blocking this thread (e.g. during debugging)
|
||||
// We should be able to handle all of them as quickly as possible without causing unnecessary output steps.
|
||||
while event::poll(Duration::from_millis(POLL_WAIT))? {
|
||||
match event::read()? {
|
||||
Event::Resize(x, y) => {
|
||||
latest_resize = Some((x, y));
|
||||
}
|
||||
enter @ Event::Key(KeyEvent {
|
||||
code: KeyCode::Enter,
|
||||
modifiers: KeyModifiers::NONE,
|
||||
..
|
||||
}) => {
|
||||
let enter = ReedlineRawEvent::convert_from(enter);
|
||||
match enter {
|
||||
Some(enter) => {
|
||||
crossterm_events.push(enter);
|
||||
// Break early to check if the input is complete and
|
||||
// can be send to the hosting application. If
|
||||
// multiple complete entries are submitted, events
|
||||
// are still in the crossterm queue for us to
|
||||
// process.
|
||||
paste_enter_state = crossterm_events.len() > EVENTS_THRESHOLD;
|
||||
break;
|
||||
}
|
||||
None => continue,
|
||||
}
|
||||
}
|
||||
x => {
|
||||
let raw_event = ReedlineRawEvent::convert_from(x);
|
||||
match raw_event {
|
||||
Some(evt) => crossterm_events.push(evt),
|
||||
None => continue,
|
||||
}
|
||||
}
|
||||
if !event::poll(Duration::from_millis(POLL_WAIT))? {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some((x, y)) = latest_resize {
|
||||
reedline_events.push(ReedlineEvent::Resize(x, y));
|
||||
}
|
||||
|
||||
// Accelerate pasted text by fusing `EditCommand`s
|
||||
//
|
||||
// (Text should only be `EditCommand::InsertChar`s)
|
||||
let mut last_edit_commands = None;
|
||||
for event in crossterm_events.drain(..) {
|
||||
match (&mut last_edit_commands, self.edit_mode.parse_event(event)) {
|
||||
(None, ReedlineEvent::Edit(ec)) => {
|
||||
last_edit_commands = Some(ec);
|
||||
}
|
||||
(None, other_event) => {
|
||||
reedline_events.push(other_event);
|
||||
}
|
||||
(Some(ref mut last_ecs), ReedlineEvent::Edit(ec)) => {
|
||||
last_ecs.extend(ec);
|
||||
}
|
||||
(ref mut a @ Some(_), other_event) => {
|
||||
reedline_events.push(ReedlineEvent::Edit(a.take().unwrap()));
|
||||
|
||||
reedline_events.push(other_event);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some((x, y)) = latest_resize {
|
||||
reedline_events.push(ReedlineEvent::Resize(x, y));
|
||||
}
|
||||
|
||||
// Accelerate pasted text by fusing `EditCommand`s
|
||||
//
|
||||
// (Text should only be `EditCommand::InsertChar`s)
|
||||
let mut last_edit_commands = None;
|
||||
for event in crossterm_events.drain(..) {
|
||||
match (&mut last_edit_commands, self.edit_mode.parse_event(event)) {
|
||||
(None, ReedlineEvent::Edit(ec)) => {
|
||||
last_edit_commands = Some(ec);
|
||||
}
|
||||
(None, other_event) => {
|
||||
reedline_events.push(other_event);
|
||||
}
|
||||
(Some(ref mut last_ecs), ReedlineEvent::Edit(ec)) => {
|
||||
last_ecs.extend(ec);
|
||||
}
|
||||
(ref mut a @ Some(_), other_event) => {
|
||||
reedline_events.push(ReedlineEvent::Edit(a.take().unwrap()));
|
||||
|
||||
reedline_events.push(other_event);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(ec) = last_edit_commands {
|
||||
reedline_events.push(ReedlineEvent::Edit(ec));
|
||||
}
|
||||
};
|
||||
}
|
||||
if let Some(ec) = last_edit_commands {
|
||||
reedline_events.push(ReedlineEvent::Edit(ec));
|
||||
}
|
||||
|
||||
for event in reedline_events.drain(..) {
|
||||
match self.handle_event(prompt, event)? {
|
||||
|
Loading…
Reference in New Issue
Block a user