diff --git a/README.md b/README.md index f60f3204..0101763d 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ let mut line_editor = Reedline::create(); let prompt = DefaultPrompt::default(); loop { - let sig = line_editor.read_line(&prompt); + let sig = line_editor.read_line(&prompt, false); match sig { Ok(Signal::Success(buffer)) => { println!("We processed: {}", buffer); diff --git a/examples/basic.rs b/examples/basic.rs index 2c04b75b..f5dd46ee 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -12,7 +12,7 @@ fn main() -> io::Result<()> { let prompt = DefaultPrompt::default(); loop { - let sig = line_editor.read_line(&prompt)?; + let sig = line_editor.read_line(&prompt, false)?; match sig { Signal::Success(buffer) => { println!("We processed: {buffer}"); diff --git a/examples/completions.rs b/examples/completions.rs index 164b5c30..78752d4e 100644 --- a/examples/completions.rs +++ b/examples/completions.rs @@ -81,7 +81,7 @@ fn main() -> io::Result<()> { let prompt = DefaultPrompt::default(); loop { - let sig = line_editor.read_line(&prompt)?; + let sig = line_editor.read_line(&prompt, false)?; match sig { Signal::Success(buffer) => { println!("We processed: {buffer}"); diff --git a/examples/custom_prompt.rs b/examples/custom_prompt.rs index fc9b1034..abc1656b 100644 --- a/examples/custom_prompt.rs +++ b/examples/custom_prompt.rs @@ -61,7 +61,7 @@ fn main() -> io::Result<()> { let prompt = CustomPrompt(Cell::new(0), "Custom Prompt"); loop { - let sig = line_editor.read_line(&prompt)?; + let sig = line_editor.read_line(&prompt, false)?; match sig { Signal::Success(buffer) => { println!("We processed: {buffer}"); diff --git a/examples/cwd_aware_hinter.rs b/examples/cwd_aware_hinter.rs index b8b9145d..4044b6c0 100644 --- a/examples/cwd_aware_hinter.rs +++ b/examples/cwd_aware_hinter.rs @@ -71,7 +71,7 @@ fn main() -> io::Result<()> { } else { std::env::set_current_dir(&home_dir).unwrap(); } - let sig = line_editor.read_line(&prompt)?; + let sig = line_editor.read_line(&prompt, false)?; match sig { Signal::Success(buffer) => { println!("We processed: {buffer}"); diff --git a/examples/demo.rs b/examples/demo.rs index 44e7b921..6fec5b1b 100644 --- a/examples/demo.rs +++ b/examples/demo.rs @@ -134,7 +134,7 @@ fn main() -> reedline::Result<()> { let prompt = DefaultPrompt::default(); loop { - let sig = line_editor.read_line(&prompt); + let sig = line_editor.read_line(&prompt, false); match sig { Ok(Signal::CtrlD) => { diff --git a/examples/external_printer.rs b/examples/external_printer.rs index 633a1238..22f636ca 100644 --- a/examples/external_printer.rs +++ b/examples/external_printer.rs @@ -42,7 +42,7 @@ fn main() { let prompt = DefaultPrompt::default(); loop { - if let Ok(sig) = line_editor.read_line(&prompt) { + if let Ok(sig) = line_editor.read_line(&prompt, false) { match sig { Signal::Success(buffer) => { println!("We processed: {buffer}"); diff --git a/examples/highlighter.rs b/examples/highlighter.rs index 3edeb974..82616b7c 100644 --- a/examples/highlighter.rs +++ b/examples/highlighter.rs @@ -17,7 +17,7 @@ fn main() -> io::Result<()> { let prompt = DefaultPrompt::default(); loop { - let sig = line_editor.read_line(&prompt)?; + let sig = line_editor.read_line(&prompt, false)?; match sig { Signal::Success(buffer) => { println!("We processed: {buffer}"); diff --git a/examples/hinter.rs b/examples/hinter.rs index 9ed4ba2d..7eebade8 100644 --- a/examples/hinter.rs +++ b/examples/hinter.rs @@ -17,7 +17,7 @@ fn main() -> io::Result<()> { let prompt = DefaultPrompt::default(); loop { - let sig = line_editor.read_line(&prompt)?; + let sig = line_editor.read_line(&prompt, false)?; match sig { Signal::Success(buffer) => { println!("We processed: {buffer}"); diff --git a/examples/history.rs b/examples/history.rs index c709bce9..c9a6714f 100644 --- a/examples/history.rs +++ b/examples/history.rs @@ -19,7 +19,7 @@ fn main() -> io::Result<()> { let prompt = DefaultPrompt::default(); loop { - let sig = line_editor.read_line(&prompt)?; + let sig = line_editor.read_line(&prompt, false)?; match sig { Signal::Success(buffer) => { println!("We processed: {buffer}"); diff --git a/examples/ide_completions.rs b/examples/ide_completions.rs index a209a167..dd8fcda6 100644 --- a/examples/ide_completions.rs +++ b/examples/ide_completions.rs @@ -117,7 +117,7 @@ fn main() -> io::Result<()> { let prompt = DefaultPrompt::default(); loop { - let sig = line_editor.read_line(&prompt)?; + let sig = line_editor.read_line(&prompt, false)?; match sig { Signal::Success(buffer) => { println!("We processed: {buffer}"); diff --git a/examples/transient_prompt.rs b/examples/transient_prompt.rs index d3aaa390..cc44cf23 100644 --- a/examples/transient_prompt.rs +++ b/examples/transient_prompt.rs @@ -118,7 +118,7 @@ fn main() -> io::Result<()> { let prompt = DefaultPrompt::default(); loop { - let sig = line_editor.read_line(&prompt)?; + let sig = line_editor.read_line(&prompt, false)?; match sig { Signal::Success(buffer) => { println!("We processed: {buffer}"); diff --git a/examples/validator.rs b/examples/validator.rs index 2e7ca4f9..6efbdb0b 100644 --- a/examples/validator.rs +++ b/examples/validator.rs @@ -27,7 +27,7 @@ fn main() -> io::Result<()> { let prompt = DefaultPrompt::default(); loop { - let sig = line_editor.read_line(&prompt)?; + let sig = line_editor.read_line(&prompt, false)?; match sig { Signal::Success(buffer) => { println!("We processed: {buffer}"); diff --git a/src/core_editor/line_buffer.rs b/src/core_editor/line_buffer.rs index e5c34968..07eaa035 100644 --- a/src/core_editor/line_buffer.rs +++ b/src/core_editor/line_buffer.rs @@ -163,7 +163,7 @@ impl LineBuffer { pub fn grapheme_left_index(&self) -> usize { self.lines[..self.insertion_point] .grapheme_indices(true) - .last() + .next_back() .map(|(i, _)| i) .unwrap_or(0) } @@ -213,7 +213,7 @@ impl LineBuffer { .unwrap_or_else(|| { self.lines .grapheme_indices(true) - .last() + .next_back() .map(|x| x.0) .unwrap_or(0) }) @@ -238,7 +238,7 @@ impl LineBuffer { .unwrap_or_else(|| { self.lines .grapheme_indices(true) - .last() + .next_back() .map(|x| x.0) .unwrap_or(0) }) @@ -272,7 +272,7 @@ impl LineBuffer { self.lines[..self.insertion_point] .split_word_bound_indices() .filter(|(_, word)| !is_whitespace_str(word)) - .last() + .next_back() .map(|(i, _)| i) .unwrap_or(0) } @@ -471,7 +471,7 @@ impl LineBuffer { let left_index = self.lines[..right_index] .split_word_bound_indices() .filter(|(_, word)| !is_whitespace_str(word)) - .last() + .next_back() .map(|(i, _)| i) .unwrap_or(0); diff --git a/src/engine.rs b/src/engine.rs index c08a27e5..a9cc2f68 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -88,7 +88,7 @@ enum InputMode { /// let mut line_editor = Reedline::create(); /// let prompt = DefaultPrompt::default(); /// -/// let out = line_editor.read_line(&prompt).unwrap(); +/// let out = line_editor.read_line(&prompt, false).unwrap(); /// match out { /// Signal::Success(content) => { /// // process content @@ -642,12 +642,12 @@ impl Reedline { /// /// Returns a [`std::io::Result`] in which the `Err` type is [`std::io::Result`] /// and the `Ok` variant wraps a [`Signal`] which handles user inputs. - pub fn read_line(&mut self, prompt: &dyn Prompt) -> Result { + pub fn read_line(&mut self, prompt: &dyn Prompt, immediately_execute: bool) -> Result { terminal::enable_raw_mode()?; self.bracketed_paste.enter(); self.kitty_protocol.enter(); - let result = self.read_line_helper(prompt); + let result = self.read_line_helper(prompt, immediately_execute); self.bracketed_paste.exit(); self.kitty_protocol.exit(); @@ -687,7 +687,11 @@ impl Reedline { /// Helper implementing the logic for [`Reedline::read_line()`] to be wrapped /// in a `raw_mode` context. - fn read_line_helper(&mut self, prompt: &dyn Prompt) -> Result { + fn read_line_helper( + &mut self, + prompt: &dyn Prompt, + immediately_execute: bool, + ) -> Result { self.painter .initialize_prompt_position(self.suspended_state.as_ref())?; if self.suspended_state.is_some() { @@ -734,30 +738,32 @@ impl Reedline { let mut events: Vec = vec![]; - // If the `external_printer` feature is enabled, we need to - // periodically yield so that external printers get a chance to - // print. Otherwise, we can just block until we receive an event. - #[cfg(feature = "external_printer")] - if event::poll(EXTERNAL_PRINTER_WAIT)? { + if !immediately_execute { + // If the `external_printer` feature is enabled, we need to + // periodically yield so that external printers get a chance to + // print. Otherwise, we can just block until we receive an event. + #[cfg(feature = "external_printer")] + if event::poll(EXTERNAL_PRINTER_WAIT)? { + events.push(crossterm::event::read()?); + } + #[cfg(not(feature = "external_printer"))] events.push(crossterm::event::read()?); - } - #[cfg(not(feature = "external_printer"))] - events.push(crossterm::event::read()?); - // Receive all events in the queue without blocking. Will stop when - // a line of input is completed. - while !completed(&events) && event::poll(Duration::from_millis(0))? { - events.push(crossterm::event::read()?); - } - - // If we believe there's text pasting or resizing going on, batch - // more events at the cost of a slight delay. - if events.len() > EVENTS_THRESHOLD - || events.iter().any(|e| matches!(e, Event::Resize(_, _))) - { - while !completed(&events) && event::poll(POLL_WAIT)? { + // a line of input is completed. + // Receive all events in the queue without blocking. Will stop when + while !completed(&events) && event::poll(Duration::from_millis(0))? { events.push(crossterm::event::read()?); } + + // If we believe there's text pasting or resizing going on, batch + // more events at the cost of a slight delay. + if events.len() > EVENTS_THRESHOLD + || events.iter().any(|e| matches!(e, Event::Resize(_, _))) + { + while !completed(&events) && event::poll(POLL_WAIT)? { + events.push(crossterm::event::read()?); + } + } } // Convert `Event` into `ReedlineEvent`. Also, fuse consecutive @@ -787,6 +793,9 @@ impl Reedline { if let Some((x, y)) = resize { reedline_events.push(ReedlineEvent::Resize(x, y)); } + if immediately_execute { + reedline_events.push(ReedlineEvent::Submit); + } // Handle reedline events. for event in reedline_events { diff --git a/src/lib.rs b/src/lib.rs index 35eccceb..45735f63 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,7 +19,7 @@ //! let prompt = DefaultPrompt::default(); //! //! loop { -//! let sig = line_editor.read_line(&prompt); +//! let sig = line_editor.read_line(&prompt, false); //! match sig { //! Ok(Signal::Success(buffer)) => { //! println!("We processed: {}", buffer);