diff --git a/CHANGELOG.md b/CHANGELOG.md index 42544243..cf9a97c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,9 @@ ## [Unreleased] -- Pressing Ctrl+D now cancels the prompt. -- Add support for `h` and `l` bindings when vim_mode is enabled on MultiSelect prompts, clearing or selecting all options respectively. +- Pressing Ctrl+D now cancels the prompt. Thanks @mikecvet for the PR! +- Add support for `h` and `l` bindings when vim_mode is enabled on MultiSelect prompts, clearing or selecting all options respectively. Thanks @afh for the PR! +- Fix render issue [#233](https://github.com/mikaelmello/inquire/issues/233) where cursor positioning at the end of a prompt was incorrect. Thanks @msrd0 and @Sydonian for reporting! ## [0.7.1] - 2024-03-10 diff --git a/inquire/src/prompts/prompt.rs b/inquire/src/prompts/prompt.rs index 65e80980..7313fa82 100644 --- a/inquire/src/prompts/prompt.rs +++ b/inquire/src/prompts/prompt.rs @@ -123,7 +123,7 @@ where if last_handle.needs_redraw() { backend.frame_setup()?; self.render(backend)?; - backend.frame_finish()?; + backend.frame_finish(false)?; last_handle = ActionResult::Clean; } @@ -144,7 +144,7 @@ where if pre_cancel_result { backend.frame_setup()?; backend.render_canceled_prompt(self.message())?; - backend.frame_finish()?; + backend.frame_finish(true)?; return Err(InquireError::OperationCanceled); } @@ -160,7 +160,7 @@ where backend.frame_setup()?; backend.render_prompt_with_answer(self.message(), &formatted)?; - backend.frame_finish()?; + backend.frame_finish(true)?; Ok(final_answer) } diff --git a/inquire/src/ui/backend.rs b/inquire/src/ui/backend.rs index a6baf917..579683a6 100644 --- a/inquire/src/ui/backend.rs +++ b/inquire/src/ui/backend.rs @@ -14,7 +14,7 @@ use super::{frame_renderer::FrameRenderer, InputReader}; pub trait CommonBackend: InputReader { fn frame_setup(&mut self) -> Result<()>; - fn frame_finish(&mut self) -> Result<()>; + fn frame_finish(&mut self, is_last_frame: bool) -> Result<()>; fn render_canceled_prompt(&mut self, prompt: &str) -> Result<()>; fn render_prompt_with_answer(&mut self, prompt: &str, answer: &str) -> Result<()>; @@ -247,8 +247,8 @@ where self.frame_renderer.start_frame() } - fn frame_finish(&mut self) -> Result<()> { - self.frame_renderer.finish_current_frame() + fn frame_finish(&mut self, is_last_frame: bool) -> Result<()> { + self.frame_renderer.finish_current_frame(is_last_frame) } fn render_canceled_prompt(&mut self, prompt: &str) -> Result<()> { @@ -689,6 +689,7 @@ pub(crate) mod test { min_date: Option, max_date: Option, }, + PromptEnd, } #[derive(Default, Debug, Clone)] @@ -751,7 +752,11 @@ pub(crate) mod test { Ok(()) } - fn frame_finish(&mut self) -> std::io::Result<()> { + fn frame_finish(&mut self, is_last_frame: bool) -> std::io::Result<()> { + if is_last_frame { + self.push_token(Token::PromptEnd); + } + if let Some(frame) = self.cur_frame.take() { self.frames.push(frame); } else { diff --git a/inquire/src/ui/frame_renderer.rs b/inquire/src/ui/frame_renderer.rs index 073262fc..2a08d5f8 100644 --- a/inquire/src/ui/frame_renderer.rs +++ b/inquire/src/ui/frame_renderer.rs @@ -262,7 +262,7 @@ where Ok(()) } - pub fn finish_current_frame(&mut self) -> io::Result<()> { + pub fn finish_current_frame(&mut self, add_empty_line: bool) -> io::Result<()> { let (last_rendered_frame, mut current_frame) = match std::mem::take(&mut self.state) { RenderState::Rendered(_) | RenderState::Initial => { return Ok(()); @@ -280,7 +280,7 @@ where current_frame.frame_size.height(), ); - self.terminal.cursor_hide()?; + //self.terminal.cursor_hide()?; self.move_cursor_to(Position { row: 0, col: 0 })?; for i in 0..rows_to_iterate { @@ -321,6 +321,11 @@ where } } + if add_empty_line { + self.terminal.write("\n")?; + self.cursor_position.row += 1; + } + if let Some(expected_cursor_position) = current_frame.expected_cursor_position { self.move_cursor_to(expected_cursor_position)?; }